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.net.Authenticator;
25 import java.net.PasswordAuthentication;
26 import java.security.MessageDigest;
27 import java.security.NoSuchAlgorithmException;
28 import java.sql.Connection;
29 import java.sql.DriverManager;
30 import java.sql.SQLException;
31 import java.sql.Statement;
32 import java.text.SimpleDateFormat;
33 import java.util.ArrayList;
34 import java.util.Calendar;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.Comparator;
38 import java.util.Date;
39 import java.util.GregorianCalendar;
40 import java.util.HashMap;
41 import java.util.Iterator;
42 import java.util.List;
43 import java.util.SortedMap;
44 import java.util.Vector;
46 import org.apache.thrift.TException;
47 import org.h2.tools.ChangeFileEncryption;
49 import com.evernote.edam.error.EDAMNotFoundException;
50 import com.evernote.edam.error.EDAMSystemException;
51 import com.evernote.edam.error.EDAMUserException;
52 import com.evernote.edam.notestore.NoteFilter;
53 import com.evernote.edam.notestore.NoteVersionId;
54 import com.evernote.edam.type.Data;
55 import com.evernote.edam.type.Note;
56 import com.evernote.edam.type.NoteAttributes;
57 import com.evernote.edam.type.Notebook;
58 import com.evernote.edam.type.Publishing;
59 import com.evernote.edam.type.QueryFormat;
60 import com.evernote.edam.type.Resource;
61 import com.evernote.edam.type.SavedSearch;
62 import com.evernote.edam.type.Tag;
63 import com.evernote.edam.type.User;
64 import com.trolltech.qt.QThread;
65 import com.trolltech.qt.core.QByteArray;
66 import com.trolltech.qt.core.QDateTime;
67 import com.trolltech.qt.core.QDir;
68 import com.trolltech.qt.core.QEvent;
69 import com.trolltech.qt.core.QFile;
70 import com.trolltech.qt.core.QFileInfo;
71 import com.trolltech.qt.core.QFileSystemWatcher;
72 import com.trolltech.qt.core.QIODevice;
73 import com.trolltech.qt.core.QIODevice.OpenModeFlag;
74 import com.trolltech.qt.core.QLocale;
75 import com.trolltech.qt.core.QModelIndex;
76 import com.trolltech.qt.core.QSize;
77 import com.trolltech.qt.core.QTemporaryFile;
78 import com.trolltech.qt.core.QTextCodec;
79 import com.trolltech.qt.core.QThreadPool;
80 import com.trolltech.qt.core.QTimer;
81 import com.trolltech.qt.core.QTranslator;
82 import com.trolltech.qt.core.QUrl;
83 import com.trolltech.qt.core.Qt;
84 import com.trolltech.qt.core.Qt.BGMode;
85 import com.trolltech.qt.core.Qt.ItemDataRole;
86 import com.trolltech.qt.core.Qt.SortOrder;
87 import com.trolltech.qt.core.Qt.WidgetAttribute;
88 import com.trolltech.qt.gui.QAbstractItemView;
89 import com.trolltech.qt.gui.QAbstractItemView.ScrollHint;
90 import com.trolltech.qt.gui.QAction;
91 import com.trolltech.qt.gui.QApplication;
92 import com.trolltech.qt.gui.QCloseEvent;
93 import com.trolltech.qt.gui.QColor;
94 import com.trolltech.qt.gui.QComboBox;
95 import com.trolltech.qt.gui.QComboBox.InsertPolicy;
96 import com.trolltech.qt.gui.QCursor;
97 import com.trolltech.qt.gui.QDesktopServices;
98 import com.trolltech.qt.gui.QDialog;
99 import com.trolltech.qt.gui.QFileDialog;
100 import com.trolltech.qt.gui.QFileDialog.AcceptMode;
101 import com.trolltech.qt.gui.QFileDialog.FileMode;
102 import com.trolltech.qt.gui.QGridLayout;
103 import com.trolltech.qt.gui.QHBoxLayout;
104 import com.trolltech.qt.gui.QIcon;
105 import com.trolltech.qt.gui.QImage;
106 import com.trolltech.qt.gui.QLabel;
107 import com.trolltech.qt.gui.QListWidget;
108 import com.trolltech.qt.gui.QMainWindow;
109 import com.trolltech.qt.gui.QMenu;
110 import com.trolltech.qt.gui.QMessageBox;
111 import com.trolltech.qt.gui.QMessageBox.StandardButton;
112 import com.trolltech.qt.gui.QPainter;
113 import com.trolltech.qt.gui.QPalette.ColorRole;
114 import com.trolltech.qt.gui.QPixmap;
115 import com.trolltech.qt.gui.QPrintDialog;
116 import com.trolltech.qt.gui.QPrinter;
117 import com.trolltech.qt.gui.QSizePolicy;
118 import com.trolltech.qt.gui.QSizePolicy.Policy;
119 import com.trolltech.qt.gui.QSpinBox;
120 import com.trolltech.qt.gui.QSplashScreen;
121 import com.trolltech.qt.gui.QSplitter;
122 import com.trolltech.qt.gui.QStatusBar;
123 import com.trolltech.qt.gui.QSystemTrayIcon;
124 import com.trolltech.qt.gui.QTableWidgetItem;
125 import com.trolltech.qt.gui.QTextEdit;
126 import com.trolltech.qt.gui.QToolBar;
127 import com.trolltech.qt.gui.QTreeWidgetItem;
128 import com.trolltech.qt.webkit.QWebPage.WebAction;
129 import com.trolltech.qt.webkit.QWebSettings;
131 import cx.fbn.nevernote.config.InitializationException;
132 import cx.fbn.nevernote.config.StartupConfig;
133 import cx.fbn.nevernote.dialog.AccountDialog;
134 import cx.fbn.nevernote.dialog.ConfigDialog;
135 import cx.fbn.nevernote.dialog.DBEncryptDialog;
136 import cx.fbn.nevernote.dialog.DatabaseLoginDialog;
137 import cx.fbn.nevernote.dialog.DatabaseStatus;
138 import cx.fbn.nevernote.dialog.FindDialog;
139 import cx.fbn.nevernote.dialog.LoginDialog;
140 import cx.fbn.nevernote.dialog.NotebookArchive;
141 import cx.fbn.nevernote.dialog.NotebookEdit;
142 import cx.fbn.nevernote.dialog.OnlineNoteHistory;
143 import cx.fbn.nevernote.dialog.PublishNotebook;
144 import cx.fbn.nevernote.dialog.SavedSearchEdit;
145 import cx.fbn.nevernote.dialog.SetIcon;
146 import cx.fbn.nevernote.dialog.ShareNotebook;
147 import cx.fbn.nevernote.dialog.StackNotebook;
148 import cx.fbn.nevernote.dialog.TagEdit;
149 import cx.fbn.nevernote.dialog.ThumbnailViewer;
150 import cx.fbn.nevernote.dialog.WatchFolder;
151 import cx.fbn.nevernote.gui.AttributeTreeWidget;
152 import cx.fbn.nevernote.gui.BrowserWindow;
153 import cx.fbn.nevernote.gui.DateAttributeFilterTable;
154 import cx.fbn.nevernote.gui.ExternalBrowse;
155 import cx.fbn.nevernote.gui.MainMenuBar;
156 import cx.fbn.nevernote.gui.NotebookTreeWidget;
157 import cx.fbn.nevernote.gui.SavedSearchTreeWidget;
158 import cx.fbn.nevernote.gui.TableView;
159 import cx.fbn.nevernote.gui.TagTreeWidget;
160 import cx.fbn.nevernote.gui.Thumbnailer;
161 import cx.fbn.nevernote.gui.TrashTreeWidget;
162 import cx.fbn.nevernote.gui.controls.QuotaProgressBar;
163 import cx.fbn.nevernote.sql.DatabaseConnection;
164 import cx.fbn.nevernote.sql.WatchFolderRecord;
165 import cx.fbn.nevernote.threads.IndexRunner;
166 import cx.fbn.nevernote.threads.SyncRunner;
167 import cx.fbn.nevernote.threads.ThumbnailRunner;
168 import cx.fbn.nevernote.utilities.AESEncrypter;
169 import cx.fbn.nevernote.utilities.ApplicationLogger;
170 import cx.fbn.nevernote.utilities.FileImporter;
171 import cx.fbn.nevernote.utilities.FileUtils;
172 import cx.fbn.nevernote.utilities.ListManager;
173 import cx.fbn.nevernote.utilities.SyncTimes;
174 import cx.fbn.nevernote.xml.ExportData;
175 import cx.fbn.nevernote.xml.ImportData;
176 import cx.fbn.nevernote.xml.NoteFormatter;
179 public class NeverNote extends QMainWindow{
181 QStatusBar statusBar; // Application status bar
183 DatabaseConnection conn;
185 MainMenuBar menuBar; // Main menu bar
186 FindDialog find; // Text search in note dialog
187 List<String> emitLog; // Messages displayed in the status bar;
188 QSystemTrayIcon trayIcon; // little tray icon
189 QMenu trayMenu; // System tray menu
190 QAction trayExitAction; // Exit the application
191 QAction trayShowAction; // toggle the show/hide action
192 QAction trayAddNoteAction; // Add a note from the system tray
194 NotebookTreeWidget notebookTree; // List of notebooks
195 AttributeTreeWidget attributeTree; // List of note attributes
196 TagTreeWidget tagTree; // list of user created tags
197 SavedSearchTreeWidget savedSearchTree; // list of saved searches
198 TrashTreeWidget trashTree; // Trashcan
199 TableView noteTableView; // List of notes (the widget).
201 public BrowserWindow browserWindow; // Window containing browser & labels
202 public QToolBar toolBar; // The tool bar under the menu
203 QComboBox searchField; // search filter bar on the toolbar;
204 boolean searchPerformed = false; // Search was done?
205 QuotaProgressBar quotaBar; // The current quota usage
207 ApplicationLogger logger;
208 List<String> selectedNotebookGUIDs; // List of notebook GUIDs
209 List<String> selectedTagGUIDs; // List of selected tag GUIDs
210 String previousSelectedTag; // Tag that was selected last time
211 List<String> selectedNoteGUIDs; // List of selected notes
212 String previousSelectedNotebook; // Notebook selected last time
213 String selectedSavedSearchGUID; // Currently selected saved searches
214 private final HashMap<String, ExternalBrowse> externalWindows; // Notes being edited by an external window;
216 NoteFilter filter; // Note filter
217 String currentNoteGuid; // GUID of the current note
218 Note currentNote; // The currently viewed note
219 boolean noteDirty; // Has the note been changed?
220 boolean inkNote; // if this is an ink note, it is read only
222 ListManager listManager; // DB runnable task
224 List<QTemporaryFile> tempFiles; // Array of temporary files;
226 QTimer indexTimer; // timer to start the index thread
227 IndexRunner indexRunner; // thread to index notes
230 QTimer syncTimer; // Sync on an interval
231 QTimer syncDelayTimer; // Sync delay to free up database
232 SyncRunner syncRunner; // thread to do a sync.
233 QThread syncThread; // Thread which talks to evernote
234 ThumbnailRunner thumbnailRunner; // Runner for thumbnail thread
235 QThread thumbnailThread; // Thread that generates pretty pictures
236 QTimer saveTimer; // Timer to save note contents
238 QTimer authTimer; // Refresh authentication
239 QTimer externalFileSaveTimer; // Save files altered externally
240 QTimer thumbnailTimer; // Wakeup & scan for thumbnails
241 List<String> externalFiles; // External files to save later
242 List<String> importFilesKeep; // Auto-import files to save later
243 List<String> importFilesDelete; // Auto-import files to save later
245 int indexTime; // how often to try and index
246 boolean indexRunning; // Is indexing running?
247 boolean indexDisabled; // Is indexing disabled?
249 int syncThreadsReady; // number of sync threads that are free
250 int syncTime; // Sync interval
251 boolean syncRunning; // Is sync running?
252 boolean automaticSync; // do sync automatically?
253 QTreeWidgetItem attributeTreeSelected;
255 QAction prevButton; // Go to the previous item viewed
256 QAction nextButton; // Go to the next item in the history
257 QAction downButton; // Go to the next item in the list
258 QAction upButton; // Go to the prev. item in the list;
259 QAction synchronizeButton; // Synchronize with Evernote
260 QAction allNotesButton; // Reset & view all notes
261 QTimer synchronizeAnimationTimer; // Timer to change animation button
262 double synchronizeIconAngle; // Used to rotate sync icon
263 QAction printButton; // Print Button
264 QAction tagButton; // Tag edit button
265 QAction attributeButton; // Attribute information button
266 QAction emailButton; // Email button
267 QAction deleteButton; // Delete button
268 QAction newButton; // new Note Button;
269 QSpinBox zoomSpinner; // Zoom zoom
270 QAction searchClearButton; // Clear the search field
272 QSplitter mainLeftRightSplitter; // main splitter for left/right side
273 QSplitter leftSplitter1; // first left hand splitter
274 QSplitter browserIndexSplitter; // splitter between note index & note text
276 QFileSystemWatcher importKeepWatcher; // Watch & keep auto-import
277 QFileSystemWatcher importDeleteWatcher; // Watch & Delete auto-import
278 List<String> importedFiles; // History of imported files (so we don't import twice)
280 OnlineNoteHistory historyWindow; // online history window
281 List<NoteVersionId> versions; // history versions
283 QTimer threadMonitorTimer; // Timer to watch threads.
284 int dbThreadDeadCount=0; // number of consecutive dead times for the db thread
285 int syncThreadDeadCount=0; // number of consecutive dead times for the sync thread
286 int indexThreadDeadCount=0; // number of consecutive dead times for the index thread
287 int notebookThreadDeadCount=0; // number of consecutive dead times for the notebook thread
288 int tagDeadCount=0; // number of consecutive dead times for the tag thread
289 int trashDeadCount=0; // number of consecutive dead times for the trash thread
290 int saveThreadDeadCount=0; // number of consecutive dead times for the save thread
292 HashMap<String, String> noteCache; // Cash of note content
293 HashMap<String, Boolean> readOnlyCache; // List of cash notes that are read-only
294 List<String> historyGuids; // GUIDs of previously viewed items
295 int historyPosition; // Position within the viewed items
296 boolean fromHistory; // Is this from the history queue?
297 String trashNoteGuid; // Guid to restore / set into or out of trash to save position
298 List<Thumbnailer> thumbGenerators; // generate preview image
299 ThumbnailViewer thumbnailViewer; // View preview thumbnail;
300 boolean encryptOnShutdown; // should I encrypt when I close?
301 boolean decryptOnShutdown; // should I decrypt on shutdown;
302 String encryptCipher; // What cipher should I use?
303 Signal0 minimizeToTray;
304 boolean windowMaximized = false; // Keep track of the window state for restores
305 List<String> pdfReadyQueue; // Queue of PDFs that are ready to be rendered.
308 String iconPath = new String("classpath:cx/fbn/nevernote/icons/");
311 //***************************************************************
312 //***************************************************************
313 //** Constructor & main entry point
314 //***************************************************************
315 //***************************************************************
316 // Application Constructor
317 @SuppressWarnings("static-access")
318 public NeverNote(DatabaseConnection dbConn) {
320 if (conn.getConnection() == null) {
321 String msg = new String(tr("Unable to connect to the database.\n\nThe most probable reason is that some other process\n" +
322 "is accessing the database or NeverNote is already running.\n\n" +
323 "Please end any other process or shutdown the other NeverNote before starting.\n\nExiting program."));
325 QMessageBox.critical(null, tr("Database Connection Error") ,msg);
329 thread().setPriority(Thread.MAX_PRIORITY);
331 logger = new ApplicationLogger("nevernote.log");
332 logger.log(logger.HIGH, "Starting Application");
334 decryptOnShutdown = false;
335 encryptOnShutdown = false;
336 conn.checkDatabaseVersion();
340 // Start building the invalid XML tables
341 Global.invalidElements = conn.getInvalidXMLTable().getInvalidElements();
342 List<String> elements = conn.getInvalidXMLTable().getInvalidAttributeElements();
344 for (int i=0; i<elements.size(); i++) {
345 Global.invalidAttributes.put(elements.get(i), conn.getInvalidXMLTable().getInvalidAttributes(elements.get(i)));
348 logger.log(logger.EXTREME, "Starting GUI build");
350 QTranslator nevernoteTranslator = new QTranslator();
351 nevernoteTranslator.load(Global.getFileManager().getTranslateFilePath("nevernote_" + QLocale.system().name() + ".qm"));
352 QApplication.instance().installTranslator(nevernoteTranslator);
354 Global.originalPalette = QApplication.palette();
355 QApplication.setStyle(Global.getStyle());
356 if (Global.useStandardPalette())
357 QApplication.setPalette(QApplication.style().standardPalette());
358 setWindowTitle("NeverNote");
360 mainLeftRightSplitter = new QSplitter();
361 setCentralWidget(mainLeftRightSplitter);
362 leftSplitter1 = new QSplitter();
363 leftSplitter1.setOrientation(Qt.Orientation.Vertical);
365 browserIndexSplitter = new QSplitter();
366 browserIndexSplitter.setOrientation(Qt.Orientation.Vertical);
368 //* Setup threads & thread timers
369 int indexRunnerCount = Global.getIndexThreads();
370 indexRunnerCount = 1;
371 QThreadPool.globalInstance().setMaxThreadCount(indexRunnerCount+5); // increase max thread count
373 logger.log(logger.EXTREME, "Building list manager");
374 listManager = new ListManager(conn, logger);
376 logger.log(logger.EXTREME, "Building index runners & timers");
377 indexRunner = new IndexRunner("indexRunner.log", Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
378 indexThread = new QThread(indexRunner, "Index Thread");
381 synchronizeAnimationTimer = new QTimer();
382 synchronizeAnimationTimer.timeout.connect(this, "updateSyncButton()");
384 indexTimer = new QTimer();
385 indexTime = 1000*Global.getIndexThreadSleepInterval();
386 indexTimer.start(indexTime); // Start indexing timer
387 indexTimer.timeout.connect(this, "indexTimer()");
388 indexDisabled = false;
389 indexRunning = false;
391 logger.log(logger.EXTREME, "Setting sync thread & timers");
393 syncRunner = new SyncRunner("syncRunner.log", Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
394 syncTime = new SyncTimes().timeValue(Global.getSyncInterval());
395 syncTimer = new QTimer();
396 syncTimer.timeout.connect(this, "syncTimer()");
397 syncRunner.status.message.connect(this, "setMessage(String)");
398 syncRunner.syncSignal.finished.connect(this, "syncThreadComplete(Boolean)");
399 syncRunner.syncSignal.errorDisconnect.connect(this, "remoteErrorDisconnect()");
402 automaticSync = true;
403 syncTimer.start(syncTime*60*1000);
405 automaticSync = false;
408 syncRunner.setEvernoteUpdateCount(Global.getEvernoteUpdateCount());
409 syncThread = new QThread(syncRunner, "Synchronization Thread");
413 logger.log(logger.EXTREME, "Starting thumnail thread");
414 pdfReadyQueue = new ArrayList<String>();
415 thumbnailRunner = new ThumbnailRunner("thumbnailRunner.log", Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
416 thumbnailThread = new QThread(thumbnailRunner, "Thumbnail Thread");
417 thumbnailRunner.noteSignal.thumbnailPageReady.connect(this, "thumbnailHTMLReady(String,QByteArray,Integer)");
418 thumbnailThread.start();
419 thumbGenerators = new ArrayList<Thumbnailer>();
420 thumbnailTimer = new QTimer();
421 thumbnailTimer.timeout.connect(this, "thumbnailTimer()");
423 thumbnailTimer.setInterval(60*1000); // Thumbnail every minute
424 thumbnailTimer.start();
426 logger.log(logger.EXTREME, "Starting authentication timer");
427 authTimer = new QTimer();
428 authTimer.timeout.connect(this, "authTimer()");
429 authTimer.start(1000*60*15);
430 syncRunner.syncSignal.authRefreshComplete.connect(this, "authRefreshComplete(boolean)");
432 logger.log(logger.EXTREME, "Setting save note timer");
433 saveTimer = new QTimer();
434 saveTimer.timeout.connect(this, "saveNote()");
435 if (Global.getAutoSaveInterval() > 0) {
436 saveTimer.setInterval(1000*60*Global.getAutoSaveInterval());
439 listManager.saveRunner.noteSignals.noteSaveRunnerError.connect(this, "saveRunnerError(String, String)");
441 logger.log(logger.EXTREME, "Starting external file monitor timer");
442 externalFileSaveTimer = new QTimer();
443 externalFileSaveTimer.timeout.connect(this, "externalFileEditedSaver()");
444 externalFileSaveTimer.setInterval(1000*5); // save every 5 seconds;
445 externalFiles = new ArrayList<String>();
446 importFilesDelete = new ArrayList<String>();
447 importFilesKeep = new ArrayList<String>();
448 externalFileSaveTimer.start();
450 notebookTree = new NotebookTreeWidget(conn);
451 attributeTree = new AttributeTreeWidget();
452 tagTree = new TagTreeWidget(conn);
453 savedSearchTree = new SavedSearchTreeWidget();
454 trashTree = new TrashTreeWidget();
455 noteTableView = new TableView(logger, listManager);
457 QGridLayout leftGrid = new QGridLayout();
458 leftSplitter1.setLayout(leftGrid);
459 leftGrid.addWidget(notebookTree, 1, 1);
460 leftGrid.addWidget(tagTree,2,1);
461 leftGrid.addWidget(attributeTree,3,1);
462 leftGrid.addWidget(savedSearchTree,4,1);
463 leftGrid.addWidget(trashTree, 5, 1);
465 // Setup the browser window
466 noteCache = new HashMap<String,String>();
467 readOnlyCache = new HashMap<String, Boolean>();
468 browserWindow = new BrowserWindow(conn);
470 mainLeftRightSplitter.addWidget(leftSplitter1);
471 mainLeftRightSplitter.addWidget(browserIndexSplitter);
473 if (Global.getListView() == Global.View_List_Wide) {
474 browserIndexSplitter.addWidget(noteTableView);
475 browserIndexSplitter.addWidget(browserWindow);
477 mainLeftRightSplitter.addWidget(noteTableView);
478 mainLeftRightSplitter.addWidget(browserWindow);
481 searchField = new QComboBox();
482 searchField.setEditable(true);
483 searchField.activatedIndex.connect(this, "searchFieldChanged()");
484 searchField.setDuplicatesEnabled(false);
485 searchField.editTextChanged.connect(this,"searchFieldTextChanged(String)");
487 quotaBar = new QuotaProgressBar();
489 // Setup the thumbnail viewer
490 thumbnailViewer = new ThumbnailViewer();
491 thumbnailViewer.upArrow.connect(this, "upAction()");
492 thumbnailViewer.downArrow.connect(this, "downAction()");
493 thumbnailViewer.leftArrow.connect(this, "nextViewedAction()");
494 thumbnailViewer.rightArrow.connect(this, "previousViewedAction()");
496 //Setup external browser manager
497 externalWindows = new HashMap<String, ExternalBrowse>();
499 listManager.loadNotesIndex();
500 initializeNotebookTree();
502 initializeSavedSearchTree();
503 attributeTree.itemClicked.connect(this, "attributeTreeClicked(QTreeWidgetItem, Integer)");
504 attributeTreeSelected = null;
505 initializeNoteTable();
507 selectedNoteGUIDs = new ArrayList<String>();
508 statusBar = new QStatusBar();
509 setStatusBar(statusBar);
510 menuBar = new MainMenuBar(this);
511 emitLog = new ArrayList<String>();
513 tagTree.setDeleteAction(menuBar.tagDeleteAction);
514 tagTree.setEditAction(menuBar.tagEditAction);
515 tagTree.setAddAction(menuBar.tagAddAction);
516 tagTree.setIconAction(menuBar.tagIconAction);
517 tagTree.setVisible(Global.isWindowVisible("tagTree"));
518 tagTree.noteSignal.tagsAdded.connect(this, "tagsAdded(String, String)");
519 menuBar.hideTags.setChecked(Global.isWindowVisible("tagTree"));
520 listManager.tagSignal.listChanged.connect(this, "reloadTagTree()");
522 notebookTree.setDeleteAction(menuBar.notebookDeleteAction);
523 notebookTree.setEditAction(menuBar.notebookEditAction);
524 notebookTree.setAddAction(menuBar.notebookAddAction);
525 notebookTree.setIconAction(menuBar.notebookIconAction);
526 notebookTree.setStackAction(menuBar.notebookStackAction);
527 notebookTree.setPublishAction(menuBar.notebookPublishAction);
528 notebookTree.setShareAction(menuBar.notebookShareAction);
529 notebookTree.setVisible(Global.isWindowVisible("notebookTree"));
530 notebookTree.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
531 menuBar.hideNotebooks.setChecked(Global.isWindowVisible("notebookTree"));
533 savedSearchTree.setAddAction(menuBar.savedSearchAddAction);
534 savedSearchTree.setEditAction(menuBar.savedSearchEditAction);
535 savedSearchTree.setDeleteAction(menuBar.savedSearchDeleteAction);
536 savedSearchTree.setIconAction(menuBar.savedSearchIconAction);
537 savedSearchTree.itemSelectionChanged.connect(this, "updateSavedSearchSelection()");
538 savedSearchTree.setVisible(Global.isWindowVisible("savedSearchTree"));
539 menuBar.hideSavedSearches.setChecked(Global.isWindowVisible("savedSearchTree"));
541 noteTableView.setAddAction(menuBar.noteAdd);
542 noteTableView.setDeleteAction(menuBar.noteDelete);
543 noteTableView.setRestoreAction(menuBar.noteRestoreAction);
544 noteTableView.setNoteDuplicateAction(menuBar.noteDuplicateAction);
545 noteTableView.setNoteHistoryAction(menuBar.noteOnlineHistoryAction);
546 noteTableView.noteSignal.titleColorChanged.connect(this, "titleColorChanged(Integer)");
547 noteTableView.setMergeNotesAction(menuBar.noteMergeAction);
548 noteTableView.rowChanged.connect(this, "scrollToGuid(String)");
549 noteTableView.resetViewport.connect(this, "scrollToCurrentGuid()");
550 noteTableView.doubleClicked.connect(this, "listDoubleClick()");
551 listManager.trashSignal.countChanged.connect(trashTree, "updateCounts(Integer)");
553 quotaBar.setMouseClickAction(menuBar.accountAction);
556 trashTree.itemSelectionChanged.connect(this, "trashTreeSelection()");
557 trashTree.setEmptyAction(menuBar.emptyTrashAction);
558 trashTree.setVisible(Global.isWindowVisible("trashTree"));
559 menuBar.hideTrash.setChecked(Global.isWindowVisible("trashTree"));
560 trashTree.updateCounts(listManager.getTrashCount());
561 attributeTree.setVisible(Global.isWindowVisible("attributeTree"));
562 menuBar.hideAttributes.setChecked(Global.isWindowVisible("attributeTree"));
564 noteTableView.setVisible(Global.isWindowVisible("noteList"));
565 menuBar.hideNoteList.setChecked(Global.isWindowVisible("noteList"));
567 if (!Global.isWindowVisible("editorButtonBar"))
568 toggleEditorButtonBar();
569 if (!Global.isWindowVisible("leftPanel"))
570 menuBar.hideLeftSide.setChecked(true);
571 if (Global.isWindowVisible("noteInformation"))
572 toggleNoteInformation();
576 find = new FindDialog();
577 find.getOkButton().clicked.connect(this, "doFindText()");
579 // Setup the tray icon menu bar
580 trayShowAction = new QAction("Show/Hide", this);
581 trayExitAction = new QAction("Exit", this);
582 trayAddNoteAction = new QAction("Add Note", this);
584 trayExitAction.triggered.connect(this, "close()");
585 trayAddNoteAction.triggered.connect(this, "addNote()");
586 trayShowAction.triggered.connect(this, "trayToggleVisible()");
588 trayMenu = new QMenu(this);
589 trayMenu.addAction(trayAddNoteAction);
590 trayMenu.addAction(trayShowAction);
591 trayMenu.addAction(trayExitAction);
594 trayIcon = new QSystemTrayIcon(this);
595 trayIcon.setToolTip("NeverNote");
596 trayIcon.setContextMenu(trayMenu);
597 trayIcon.activated.connect(this, "trayActivated(com.trolltech.qt.gui.QSystemTrayIcon$ActivationReason)");
600 currentNoteGuid = Global.getLastViewedNoteGuid();
601 historyGuids = new ArrayList<String>();
605 if (!currentNoteGuid.trim().equals("")) {
606 currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true);
609 noteIndexUpdated(true);
611 menuBar.showEditorBar.setChecked(Global.isWindowVisible("editorButtonBar"));
612 if (menuBar.showEditorBar.isChecked())
613 showEditorButtons(browserWindow);
614 tagIndexUpdated(true);
615 savedSearchIndexUpdated();
616 notebookIndexUpdated();
618 setupSyncSignalListeners();
619 setupBrowserSignalListeners();
620 setupIndexListeners();
623 tagTree.tagSignal.listChanged.connect(this, "tagIndexUpdated()");
624 tagTree.showAllTags(true);
626 QIcon appIcon = new QIcon(iconPath+"nevernote.png");
627 setWindowIcon(appIcon);
628 trayIcon.setIcon(appIcon);
629 if (Global.showTrayIcon())
634 scrollToGuid(currentNoteGuid);
635 if (Global.automaticLogin()) {
637 if (Global.isConnected)
640 setupFolderImports();
643 restoreWindowState(true);
645 if (Global.mimicEvernoteInterface) {
646 notebookTree.selectGuid("");
649 threadMonitorTimer = new QTimer();
650 threadMonitorTimer.timeout.connect(this, "threadMonitorCheck()");
651 threadMonitorTimer.start(1000*10); // Check for threads every 10 seconds;
653 historyGuids.add(currentNoteGuid);
656 if (Global.getListView() == Global.View_List_Narrow) {
657 menuBar.narrowListView.setChecked(true);
661 menuBar.wideListView.setChecked(true);
665 if (Global.getListView() == Global.View_List_Wide) {
666 browserIndexSplitter.addWidget(noteTableView);
667 browserIndexSplitter.addWidget(browserWindow);
669 mainLeftRightSplitter.addWidget(noteTableView);
670 mainLeftRightSplitter.addWidget(browserWindow);
673 int sortCol = Global.getSortColumn();
674 int sortOrder = Global.getSortOrder();
675 noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder));
681 public static void main(String[] args) {
682 QApplication.initialize(args);
683 QPixmap pixmap = new QPixmap("classpath:cx/fbn/nevernote/icons/splash_logo.png");
684 QSplashScreen splash = new QSplashScreen(pixmap);
687 DatabaseConnection dbConn;
690 initializeGlobalSettings(args);
692 showSplash = Global.isWindowVisible("SplashScreen");
696 dbConn = setupDatabaseConnection();
698 // Must be last stage of setup - only safe once DB is open hence we know we are the only instance running
699 Global.getFileManager().purgeResDirectory();
701 } catch (InitializationException e) {
704 QMessageBox.critical(null, "Startup error", "Aborting: " + e.getMessage());
708 NeverNote application = new NeverNote(dbConn);
710 application.setAttribute(WidgetAttribute.WA_DeleteOnClose, true);
711 if (Global.startMinimized())
712 application.showMinimized();
714 if (Global.wasWindowMaximized())
715 application.showMaximized();
721 splash.finish(application);
723 System.out.println("Goodbye.");
728 * Open the internal database, or create if not present
730 * @throws InitializationException when opening the database fails, e.g. because another process has it locked
732 private static DatabaseConnection setupDatabaseConnection() throws InitializationException {
733 ApplicationLogger logger = new ApplicationLogger("nevernote-database.log");
735 File f = Global.getFileManager().getDbDirFile(Global.databaseName + ".h2.db");
736 boolean dbExists = f.exists();
738 Global.setDatabaseUrl("");
740 if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") > -1) {
741 boolean goodCheck = false;
743 DatabaseLoginDialog dialog = new DatabaseLoginDialog();
745 if (!dialog.okPressed())
747 Global.cipherPassword = dialog.getPassword();
748 goodCheck = databaseCheck(Global.getDatabaseUrl(), Global.getDatabaseUserid(),
749 Global.getDatabaseUserPassword(), Global.cipherPassword);
752 DatabaseConnection dbConn = new DatabaseConnection(logger,Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
756 // Encrypt the database upon shutdown
757 private void encryptOnShutdown() {
758 String dbPath= Global.getFileManager().getDbDirPath("");
759 String dbName = "NeverNote";
761 Statement st = conn.getConnection().createStatement();
762 st.execute("shutdown");
763 if (QMessageBox.question(this, "Are you sure",
764 "Are you sure you wish to encrypt the database?",
765 QMessageBox.StandardButton.Yes,
766 QMessageBox.StandardButton.No) == StandardButton.Yes.value()) {
767 ChangeFileEncryption.execute(dbPath, dbName, encryptCipher, null, Global.cipherPassword.toCharArray(), true);
768 Global.setDatabaseUrl(Global.getDatabaseUrl() + ";CIPHER="+encryptCipher);
769 QMessageBox.information(this, "Encryption Complete", "Encryption is complete");
771 } catch (SQLException e) {
776 // Decrypt the database upon shutdown
777 private void decryptOnShutdown() {
778 String dbPath= Global.getFileManager().getDbDirPath("");
779 String dbName = "NeverNote";
781 Statement st = conn.getConnection().createStatement();
782 st.execute("shutdown");
783 if (Global.getDatabaseUrl().toUpperCase().indexOf(";CIPHER=AES") > -1)
784 encryptCipher = "AES";
786 encryptCipher = "XTEA";
787 if (QMessageBox.question(this, tr("Confirmation"), tr("Are you sure",
788 "Are you sure you wish to decrypt the database?"),
789 QMessageBox.StandardButton.Yes,
790 QMessageBox.StandardButton.No) == StandardButton.Yes.value()) {
792 ChangeFileEncryption.execute(dbPath, dbName, encryptCipher, Global.cipherPassword.toCharArray(), null, true);
793 Global.setDatabaseUrl("");
794 QMessageBox.information(this, tr("Decryption Complete"), tr("Decryption is complete"));
796 } catch (SQLException e) {
801 * Encrypt/Decrypt the local database
803 public void doDatabaseEncrypt() {
804 // The database is not currently encrypted
805 if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") == -1) {
806 if (QMessageBox.question(this, tr("Confirmation"), tr("Encrypting the database is used" +
807 "to enhance security and is performed\nupon shutdown, but please be aware that if"+
808 " you lose the password your\nis lost forever.\n\nIt is highly recommended you " +
809 "perform a backup and/or fully synchronize\n prior to executing this funtction.\n\n" +
810 "Do you wish to proceed?"),
811 QMessageBox.StandardButton.Yes,
812 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
815 DBEncryptDialog dialog = new DBEncryptDialog();
817 if (dialog.okPressed()) {
818 Global.cipherPassword = dialog.getPassword();
819 encryptOnShutdown = true;
820 encryptCipher = dialog.getEncryptionMethod();
823 DBEncryptDialog dialog = new DBEncryptDialog();
824 dialog.setWindowTitle("Database Decryption");
825 dialog.hideEncryption();
827 if (dialog.okPressed()) {
828 if (!dialog.getPassword().equals(Global.cipherPassword)) {
829 QMessageBox.critical(null, tr("Incorrect Password"), tr("Incorrect Password"));
832 decryptOnShutdown = true;
839 private static void initializeGlobalSettings(String[] args) throws InitializationException {
840 StartupConfig startupConfig = new StartupConfig();
842 for (String arg : args) {
843 String lower = arg.toLowerCase();
844 if (lower.startsWith("--name="))
845 startupConfig.setName(arg.substring(arg.indexOf('=') + 1));
846 if (lower.startsWith("--home="))
847 startupConfig.setHomeDirPath(arg.substring(arg.indexOf('=') + 1));
848 if (lower.startsWith("--disable-viewing"))
849 startupConfig.setDisableViewing(true);
851 Global.setup(startupConfig);
856 public void closeEvent(QCloseEvent event) {
857 logger.log(logger.HIGH, "Entering NeverNote.closeEvent");
860 if (currentNote!= null & browserWindow!=null) {
861 if (!currentNote.getTitle().equals(browserWindow.getTitle()))
862 conn.getNoteTable().updateNoteTitle(currentNote.getGuid(), browserWindow.getTitle());
865 setMessage(tr("Beginning shutdown."));
867 // Close down external windows
868 Collection<ExternalBrowse> windows = externalWindows.values();
869 Iterator<ExternalBrowse> iterator = windows.iterator();
870 while (iterator.hasNext()) {
871 ExternalBrowse browser = iterator.next();
872 browser.windowClosing.disconnect();
877 externalFileEditedSaver();
878 if (Global.isConnected && Global.synchronizeOnClose()) {
879 setMessage(tr("Performing synchronization before closing."));
880 syncRunner.addWork("SYNC");
882 setMessage("Closing Program.");
883 threadMonitorTimer.stop();
885 syncRunner.addWork("STOP");
886 syncRunner.keepRunning = false;
887 thumbnailRunner.addWork("STOP");
888 syncRunner.keepRunning = false;
889 indexRunner.addWork("STOP");
890 syncRunner.keepRunning = false;
895 if (tempFiles != null)
898 browserWindow.noteSignal.tagsChanged.disconnect();
899 browserWindow.noteSignal.titleChanged.disconnect();
900 browserWindow.noteSignal.noteChanged.disconnect();
901 browserWindow.noteSignal.notebookChanged.disconnect();
902 browserWindow.noteSignal.createdDateChanged.disconnect();
903 browserWindow.noteSignal.alteredDateChanged.disconnect();
904 syncRunner.searchSignal.listChanged.disconnect();
905 syncRunner.tagSignal.listChanged.disconnect();
906 syncRunner.notebookSignal.listChanged.disconnect();
907 syncRunner.noteIndexSignal.listChanged.disconnect();
910 Global.saveWindowVisible("toolBar", toolBar.isVisible());
911 saveNoteColumnPositions();
912 saveNoteIndexWidth();
914 int width = notebookTree.columnWidth(0);
915 Global.setColumnWidth("notebookTreeName", width);
916 width = tagTree.columnWidth(0);
917 Global.setColumnWidth("tagTreeName", width);
919 Global.saveWindowMaximized(isMaximized());
920 Global.saveCurrentNoteGuid(currentNoteGuid);
922 int sortCol = noteTableView.proxyModel.sortColumn();
923 int sortOrder = noteTableView.proxyModel.sortOrder().value();
924 Global.setSortColumn(sortCol);
925 Global.setSortOrder(sortOrder);
929 Global.keepRunning = false;
931 logger.log(logger.MEDIUM, "Waiting for indexThread to stop");
932 indexRunner.thread().join(50);
933 logger.log(logger.MEDIUM, "Index thread has stopped");
934 } catch (InterruptedException e1) {
935 e1.printStackTrace();
937 if (!syncRunner.isIdle()) {
939 logger.log(logger.MEDIUM, "Waiting for syncThread to stop");
941 logger.log(logger.MEDIUM, "Sync thread has stopped");
942 } catch (InterruptedException e1) {
943 e1.printStackTrace();
947 if (encryptOnShutdown) {
950 if (decryptOnShutdown) {
953 logger.log(logger.HIGH, "Leaving NeverNote.closeEvent");
956 public void setMessage(String s) {
957 logger.log(logger.HIGH, "Entering NeverNote.setMessage");
958 logger.log(logger.HIGH, "Message: " +s);
959 statusBar.showMessage(s);
961 logger.log(logger.HIGH, "Leaving NeverNote.setMessage");
964 private void waitCursor(boolean wait) {
966 if (QApplication.overrideCursor() == null)
967 QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.WaitCursor));
970 while (QApplication.overrideCursor() != null)
971 QApplication.restoreOverrideCursor();
975 private void setupIndexListeners() {
976 indexRunner.noteSignal.noteIndexed.connect(this, "indexThreadComplete(String)");
977 indexRunner.resourceSignal.resourceIndexed.connect(this, "indexThreadComplete(String)");
978 // indexRunner.threadSignal.indexNeeded.connect(listManager, "setIndexNeeded(String, String, Boolean)");
980 private void setupSyncSignalListeners() {
981 syncRunner.tagSignal.listChanged.connect(this, "tagIndexUpdated()");
982 syncRunner.searchSignal.listChanged.connect(this, "savedSearchIndexUpdated()");
983 syncRunner.notebookSignal.listChanged.connect(this, "notebookIndexUpdated()");
984 syncRunner.noteIndexSignal.listChanged.connect(this, "noteIndexUpdated(boolean)");
985 syncRunner.noteSignal.quotaChanged.connect(this, "updateQuotaBar()");
987 syncRunner.syncSignal.saveUploadAmount.connect(this,"saveUploadAmount(long)");
988 syncRunner.syncSignal.saveUserInformation.connect(this,"saveUserInformation(User)");
989 syncRunner.syncSignal.saveEvernoteUpdateCount.connect(this,"saveEvernoteUpdateCount(int)");
991 syncRunner.noteSignal.guidChanged.connect(this, "noteGuidChanged(String, String)");
992 syncRunner.noteSignal.noteChanged.connect(this, "invalidateNoteCache(String, String)");
993 syncRunner.resourceSignal.resourceGuidChanged.connect(this, "noteResourceGuidChanged(String,String,String)");
994 syncRunner.noteSignal.noteDownloaded.connect(listManager, "noteDownloaded(Note)");
996 syncRunner.syncSignal.refreshLists.connect(this, "refreshLists()");
999 private void setupBrowserSignalListeners() {
1000 setupBrowserWindowListeners(browserWindow, true);
1003 private void setupBrowserWindowListeners(BrowserWindow browser, boolean master) {
1004 browser.fileWatcher.fileChanged.connect(this, "externalFileEdited(String)");
1005 browser.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)");
1006 browser.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)");
1007 if (master) browser.noteSignal.noteChanged.connect(this, "setNoteDirty()");
1008 browser.noteSignal.titleChanged.connect(listManager, "updateNoteTitle(String, String)");
1009 browser.noteSignal.titleChanged.connect(this, "updateNoteTitle(String, String)");
1010 browser.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
1011 browser.noteSignal.createdDateChanged.connect(listManager, "updateNoteCreatedDate(String, QDateTime)");
1012 browser.noteSignal.alteredDateChanged.connect(listManager, "updateNoteAlteredDate(String, QDateTime)");
1013 browser.noteSignal.subjectDateChanged.connect(listManager, "updateNoteSubjectDate(String, QDateTime)");
1014 browser.noteSignal.authorChanged.connect(listManager, "updateNoteAuthor(String, String)");
1015 browser.noteSignal.geoChanged.connect(listManager, "updateNoteGeoTag(String, Double,Double,Double)");
1016 browser.noteSignal.geoChanged.connect(this, "setNoteDirty()");
1017 browser.noteSignal.sourceUrlChanged.connect(listManager, "updateNoteSourceUrl(String, String)");
1018 if (master) browser.focusLost.connect(this, "saveNote()");
1019 browser.resourceSignal.contentChanged.connect(this, "externalFileEdited(String)");
1022 //***************************************************************
1023 //***************************************************************
1024 //* Settings and look & feel
1025 //***************************************************************
1026 //***************************************************************
1027 @SuppressWarnings("unused")
1028 private void settings() {
1029 logger.log(logger.HIGH, "Entering NeverNote.settings");
1030 saveNoteColumnPositions();
1031 saveNoteIndexWidth();
1033 ConfigDialog settings = new ConfigDialog(this);
1034 String dateFormat = Global.getDateFormat();
1035 String timeFormat = Global.getTimeFormat();
1037 indexTime = 1000*Global.getIndexThreadSleepInterval();
1038 indexTimer.start(indexTime); // reset indexing timer
1041 if (Global.showTrayIcon())
1046 if (menuBar.showEditorBar.isChecked())
1047 showEditorButtons(browserWindow);
1049 // Reset the save timer
1050 if (Global.getAutoSaveInterval() > 0)
1051 saveTimer.setInterval(1000*60*Global.getAutoSaveInterval());
1055 // This is a hack to force a reload of the index in case the date or time changed.
1056 // if (!dateFormat.equals(Global.getDateFormat()) ||
1057 // !timeFormat.equals(Global.getTimeFormat())) {
1059 readOnlyCache.clear();
1060 noteIndexUpdated(true);
1063 logger.log(logger.HIGH, "Leaving NeverNote.settings");
1065 // Restore things to the way they were
1066 private void restoreWindowState(boolean mainWindow) {
1067 // We need to name things or this doesn't work.
1068 setObjectName("NeverNote");
1069 mainLeftRightSplitter.setObjectName("mainLeftRightSplitter");
1070 browserIndexSplitter.setObjectName("browserIndexSplitter");
1071 leftSplitter1.setObjectName("leftSplitter1");
1073 // Restore the actual positions.
1075 restoreGeometry(Global.restoreGeometry(objectName()));
1076 mainLeftRightSplitter.restoreState(Global.restoreState(mainLeftRightSplitter.objectName()));
1077 browserIndexSplitter.restoreState(Global.restoreState(browserIndexSplitter.objectName()));
1078 leftSplitter1.restoreState(Global.restoreState(leftSplitter1.objectName()));
1081 // Save window positions for the next start
1082 private void saveWindowState() {
1083 Global.saveGeometry(objectName(), saveGeometry());
1084 Global.saveState(mainLeftRightSplitter.objectName(), mainLeftRightSplitter.saveState());
1085 Global.saveState(browserIndexSplitter.objectName(), browserIndexSplitter.saveState());
1086 Global.saveState(leftSplitter1.objectName(), leftSplitter1.saveState());
1088 // Load the style sheet
1089 private void loadStyleSheet() {
1090 String fileName = Global.getFileManager().getQssDirPath("default.qss");
1091 QFile file = new QFile(fileName);
1092 file.open(OpenModeFlag.ReadOnly);
1093 String styleSheet = file.readAll().toString();
1095 setStyleSheet(styleSheet);
1097 // Save column positions for the next time
1098 private void saveNoteColumnPositions() {
1099 int position = noteTableView.header.visualIndex(Global.noteTableCreationPosition);
1100 Global.setColumnPosition("noteTableCreationPosition", position);
1101 position = noteTableView.header.visualIndex(Global.noteTableTagPosition);
1102 Global.setColumnPosition("noteTableTagPosition", position);
1103 position = noteTableView.header.visualIndex(Global.noteTableNotebookPosition);
1104 Global.setColumnPosition("noteTableNotebookPosition", position);
1105 position = noteTableView.header.visualIndex(Global.noteTableChangedPosition);
1106 Global.setColumnPosition("noteTableChangedPosition", position);
1107 position = noteTableView.header.visualIndex(Global.noteTableAuthorPosition);
1108 Global.setColumnPosition("noteTableAuthorPosition", position);
1109 position = noteTableView.header.visualIndex(Global.noteTableSourceUrlPosition);
1110 Global.setColumnPosition("noteTableSourceUrlPosition", position);
1111 position = noteTableView.header.visualIndex(Global.noteTableSubjectDatePosition);
1112 Global.setColumnPosition("noteTableSubjectDatePosition", position);
1113 position = noteTableView.header.visualIndex(Global.noteTableTitlePosition);
1114 Global.setColumnPosition("noteTableTitlePosition", position);
1115 position = noteTableView.header.visualIndex(Global.noteTableSynchronizedPosition);
1116 Global.setColumnPosition("noteTableSynchronizedPosition", position);
1117 position = noteTableView.header.visualIndex(Global.noteTableGuidPosition);
1118 Global.setColumnPosition("noteTableGuidPosition", position);
1119 position = noteTableView.header.visualIndex(Global.noteTableThumbnailPosition);
1120 Global.setColumnPosition("noteTableThumbnailPosition", position);
1123 // Save column widths for the next time
1124 private void saveNoteIndexWidth() {
1126 width = noteTableView.getColumnWidth(Global.noteTableCreationPosition);
1127 Global.setColumnWidth("noteTableCreationPosition", width);
1128 width = noteTableView.getColumnWidth(Global.noteTableChangedPosition);
1129 Global.setColumnWidth("noteTableChangedPosition", width);
1130 width = noteTableView.getColumnWidth(Global.noteTableGuidPosition);
1131 Global.setColumnWidth("noteTableGuidPosition", width);
1132 width = noteTableView.getColumnWidth(Global.noteTableNotebookPosition);
1133 Global.setColumnWidth("noteTableNotebookPosition", width);
1134 width = noteTableView.getColumnWidth(Global.noteTableTagPosition);
1135 Global.setColumnWidth("noteTableTagPosition", width);
1136 width = noteTableView.getColumnWidth(Global.noteTableTitlePosition);
1137 Global.setColumnWidth("noteTableTitlePosition", width);
1138 width = noteTableView.getColumnWidth(Global.noteTableSourceUrlPosition);
1139 Global.setColumnWidth("noteTableSourceUrlPosition", width);
1140 width = noteTableView.getColumnWidth(Global.noteTableAuthorPosition);
1141 Global.setColumnWidth("noteTableAuthorPosition", width);
1142 width = noteTableView.getColumnWidth(Global.noteTableSubjectDatePosition);
1143 Global.setColumnWidth("noteTableSubjectDatePosition", width);
1144 width = noteTableView.getColumnWidth(Global.noteTableSynchronizedPosition);
1145 Global.setColumnWidth("noteTableSynchronizedPosition", width);
1146 width = noteTableView.getColumnWidth(Global.noteTableThumbnailPosition);
1147 Global.setColumnWidth("noteTableThumbnailPosition", width);
1148 width = noteTableView.getColumnWidth(Global.noteTableGuidPosition);
1149 Global.setColumnWidth("noteTableGuidPosition", width);
1153 //***************************************************************
1154 //***************************************************************
1155 //** These functions deal with Notebook menu items
1156 //***************************************************************
1157 //***************************************************************
1158 // Setup the tree containing the user's notebooks.
1159 private void initializeNotebookTree() {
1160 logger.log(logger.HIGH, "Entering NeverNote.initializeNotebookTree");
1161 notebookTree.itemClicked.connect(this, "notebookTreeSelection()");
1162 listManager.notebookSignal.refreshNotebookTreeCounts.connect(notebookTree, "updateCounts(List, List)");
1163 logger.log(logger.HIGH, "Leaving NeverNote.initializeNotebookTree");
1165 // Listener when a notebook is selected
1166 private void notebookTreeSelection() {
1167 logger.log(logger.HIGH, "Entering NeverNote.notebookTreeSelection");
1170 clearAttributeFilter();
1171 clearSavedSearchFilter();
1172 if (Global.mimicEvernoteInterface) {
1174 searchField.clear();
1176 menuBar.noteRestoreAction.setVisible(false);
1177 menuBar.notebookEditAction.setEnabled(true);
1178 menuBar.notebookDeleteAction.setEnabled(true);
1179 menuBar.notebookPublishAction.setEnabled(true);
1180 menuBar.notebookShareAction.setEnabled(true);
1181 menuBar.notebookIconAction.setEnabled(true);
1182 menuBar.notebookStackAction.setEnabled(true);
1183 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1184 QTreeWidgetItem currentSelection;
1185 selectedNotebookGUIDs.clear();
1186 if (!Global.mimicEvernoteInterface) {
1187 for (int i=0; i<selections.size(); i++) {
1188 currentSelection = selections.get(i);
1189 if (!currentSelection.text(2).equals("STACK"))
1190 selectedNotebookGUIDs.add(currentSelection.text(2));
1192 String stackName = currentSelection.text(0);
1193 for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1194 Notebook book = listManager.getNotebookIndex().get(j);
1195 if (book.getStack()!=null && book.getStack().equalsIgnoreCase(stackName))
1196 selectedNotebookGUIDs.add(book.getGuid());
1202 // There is the potential for no notebooks to be selected if this
1203 // happens then we make it look like all notebooks were selecetd.
1204 // If that happens, just select the "all notebooks"
1205 selections = notebookTree.selectedItems();
1206 if (selections.size()==0) {
1207 selectedNotebookGUIDs.clear();
1208 menuBar.notebookEditAction.setEnabled(false);
1209 menuBar.notebookDeleteAction.setEnabled(false);
1210 menuBar.notebookIconAction.setEnabled(false);
1211 menuBar.notebookStackAction.setEnabled(false);
1213 if (selectedNotebookGUIDs.size() == 1 && selectedNotebookGUIDs.get(0).equals(previousSelectedNotebook)) {
1214 previousSelectedNotebook = selectedNotebookGUIDs.get(0);
1215 previousSelectedNotebook = "";
1216 notebookTree.clearSelection();
1217 notebookTreeSelection();
1220 if (selectedNotebookGUIDs.size() == 1)
1221 previousSelectedNotebook = selectedNotebookGUIDs.get(0);
1222 if (selectedNotebookGUIDs.size() > 1)
1223 previousSelectedNotebook = "";
1226 String stackName = "";
1227 if (selections.size() > 0) {
1228 guid = (selections.get(0).text(2));
1229 stackName = selections.get(0).text(0);
1231 if (!guid.equals("") && !guid.equals("STACK")) {
1232 selectedNotebookGUIDs.add(guid);
1233 menuBar.notebookIconAction.setEnabled(true);
1236 menuBar.notebookIconAction.setEnabled(true);
1237 for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1238 Notebook book = listManager.getNotebookIndex().get(j);
1239 if (book.getStack() != null && book.getStack().equalsIgnoreCase(stackName))
1240 selectedNotebookGUIDs.add(book.getGuid());
1244 listManager.setSelectedNotebooks(selectedNotebookGUIDs);
1245 listManager.loadNotesIndex();
1246 noteIndexUpdated(false);
1247 logger.log(logger.HIGH, "Leaving NeverNote.notebookTreeSelection");
1250 private void clearNotebookFilter() {
1251 notebookTree.blockSignals(true);
1252 notebookTree.clearSelection();
1253 menuBar.noteRestoreAction.setVisible(false);
1254 menuBar.notebookEditAction.setEnabled(false);
1255 menuBar.notebookDeleteAction.setEnabled(false);
1256 selectedNotebookGUIDs.clear();
1257 listManager.setSelectedNotebooks(selectedNotebookGUIDs);
1258 notebookTree.blockSignals(false);
1260 // Triggered when the notebook DB has been updated
1261 private void notebookIndexUpdated() {
1262 logger.log(logger.HIGH, "Entering NeverNote.notebookIndexUpdated");
1264 // Get the possible icons
1265 HashMap<String, QIcon> icons = conn.getNotebookTable().getAllIcons();
1266 notebookTree.setIcons(icons);
1268 if (selectedNotebookGUIDs == null)
1269 selectedNotebookGUIDs = new ArrayList<String>();
1270 List<Notebook> books = conn.getNotebookTable().getAll();
1271 for (int i=books.size()-1; i>=0; i--) {
1272 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1273 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(books.get(i).getGuid())) {
1275 j=listManager.getArchiveNotebookIndex().size();
1281 listManager.countNotebookResults(listManager.getNoteIndex());
1282 notebookTree.blockSignals(true);
1283 notebookTree.load(books, listManager.getLocalNotebooks());
1284 for (int i=selectedNotebookGUIDs.size()-1; i>=0; i--) {
1285 boolean found = notebookTree.selectGuid(selectedNotebookGUIDs.get(i));
1287 selectedNotebookGUIDs.remove(i);
1289 notebookTree.blockSignals(false);
1291 logger.log(logger.HIGH, "Leaving NeverNote.notebookIndexUpdated");
1293 // Show/Hide note information
1294 private void toggleNotebookWindow() {
1295 logger.log(logger.HIGH, "Entering NeverNote.toggleNotebookWindow");
1296 if (notebookTree.isVisible())
1297 notebookTree.hide();
1299 notebookTree.show();
1300 menuBar.hideNotebooks.setChecked(notebookTree.isVisible());
1301 Global.saveWindowVisible("notebookTree", notebookTree.isVisible());
1302 logger.log(logger.HIGH, "Leaving NeverNote.toggleNotebookWindow");
1304 // Add a new notebook
1305 @SuppressWarnings("unused")
1306 private void addNotebook() {
1307 logger.log(logger.HIGH, "Inside NeverNote.addNotebook");
1308 NotebookEdit edit = new NotebookEdit();
1309 edit.setNotebooks(listManager.getNotebookIndex());
1312 if (!edit.okPressed())
1315 Calendar currentTime = new GregorianCalendar();
1316 Long l = new Long(currentTime.getTimeInMillis());
1317 String randint = new String(Long.toString(l));
1319 Notebook newBook = new Notebook();
1320 newBook.setUpdateSequenceNum(0);
1321 newBook.setGuid(randint);
1322 newBook.setName(edit.getNotebook());
1323 newBook.setServiceCreated(new Date().getTime());
1324 newBook.setServiceUpdated(new Date().getTime());
1325 newBook.setDefaultNotebook(false);
1326 newBook.setPublished(false);
1328 listManager.getNotebookIndex().add(newBook);
1330 listManager.getLocalNotebooks().add(newBook.getGuid());
1331 conn.getNotebookTable().addNotebook(newBook, true, edit.isLocal());
1332 notebookIndexUpdated();
1333 listManager.countNotebookResults(listManager.getNoteIndex());
1334 // notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
1335 logger.log(logger.HIGH, "Leaving NeverNote.addNotebook");
1337 // Edit an existing notebook
1338 @SuppressWarnings("unused")
1339 private void stackNotebook() {
1340 logger.log(logger.HIGH, "Entering NeverNote.stackNotebook");
1341 StackNotebook edit = new StackNotebook();
1343 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1344 QTreeWidgetItem currentSelection;
1345 for (int i=0; i<selections.size(); i++) {
1346 currentSelection = selections.get(0);
1347 String guid = currentSelection.text(2);
1348 if (guid.equalsIgnoreCase("")) {
1349 QMessageBox.critical(this, tr("Unable To Stack") ,tr("You can't stack the \"All Notebooks\" item."));
1352 if (guid.equalsIgnoreCase("STACK")) {
1353 QMessageBox.critical(this, tr("Unable To Stack") ,tr("You can't stack a stack."));
1358 edit.setStackNames(conn.getNotebookTable().getAllStackNames());
1363 if (!edit.okPressed())
1366 String stack = edit.getStackName();
1368 for (int i=0; i<selections.size(); i++) {
1369 currentSelection = selections.get(i);
1370 String guid = currentSelection.text(2);
1371 listManager.updateNotebookStack(guid, stack);
1373 notebookIndexUpdated();
1374 logger.log(logger.HIGH, "Leaving NeverNote.stackNotebook");
1376 // Edit an existing notebook
1377 @SuppressWarnings("unused")
1378 private void editNotebook() {
1379 logger.log(logger.HIGH, "Entering NeverNote.editNotebook");
1380 NotebookEdit edit = new NotebookEdit();
1382 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1383 QTreeWidgetItem currentSelection;
1384 currentSelection = selections.get(0);
1385 edit.setNotebook(currentSelection.text(0));
1387 String guid = currentSelection.text(2);
1388 if (!guid.equalsIgnoreCase("STACK")) {
1389 edit.setTitle(tr("Edit Notebook"));
1390 edit.setNotebooks(listManager.getNotebookIndex());
1391 edit.setLocalCheckboxEnabled(false);
1392 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1393 if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
1394 edit.setDefaultNotebook(listManager.getNotebookIndex().get(i).isDefaultNotebook());
1395 i=listManager.getNotebookIndex().size();
1399 edit.setTitle(tr("Edit Stack"));
1400 edit.setStacks(conn.getNotebookTable().getAllStackNames());
1401 edit.hideLocalCheckbox();
1402 edit.hideDefaultCheckbox();
1407 if (!edit.okPressed())
1411 if (guid.equalsIgnoreCase("STACK")) {
1412 conn.getNotebookTable().renameStacks(currentSelection.text(0), edit.getNotebook());
1413 for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1414 if (listManager.getNotebookIndex().get(j).getStack().equalsIgnoreCase(currentSelection.text(0)))
1415 listManager.getNotebookIndex().get(j).setStack(edit.getNotebook());
1417 conn.getNotebookTable().renameStacks(currentSelection.text(0), edit.getNotebook());
1418 currentSelection.setText(0, edit.getNotebook());
1422 updateListNotebookName(currentSelection.text(0), edit.getNotebook());
1423 currentSelection.setText(0, edit.getNotebook());
1425 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1426 if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
1427 listManager.getNotebookIndex().get(i).setName(edit.getNotebook());
1428 if (!listManager.getNotebookIndex().get(i).isDefaultNotebook() && edit.isDefaultNotebook()) {
1429 for (int j=0; j<listManager.getNotebookIndex().size(); j++)
1430 listManager.getNotebookIndex().get(j).setDefaultNotebook(false);
1431 listManager.getNotebookIndex().get(i).setDefaultNotebook(true);
1432 conn.getNotebookTable().setDefaultNotebook(listManager.getNotebookIndex().get(i).getGuid());
1434 conn.getNotebookTable().updateNotebook(listManager.getNotebookIndex().get(i), true);
1435 i=listManager.getNotebookIndex().size();
1439 // Build a list of non-closed notebooks
1440 List<Notebook> nbooks = new ArrayList<Notebook>();
1441 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1442 boolean found=false;
1443 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1444 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
1448 nbooks.add(listManager.getNotebookIndex().get(i));
1451 browserWindow.setNotebookList(nbooks);
1452 logger.log(logger.HIGH, "Leaving NeverNote.editNotebook");
1454 // Publish a notebook
1455 @SuppressWarnings("unused")
1456 private void publishNotebook() {
1457 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1458 QTreeWidgetItem currentSelection;
1459 currentSelection = selections.get(0);
1460 String guid = currentSelection.text(2);
1462 if (guid.equalsIgnoreCase("STACK") || guid.equalsIgnoreCase(""))
1467 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1468 if (guid.equals(listManager.getNotebookIndex().get(i).getGuid())) {
1469 n = listManager.getNotebookIndex().get(i);
1471 i = listManager.getNotebookIndex().size();
1477 PublishNotebook publish = new PublishNotebook(Global.username, Global.getServer(), n);
1480 if (!publish.okClicked())
1483 Publishing p = publish.getPublishing();
1484 boolean isPublished = !publish.isStopPressed();
1485 conn.getNotebookTable().setPublishing(n.getGuid(), isPublished, p);
1486 n.setPublished(isPublished);
1488 listManager.getNotebookIndex().set(position, n);
1489 notebookIndexUpdated();
1491 // Publish a notebook
1492 @SuppressWarnings("unused")
1493 private void shareNotebook() {
1494 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1495 QTreeWidgetItem currentSelection;
1496 currentSelection = selections.get(0);
1497 String guid = currentSelection.text(2);
1499 if (guid.equalsIgnoreCase("STACK") || guid.equalsIgnoreCase(""))
1503 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1504 if (guid.equals(listManager.getNotebookIndex().get(i).getGuid())) {
1505 n = listManager.getNotebookIndex().get(i);
1506 i = listManager.getNotebookIndex().size();
1510 String authToken = null;
1511 if (syncRunner.isConnected)
1512 authToken = syncRunner.authToken;
1513 ShareNotebook share = new ShareNotebook(n.getName(), conn, n, syncRunner);
1518 // Delete an existing notebook
1519 @SuppressWarnings("unused")
1520 private void deleteNotebook() {
1521 logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
1522 boolean stacksFound = false;
1523 boolean notebooksFound = false;
1524 boolean assigned = false;
1525 // Check if any notes have this notebook
1526 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1527 for (int i=0; i<selections.size(); i++) {
1528 QTreeWidgetItem currentSelection;
1529 currentSelection = selections.get(i);
1530 String guid = currentSelection.text(2);
1531 if (!guid.equalsIgnoreCase("STACK")) {
1532 notebooksFound = true;
1533 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
1534 String noteGuid = listManager.getNoteIndex().get(j).getNotebookGuid();
1535 if (noteGuid.equals(guid)) {
1537 j=listManager.getNoteIndex().size();
1538 i=selections.size();
1546 QMessageBox.information(this, tr("Unable to Delete"), tr("Some of the selected notebook(s) contain notes.\n"+
1547 "Please delete the notes or move them to another notebook before deleting any notebooks."));
1551 if (conn.getNotebookTable().getAll().size() == 1) {
1552 QMessageBox.information(this, tr("Unable to Delete"), tr("You must have at least one notebook."));
1556 // If all notebooks are clear, verify the delete
1557 String msg1 = new String(tr("Delete selected notebooks?"));
1558 String msg2 = new String(tr("Remove selected stacks (notebooks will not be deleted)?"));
1559 String msg3 = new String(tr("Delete selected notebooks & remove stacks? Notebooks under the stacks are" +
1560 " not deleted unless selected?"));
1562 if (stacksFound && notebooksFound)
1564 if (!stacksFound && notebooksFound)
1566 if (stacksFound && !notebooksFound)
1568 if (QMessageBox.question(this, tr("Confirmation"), msg,
1569 QMessageBox.StandardButton.Yes,
1570 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1574 // If confirmed, delete the notebook
1575 for (int i=selections.size()-1; i>=0; i--) {
1576 QTreeWidgetItem currentSelection;
1577 currentSelection = selections.get(i);
1578 String guid = currentSelection.text(2);
1579 if (currentSelection.text(2).equalsIgnoreCase("STACK")) {
1580 conn.getNotebookTable().renameStacks(currentSelection.text(0), "");
1581 listManager.renameStack(currentSelection.text(0), "");
1583 conn.getNotebookTable().expungeNotebook(guid, true);
1584 listManager.deleteNotebook(guid);
1588 notebookTreeSelection();
1589 notebookTree.load(listManager.getNotebookIndex(), listManager.getLocalNotebooks());
1590 listManager.countNotebookResults(listManager.getNoteIndex());
1591 logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
1593 // A note's notebook has been updated
1594 @SuppressWarnings("unused")
1595 private void updateNoteNotebook(String guid, String notebookGuid) {
1597 // Update the list manager
1598 listManager.updateNoteNotebook(guid, notebookGuid);
1599 listManager.countNotebookResults(listManager.getNoteIndex());
1600 // notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
1602 // Find the name of the notebook
1603 String notebookName = null;
1604 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1605 if (listManager.getNotebookIndex().get(i).getGuid().equals(notebookGuid)) {
1606 notebookName = listManager.getNotebookIndex().get(i).getName();
1611 // If we found the name, update the browser window
1612 if (notebookName != null) {
1613 updateListNoteNotebook(guid, notebookName);
1614 if (guid.equals(currentNoteGuid)) {
1615 int pos = browserWindow.notebookBox.findText(notebookName);
1617 browserWindow.notebookBox.setCurrentIndex(pos);
1621 // If we're dealing with the current note, then we need to be sure and update the notebook there
1622 if (guid.equals(currentNoteGuid)) {
1623 if (currentNote != null) {
1624 currentNote.setNotebookGuid(notebookGuid);
1628 // Open/close notebooks
1629 @SuppressWarnings("unused")
1630 private void closeNotebooks() {
1631 NotebookArchive na = new NotebookArchive(listManager.getNotebookIndex(), listManager.getArchiveNotebookIndex());
1633 if (!na.okClicked())
1637 listManager.getArchiveNotebookIndex().clear();
1639 for (int i=na.getClosedBookList().count()-1; i>=0; i--) {
1640 String text = na.getClosedBookList().takeItem(i).text();
1641 for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1642 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
1643 Notebook n = listManager.getNotebookIndex().get(j);
1644 conn.getNotebookTable().setArchived(n.getGuid(),true);
1645 listManager.getArchiveNotebookIndex().add(n);
1646 j=listManager.getNotebookIndex().size();
1651 for (int i=na.getOpenBookList().count()-1; i>=0; i--) {
1652 String text = na.getOpenBookList().takeItem(i).text();
1653 for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1654 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
1655 Notebook n = listManager.getNotebookIndex().get(j);
1656 conn.getNotebookTable().setArchived(n.getGuid(),false);
1657 j=listManager.getNotebookIndex().size();
1661 notebookTreeSelection();
1662 listManager.loadNotesIndex();
1663 notebookIndexUpdated();
1664 noteIndexUpdated(false);
1665 // noteIndexUpdated(false);
1667 // Build a list of non-closed notebooks
1668 List<Notebook> nbooks = new ArrayList<Notebook>();
1669 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1670 boolean found=false;
1671 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1672 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
1676 nbooks.add(listManager.getNotebookIndex().get(i));
1679 browserWindow.setNotebookList(nbooks);
1681 // Change the notebook's icon
1682 @SuppressWarnings("unused")
1683 private void setNotebookIcon() {
1684 boolean stackSelected = false;
1685 boolean allNotebookSelected = false;
1687 QTreeWidgetItem currentSelection;
1688 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1689 if (selections.size() == 0)
1692 currentSelection = selections.get(0);
1693 String guid = currentSelection.text(2);
1694 if (guid.equalsIgnoreCase(""))
1695 allNotebookSelected = true;
1696 if (guid.equalsIgnoreCase("STACK"))
1697 stackSelected = true;
1699 QIcon currentIcon = currentSelection.icon(0);
1703 if (!stackSelected && !allNotebookSelected) {
1704 icon = conn.getNotebookTable().getIcon(guid);
1706 dialog = new SetIcon(currentIcon);
1707 dialog.setUseDefaultIcon(true);
1709 dialog = new SetIcon(icon);
1710 dialog.setUseDefaultIcon(false);
1713 if (stackSelected) {
1714 icon = conn.getSystemIconTable().getIcon(currentSelection.text(0), "STACK");
1716 icon = conn.getSystemIconTable().getIcon(currentSelection.text(0), "ALLNOTEBOOK");
1719 dialog = new SetIcon(currentIcon);
1720 dialog.setUseDefaultIcon(true);
1722 dialog = new SetIcon(icon);
1723 dialog.setUseDefaultIcon(false);
1727 if (dialog.okPressed()) {
1728 QIcon newIcon = dialog.getIcon();
1729 if (stackSelected) {
1730 conn.getSystemIconTable().setIcon(currentSelection.text(0), "STACK", newIcon, dialog.getFileType());
1731 if (newIcon == null) {
1732 newIcon = new QIcon(iconPath+"books2.png");
1734 currentSelection.setIcon(0,newIcon);
1737 if (allNotebookSelected) {
1738 conn.getSystemIconTable().setIcon(currentSelection.text(0), "ALLNOTEBOOK", newIcon, dialog.getFileType());
1739 if (newIcon == null) {
1740 newIcon = new QIcon(iconPath+"notebook-green.png");
1742 currentSelection.setIcon(0,newIcon);
1745 conn.getNotebookTable().setIcon(guid, newIcon, dialog.getFileType());
1746 if (newIcon == null) {
1747 boolean isPublished = false;;
1748 boolean found = false;
1749 for (int i=0; i<listManager.getNotebookIndex().size() && !found; i++) {
1750 if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
1751 isPublished = listManager.getNotebookIndex().get(i).isPublished();
1755 newIcon = notebookTree.findDefaultIcon(guid, currentSelection.text(1), listManager.getLocalNotebooks(), isPublished);
1757 currentSelection.setIcon(0, newIcon);
1763 //***************************************************************
1764 //***************************************************************
1765 //** These functions deal with Tag menu items
1766 //***************************************************************
1767 //***************************************************************
1768 // Add a new notebook
1769 @SuppressWarnings("unused")
1770 private void addTag() {
1771 logger.log(logger.HIGH, "Inside NeverNote.addTag");
1772 TagEdit edit = new TagEdit();
1773 edit.setTagList(listManager.getTagIndex());
1776 if (!edit.okPressed())
1779 Calendar currentTime = new GregorianCalendar();
1780 Long l = new Long(currentTime.getTimeInMillis());
1781 String randint = new String(Long.toString(l));
1783 Tag newTag = new Tag();
1784 newTag.setUpdateSequenceNum(0);
1785 newTag.setGuid(randint);
1786 newTag.setName(edit.getTag());
1787 conn.getTagTable().addTag(newTag, true);
1788 listManager.getTagIndex().add(newTag);
1789 reloadTagTree(true);
1791 logger.log(logger.HIGH, "Leaving NeverNote.addTag");
1793 @SuppressWarnings("unused")
1794 private void reloadTagTree() {
1795 reloadTagTree(false);
1797 private void reloadTagTree(boolean reload) {
1798 logger.log(logger.HIGH, "Entering NeverNote.reloadTagTree");
1799 tagIndexUpdated(reload);
1800 boolean filter = false;
1801 listManager.countTagResults(listManager.getNoteIndex());
1802 if (notebookTree.selectedItems().size() > 0
1803 && !notebookTree.selectedItems().get(0).text(0).equalsIgnoreCase("All Notebooks"))
1805 if (tagTree.selectedItems().size() > 0)
1807 tagTree.showAllTags(!filter);
1808 logger.log(logger.HIGH, "Leaving NeverNote.reloadTagTree");
1810 // Edit an existing tag
1811 @SuppressWarnings("unused")
1812 private void editTag() {
1813 logger.log(logger.HIGH, "Entering NeverNote.editTag");
1814 TagEdit edit = new TagEdit();
1815 edit.setTitle("Edit Tag");
1816 List<QTreeWidgetItem> selections = tagTree.selectedItems();
1817 QTreeWidgetItem currentSelection;
1818 currentSelection = selections.get(0);
1819 edit.setTag(currentSelection.text(0));
1820 edit.setTagList(listManager.getTagIndex());
1823 if (!edit.okPressed())
1826 String guid = currentSelection.text(2);
1827 currentSelection.setText(0,edit.getTag());
1829 for (int i=0; i<listManager.getTagIndex().size(); i++) {
1830 if (listManager.getTagIndex().get(i).getGuid().equals(guid)) {
1831 listManager.getTagIndex().get(i).setName(edit.getTag());
1832 conn.getTagTable().updateTag(listManager.getTagIndex().get(i), true);
1833 updateListTagName(guid);
1834 if (currentNote != null && currentNote.getTagGuids().contains(guid))
1835 browserWindow.setTag(getTagNamesForNote(currentNote));
1836 logger.log(logger.HIGH, "Leaving NeverNote.editTag");
1840 browserWindow.setTag(getTagNamesForNote(currentNote));
1841 logger.log(logger.HIGH, "Leaving NeverNote.editTag...");
1843 // Delete an existing tag
1844 @SuppressWarnings("unused")
1845 private void deleteTag() {
1846 logger.log(logger.HIGH, "Entering NeverNote.deleteTag");
1848 if (QMessageBox.question(this, tr("Confirmation"), tr("Delete the selected tags?"),
1849 QMessageBox.StandardButton.Yes,
1850 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1854 List<QTreeWidgetItem> selections = tagTree.selectedItems();
1855 for (int i=selections.size()-1; i>=0; i--) {
1856 QTreeWidgetItem currentSelection;
1857 currentSelection = selections.get(i);
1858 removeTagItem(currentSelection.text(2));
1860 tagIndexUpdated(true);
1862 listManager.countTagResults(listManager.getNoteIndex());
1863 // tagTree.updateCounts(listManager.getTagCounter());
1864 logger.log(logger.HIGH, "Leaving NeverNote.deleteTag");
1866 // Remove a tag tree item. Go recursively down & remove the children too
1867 private void removeTagItem(String guid) {
1868 for (int j=listManager.getTagIndex().size()-1; j>=0; j--) {
1869 String parent = listManager.getTagIndex().get(j).getParentGuid();
1870 if (parent != null && parent.equals(guid)) {
1871 //Remove this tag's children
1872 removeTagItem(listManager.getTagIndex().get(j).getGuid());
1875 //Now, remove this tag
1876 removeListTagName(guid);
1877 conn.getTagTable().expungeTag(guid, true);
1878 for (int a=0; a<listManager.getTagIndex().size(); a++) {
1879 if (listManager.getTagIndex().get(a).getGuid().equals(guid)) {
1880 listManager.getTagIndex().remove(a);
1885 // Setup the tree containing the user's tags
1886 private void initializeTagTree() {
1887 logger.log(logger.HIGH, "Entering NeverNote.initializeTagTree");
1888 // tagTree.itemSelectionChanged.connect(this, "tagTreeSelection()");
1889 tagTree.itemClicked.connect(this, "tagTreeSelection()");
1890 listManager.tagSignal.refreshTagTreeCounts.connect(tagTree, "updateCounts(List)");
1891 logger.log(logger.HIGH, "Leaving NeverNote.initializeTagTree");
1893 // Listener when a tag is selected
1894 private void tagTreeSelection() {
1895 logger.log(logger.HIGH, "Entering NeverNote.tagTreeSelection");
1898 clearAttributeFilter();
1899 clearSavedSearchFilter();
1901 menuBar.noteRestoreAction.setVisible(false);
1903 List<QTreeWidgetItem> selections = tagTree.selectedItems();
1904 QTreeWidgetItem currentSelection;
1905 selectedTagGUIDs.clear();
1906 for (int i=0; i<selections.size(); i++) {
1907 currentSelection = selections.get(i);
1908 selectedTagGUIDs.add(currentSelection.text(2));
1910 if (selections.size() > 0) {
1911 menuBar.tagEditAction.setEnabled(true);
1912 menuBar.tagDeleteAction.setEnabled(true);
1913 menuBar.tagIconAction.setEnabled(true);
1916 menuBar.tagEditAction.setEnabled(false);
1917 menuBar.tagDeleteAction.setEnabled(false);
1918 menuBar.tagIconAction.setEnabled(true);
1920 if (selectedTagGUIDs.size() == 1 && selectedTagGUIDs.get(0).equals(previousSelectedTag)) {
1921 previousSelectedTag = selectedTagGUIDs.get(0);
1922 previousSelectedTag = "";
1923 tagTree.clearSelection();
1927 if (selectedTagGUIDs.size() == 1)
1928 previousSelectedTag = selectedTagGUIDs.get(0);
1929 if (selectedTagGUIDs.size() > 1)
1930 previousSelectedTag = "";
1931 listManager.setSelectedTags(selectedTagGUIDs);
1932 listManager.loadNotesIndex();
1933 noteIndexUpdated(false);
1934 logger.log(logger.HIGH, "Leaving NeverNote.tagTreeSelection");
1936 // trigger the tag index to be refreshed
1937 @SuppressWarnings("unused")
1938 private void tagIndexUpdated() {
1939 tagIndexUpdated(true);
1941 private void tagIndexUpdated(boolean reload) {
1942 logger.log(logger.HIGH, "Entering NeverNote.tagIndexUpdated");
1943 if (selectedTagGUIDs == null)
1944 selectedTagGUIDs = new ArrayList<String>();
1945 // selectedTagGUIDs.clear(); // clear out old entries
1947 tagTree.blockSignals(true);
1949 tagTree.setIcons(conn.getTagTable().getAllIcons());
1950 tagTree.load(listManager.getTagIndex());
1952 for (int i=selectedTagGUIDs.size()-1; i>=0; i--) {
1953 boolean found = tagTree.selectGuid(selectedTagGUIDs.get(i));
1955 selectedTagGUIDs.remove(i);
1957 tagTree.blockSignals(false);
1959 browserWindow.setTag(getTagNamesForNote(currentNote));
1960 logger.log(logger.HIGH, "Leaving NeverNote.tagIndexUpdated");
1962 // Show/Hide note information
1963 private void toggleTagWindow() {
1964 logger.log(logger.HIGH, "Entering NeverNote.toggleTagWindow");
1965 if (tagTree.isVisible())
1969 menuBar.hideTags.setChecked(tagTree.isVisible());
1970 Global.saveWindowVisible("tagTree", tagTree.isVisible());
1971 logger.log(logger.HIGH, "Leaving NeverNote.toggleTagWindow");
1973 // A note's tags have been updated
1974 @SuppressWarnings("unused")
1975 private void updateNoteTags(String guid, List<String> tags) {
1976 // Save any new tags. We'll need them later.
1977 List<String> newTags = new ArrayList<String>();
1978 for (int i=0; i<tags.size(); i++) {
1979 if (conn.getTagTable().findTagByName(tags.get(i))==null)
1980 newTags.add(tags.get(i));
1983 listManager.saveNoteTags(guid, tags);
1984 listManager.countTagResults(listManager.getNoteIndex());
1985 StringBuffer names = new StringBuffer("");
1986 for (int i=0; i<tags.size(); i++) {
1987 names = names.append(tags.get(i));
1988 if (i<tags.size()-1) {
1989 names.append(Global.tagDelimeter + " ");
1992 browserWindow.setTag(names.toString());
1995 // Now, we need to add any new tags to the tag tree
1996 for (int i=0; i<newTags.size(); i++)
1997 tagTree.insertTag(newTags.get(i), conn.getTagTable().findTagByName(newTags.get(i)));
1999 // Get a string containing all tag names for a note
2000 private String getTagNamesForNote(Note n) {
2001 logger.log(logger.HIGH, "Entering NeverNote.getTagNamesForNote");
2002 if (n==null || n.getGuid() == null || n.getGuid().equals(""))
2004 StringBuffer buffer = new StringBuffer(100);
2005 Vector<String> v = new Vector<String>();
2006 List<String> guids = n.getTagGuids();
2011 for (int i=0; i<guids.size(); i++) {
2012 v.add(listManager.getTagNameByGuid(guids.get(i)));
2014 Comparator<String> comparator = Collections.reverseOrder();
2015 Collections.sort(v,comparator);
2016 Collections.reverse(v);
2018 for (int i = 0; i<v.size(); i++) {
2020 buffer.append(", ");
2021 buffer.append(v.get(i));
2024 logger.log(logger.HIGH, "Leaving NeverNote.getTagNamesForNote");
2025 return buffer.toString();
2027 // Tags were added via dropping notes from the note list
2028 @SuppressWarnings("unused")
2029 private void tagsAdded(String noteGuid, String tagGuid) {
2030 String tagName = null;
2031 for (int i=0; i<listManager.getTagIndex().size(); i++) {
2032 if (listManager.getTagIndex().get(i).getGuid().equals(tagGuid)) {
2033 tagName = listManager.getTagIndex().get(i).getName();
2034 i=listManager.getTagIndex().size();
2037 if (tagName == null)
2040 for (int i=0; i<listManager.getMasterNoteIndex().size(); i++) {
2041 if (listManager.getMasterNoteIndex().get(i).getGuid().equals(noteGuid)) {
2042 List<String> tagNames = new ArrayList<String>();
2043 tagNames.add(new String(tagName));
2044 Note n = listManager.getMasterNoteIndex().get(i);
2045 for (int j=0; j<n.getTagNames().size(); j++) {
2046 tagNames.add(new String(n.getTagNames().get(j)));
2048 listManager.getNoteTableModel().updateNoteTags(noteGuid, n.getTagGuids(), tagNames);
2049 if (n.getGuid().equals(currentNoteGuid)) {
2050 Collections.sort(tagNames);
2051 String display = "";
2052 for (int j=0; j<tagNames.size(); j++) {
2053 display = display+tagNames.get(j);
2054 if (j+2<tagNames.size())
2055 display = display+Global.tagDelimeter+" ";
2057 browserWindow.setTag(display);
2059 i=listManager.getMasterNoteIndex().size();
2064 listManager.getNoteTableModel().updateNoteSyncStatus(noteGuid, false);
2066 private void clearTagFilter() {
2067 tagTree.blockSignals(true);
2068 tagTree.clearSelection();
2069 menuBar.noteRestoreAction.setVisible(false);
2070 menuBar.tagEditAction.setEnabled(false);
2071 menuBar.tagDeleteAction.setEnabled(false);
2072 menuBar.tagIconAction.setEnabled(false);
2073 selectedTagGUIDs.clear();
2074 listManager.setSelectedTags(selectedTagGUIDs);
2075 tagTree.blockSignals(false);
2077 // Change the icon for a tag
2078 @SuppressWarnings("unused")
2079 private void setTagIcon() {
2080 QTreeWidgetItem currentSelection;
2081 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2082 if (selections.size() == 0)
2085 currentSelection = selections.get(0);
2086 String guid = currentSelection.text(2);
2088 QIcon currentIcon = currentSelection.icon(0);
2089 QIcon icon = conn.getTagTable().getIcon(guid);
2092 dialog = new SetIcon(currentIcon);
2093 dialog.setUseDefaultIcon(true);
2095 dialog = new SetIcon(icon);
2096 dialog.setUseDefaultIcon(false);
2099 if (dialog.okPressed()) {
2100 QIcon newIcon = dialog.getIcon();
2101 conn.getTagTable().setIcon(guid, newIcon, dialog.getFileType());
2102 if (newIcon == null)
2103 newIcon = new QIcon(iconPath+"tag.png");
2104 currentSelection.setIcon(0, newIcon);
2110 //***************************************************************
2111 //***************************************************************
2112 //** These functions deal with Saved Search menu items
2113 //***************************************************************
2114 //***************************************************************
2115 // Add a new notebook
2116 @SuppressWarnings("unused")
2117 private void addSavedSearch() {
2118 logger.log(logger.HIGH, "Inside NeverNote.addSavedSearch");
2119 SavedSearchEdit edit = new SavedSearchEdit();
2120 edit.setSearchList(listManager.getSavedSearchIndex());
2123 if (!edit.okPressed())
2126 Calendar currentTime = new GregorianCalendar();
2127 Long l = new Long(currentTime.getTimeInMillis());
2128 String randint = new String(Long.toString(l));
2130 SavedSearch search = new SavedSearch();
2131 search.setUpdateSequenceNum(0);
2132 search.setGuid(randint);
2133 search.setName(edit.getName());
2134 search.setQuery(edit.getQuery());
2135 search.setFormat(QueryFormat.USER);
2136 listManager.getSavedSearchIndex().add(search);
2137 conn.getSavedSearchTable().addSavedSearch(search, true);
2138 savedSearchIndexUpdated();
2139 logger.log(logger.HIGH, "Leaving NeverNote.addSavedSearch");
2141 // Edit an existing tag
2142 @SuppressWarnings("unused")
2143 private void editSavedSearch() {
2144 logger.log(logger.HIGH, "Entering NeverNote.editSavedSearch");
2145 SavedSearchEdit edit = new SavedSearchEdit();
2146 edit.setTitle(tr("Edit Search"));
2147 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2148 QTreeWidgetItem currentSelection;
2149 currentSelection = selections.get(0);
2150 String guid = currentSelection.text(1);
2151 SavedSearch s = conn.getSavedSearchTable().getSavedSearch(guid);
2152 edit.setName(currentSelection.text(0));
2153 edit.setQuery(s.getQuery());
2154 edit.setSearchList(listManager.getSavedSearchIndex());
2157 if (!edit.okPressed())
2160 List<SavedSearch> list = listManager.getSavedSearchIndex();
2161 SavedSearch search = null;
2162 boolean found = false;
2163 for (int i=0; i<list.size(); i++) {
2164 search = list.get(i);
2165 if (search.getGuid().equals(guid)) {
2172 search.setName(edit.getName());
2173 search.setQuery(edit.getQuery());
2174 conn.getSavedSearchTable().updateSavedSearch(search, true);
2175 savedSearchIndexUpdated();
2176 logger.log(logger.HIGH, "Leaving NeverNote.editSavedSearch");
2178 // Delete an existing tag
2179 @SuppressWarnings("unused")
2180 private void deleteSavedSearch() {
2181 logger.log(logger.HIGH, "Entering NeverNote.deleteSavedSearch");
2183 if (QMessageBox.question(this, "Confirmation", "Delete the selected search?",
2184 QMessageBox.StandardButton.Yes,
2185 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
2189 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2190 for (int i=selections.size()-1; i>=0; i--) {
2191 QTreeWidgetItem currentSelection;
2192 currentSelection = selections.get(i);
2193 for (int j=0; j<listManager.getSavedSearchIndex().size(); j++) {
2194 if (listManager.getSavedSearchIndex().get(j).getGuid().equals(currentSelection.text(1))) {
2195 conn.getSavedSearchTable().expungeSavedSearch(listManager.getSavedSearchIndex().get(j).getGuid(), true);
2196 listManager.getSavedSearchIndex().remove(j);
2197 j=listManager.getSavedSearchIndex().size()+1;
2200 selections.remove(i);
2202 savedSearchIndexUpdated();
2203 logger.log(logger.HIGH, "Leaving NeverNote.deleteSavedSearch");
2205 // Setup the tree containing the user's tags
2206 private void initializeSavedSearchTree() {
2207 logger.log(logger.HIGH, "Entering NeverNote.initializeSavedSearchTree");
2208 savedSearchTree.itemSelectionChanged.connect(this, "savedSearchTreeSelection()");
2209 logger.log(logger.HIGH, "Leaving NeverNote.initializeSavedSearchTree");
2211 // Listener when a tag is selected
2212 @SuppressWarnings("unused")
2213 private void savedSearchTreeSelection() {
2214 logger.log(logger.HIGH, "Entering NeverNote.savedSearchTreeSelection");
2216 clearNotebookFilter();
2219 clearAttributeFilter();
2221 String currentGuid = selectedSavedSearchGUID;
2222 menuBar.savedSearchEditAction.setEnabled(true);
2223 menuBar.savedSearchDeleteAction.setEnabled(true);
2224 menuBar.savedSearchIconAction.setEnabled(true);
2225 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2226 QTreeWidgetItem currentSelection;
2227 selectedSavedSearchGUID = "";
2228 for (int i=0; i<selections.size(); i++) {
2229 currentSelection = selections.get(i);
2230 if (currentSelection.text(1).equals(currentGuid)) {
2231 currentSelection.setSelected(false);
2233 selectedSavedSearchGUID = currentSelection.text(1);
2235 // i = selections.size() +1;
2238 // There is the potential for no notebooks to be selected if this
2239 // happens then we make it look like all notebooks were selecetd.
2240 // If that happens, just select the "all notebooks"
2241 if (selections.size()==0) {
2242 clearSavedSearchFilter();
2244 listManager.setSelectedSavedSearch(selectedSavedSearchGUID);
2246 logger.log(logger.HIGH, "Leaving NeverNote.savedSearchTreeSelection");
2248 private void clearSavedSearchFilter() {
2249 menuBar.savedSearchEditAction.setEnabled(false);
2250 menuBar.savedSearchDeleteAction.setEnabled(false);
2251 menuBar.savedSearchIconAction.setEnabled(false);
2252 savedSearchTree.blockSignals(true);
2253 savedSearchTree.clearSelection();
2254 savedSearchTree.blockSignals(false);
2255 selectedSavedSearchGUID = "";
2256 searchField.setEditText("");
2257 searchPerformed = false;
2258 listManager.setSelectedSavedSearch(selectedSavedSearchGUID);
2260 // trigger the tag index to be refreshed
2261 private void savedSearchIndexUpdated() {
2262 if (selectedSavedSearchGUID == null)
2263 selectedSavedSearchGUID = new String();
2264 savedSearchTree.blockSignals(true);
2265 savedSearchTree.setIcons(conn.getSavedSearchTable().getAllIcons());
2266 savedSearchTree.load(listManager.getSavedSearchIndex());
2267 savedSearchTree.selectGuid(selectedSavedSearchGUID);
2268 savedSearchTree.blockSignals(false);
2270 // trigger when the saved search selection changes
2271 @SuppressWarnings("unused")
2272 private void updateSavedSearchSelection() {
2273 logger.log(logger.HIGH, "Entering NeverNote.updateSavedSearchSelection()");
2275 menuBar.savedSearchEditAction.setEnabled(true);
2276 menuBar.savedSearchDeleteAction.setEnabled(true);
2277 menuBar.savedSearchIconAction.setEnabled(true);
2278 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2280 if (selections.size() > 0) {
2281 menuBar.savedSearchEditAction.setEnabled(true);
2282 menuBar.savedSearchDeleteAction.setEnabled(true);
2283 menuBar.savedSearchIconAction.setEnabled(true);
2284 selectedSavedSearchGUID = selections.get(0).text(1);
2285 SavedSearch s = conn.getSavedSearchTable().getSavedSearch(selectedSavedSearchGUID);
2286 searchField.setEditText(s.getQuery());
2288 menuBar.savedSearchEditAction.setEnabled(false);
2289 menuBar.savedSearchDeleteAction.setEnabled(false);
2290 menuBar.savedSearchIconAction.setEnabled(false);
2291 selectedSavedSearchGUID = "";
2292 searchField.setEditText("");
2294 searchFieldChanged();
2296 logger.log(logger.HIGH, "Leaving NeverNote.updateSavedSearchSelection()");
2300 // Show/Hide note information
2301 private void toggleSavedSearchWindow() {
2302 logger.log(logger.HIGH, "Entering NeverNote.toggleSavedSearchWindow");
2303 if (savedSearchTree.isVisible())
2304 savedSearchTree.hide();
2306 savedSearchTree.show();
2307 menuBar.hideSavedSearches.setChecked(savedSearchTree.isVisible());
2309 Global.saveWindowVisible("savedSearchTree", savedSearchTree.isVisible());
2310 logger.log(logger.HIGH, "Leaving NeverNote.toggleSavedSearchWindow");
2312 // Change the icon for a saved search
2313 @SuppressWarnings("unused")
2314 private void setSavedSearchIcon() {
2315 QTreeWidgetItem currentSelection;
2316 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2317 if (selections.size() == 0)
2320 currentSelection = selections.get(0);
2321 String guid = currentSelection.text(1);
2323 QIcon currentIcon = currentSelection.icon(0);
2324 QIcon icon = conn.getSavedSearchTable().getIcon(guid);
2327 dialog = new SetIcon(currentIcon);
2328 dialog.setUseDefaultIcon(true);
2330 dialog = new SetIcon(icon);
2331 dialog.setUseDefaultIcon(false);
2334 if (dialog.okPressed()) {
2335 QIcon newIcon = dialog.getIcon();
2336 conn.getSavedSearchTable().setIcon(guid, newIcon, dialog.getFileType());
2337 if (newIcon == null)
2338 newIcon = new QIcon(iconPath+"search.png");
2339 currentSelection.setIcon(0, newIcon);
2347 //***************************************************************
2348 //***************************************************************
2349 //** These functions deal with Help menu & tool menu items
2350 //***************************************************************
2351 //***************************************************************
2352 // Show database status
2353 @SuppressWarnings("unused")
2354 private void databaseStatus() {
2356 int dirty = conn.getNoteTable().getDirtyCount();
2357 int unindexed = conn.getNoteTable().getUnindexedCount();
2358 DatabaseStatus status = new DatabaseStatus();
2359 status.setUnsynchronized(dirty);
2360 status.setUnindexed(unindexed);
2361 status.setNoteCount(conn.getNoteTable().getNoteCount());
2362 status.setNotebookCount(listManager.getNotebookIndex().size());
2363 status.setSavedSearchCount(listManager.getSavedSearchIndex().size());
2364 status.setTagCount(listManager.getTagIndex().size());
2365 status.setResourceCount(conn.getNoteTable().noteResourceTable.getResourceCount());
2366 status.setWordCount(conn.getWordsTable().getWordCount());
2370 // Compact the database
2371 @SuppressWarnings("unused")
2372 private void compactDatabase() {
2373 logger.log(logger.HIGH, "Entering NeverNote.compactDatabase");
2374 if (QMessageBox.question(this, tr("Confirmation"), tr("This will free unused space in the database, "+
2375 "but please be aware that depending upon the size of your database this can be time consuming " +
2376 "and NeverNote will be unresponsive until it is complete. Do you wish to continue?"),
2377 QMessageBox.StandardButton.Yes,
2378 QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) {
2381 setMessage("Compacting database.");
2383 listManager.compactDatabase();
2385 setMessage("Database compact is complete.");
2386 logger.log(logger.HIGH, "Leaving NeverNote.compactDatabase");
2388 @SuppressWarnings("unused")
2389 private void accountInformation() {
2390 logger.log(logger.HIGH, "Entering NeverNote.accountInformation");
2391 AccountDialog dialog = new AccountDialog();
2393 logger.log(logger.HIGH, "Leaving NeverNote.accountInformation");
2395 @SuppressWarnings("unused")
2396 private void releaseNotes() {
2397 logger.log(logger.HIGH, "Entering NeverNote.releaseNotes");
2398 QDialog dialog = new QDialog(this);
2399 QHBoxLayout layout = new QHBoxLayout();
2400 QTextEdit textBox = new QTextEdit();
2401 layout.addWidget(textBox);
2402 textBox.setReadOnly(true);
2403 QFile file = new QFile(Global.getFileManager().getHomeDirPath("release.txt"));
2404 if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly,
2405 QIODevice.OpenModeFlag.Text)))
2407 textBox.setText(file.readAll().toString());
2409 dialog.setWindowTitle(tr("Release Notes"));
2410 dialog.setLayout(layout);
2412 logger.log(logger.HIGH, "Leaving NeverNote.releaseNotes");
2414 // Called when user picks Log from the help menu
2415 @SuppressWarnings("unused")
2416 private void logger() {
2417 logger.log(logger.HIGH, "Entering NeverNote.logger");
2418 QDialog dialog = new QDialog(this);
2419 QHBoxLayout layout = new QHBoxLayout();
2420 QListWidget textBox = new QListWidget();
2421 layout.addWidget(textBox);
2422 textBox.addItems(emitLog);
2424 dialog.setLayout(layout);
2425 dialog.setWindowTitle(tr("Mesasge Log"));
2427 logger.log(logger.HIGH, "Leaving NeverNote.logger");
2429 // Menu option "help/about" was selected
2430 @SuppressWarnings("unused")
2431 private void about() {
2432 logger.log(logger.HIGH, "Entering NeverNote.about");
2433 QMessageBox.about(this,
2434 tr("About NeverNote"),
2435 tr("<h4><center><b>NeverNote</b></center></h4><hr><center>Version ")
2437 +tr("<hr></center>Evernote"
2438 +"An Open Source Evernote Client.<br><br>"
2439 +"Licensed under GPL v2. <br><hr><br>"
2440 +"Evernote is copyright 2001-2010 by Evernote Corporation<br>"
2441 +"Jambi and QT are the licensed trademark of Nokia Corporation<br>"
2442 +"PDFRenderer is licened under the LGPL<br>"
2443 +"JTidy is copyrighted under the World Wide Web Consortium<br>"
2444 +"Apache Common Utilities licensed under the Apache License Version 2.0<br>"
2445 +"Jazzy is licened under the LGPL<br>"
2446 +"Java is a registered trademark of Oracle Corporation.<br><hr>"));
2447 logger.log(logger.HIGH, "Leaving NeverNote.about");
2449 // Hide the entire left hand side
2450 @SuppressWarnings("unused")
2451 private void toggleLeftSide() {
2454 hidden = !menuBar.hideLeftSide.isChecked();
2455 menuBar.hideLeftSide.setChecked(!hidden);
2457 if (notebookTree.isVisible() != hidden)
2458 toggleNotebookWindow();
2459 if (savedSearchTree.isVisible() != hidden)
2460 toggleSavedSearchWindow();
2461 if (tagTree.isVisible() != hidden)
2463 if (attributeTree.isVisible() != hidden)
2464 toggleAttributesWindow();
2465 if (trashTree.isVisible() != hidden)
2466 toggleTrashWindow();
2468 Global.saveWindowVisible("leftPanel", hidden);
2473 //***************************************************************
2474 //***************************************************************
2475 //** These functions deal with the Toolbar
2476 //***************************************************************
2477 //***************************************************************
2478 // Text in the search bar has been cleared
2479 private void searchFieldCleared() {
2481 searchField.setEditText("");
2482 saveNoteColumnPositions();
2483 saveNoteIndexWidth();
2485 // text in the search bar changed. We only use this to tell if it was cleared,
2486 // otherwise we trigger off searchFieldChanged.
2487 @SuppressWarnings("unused")
2488 private void searchFieldTextChanged(String text) {
2489 if (text.trim().equals("")) {
2490 searchFieldCleared();
2491 if (searchPerformed) {
2493 readOnlyCache.clear();
2494 listManager.setEnSearch("");
2495 ///// listManager.clearNoteIndexSearch();
2496 //noteIndexUpdated(true);
2497 listManager.loadNotesIndex();
2498 refreshEvernoteNote(true);
2499 noteIndexUpdated(false);
2501 searchPerformed = false;
2504 // Text in the toolbar has changed
2505 private void searchFieldChanged() {
2506 logger.log(logger.HIGH, "Entering NeverNote.searchFieldChanged");
2508 readOnlyCache.clear();
2509 saveNoteColumnPositions();
2510 saveNoteIndexWidth();
2511 String text = searchField.currentText();
2512 listManager.setEnSearch(text.trim());
2513 listManager.loadNotesIndex();
2514 //--->>> noteIndexUpdated(true);
2515 noteIndexUpdated(false);
2516 refreshEvernoteNote(true);
2517 searchPerformed = true;
2518 logger.log(logger.HIGH, "Leaving NeverNote.searchFieldChanged");
2521 // Build the window tool bar
2522 private void setupToolBar() {
2523 logger.log(logger.HIGH, "Entering NeverNote.setupToolBar");
2524 toolBar = addToolBar(tr("Tool Bar"));
2525 menuBar.setupToolBarVisible();
2526 if (!Global.isWindowVisible("toolBar"))
2527 toolBar.setVisible(false);
2529 toolBar.setVisible(true);
2531 prevButton = toolBar.addAction("Previous");
2532 QIcon prevIcon = new QIcon(iconPath+"back.png");
2533 prevButton.setIcon(prevIcon);
2534 prevButton.triggered.connect(this, "previousViewedAction()");
2535 togglePrevArrowButton(Global.isToolbarButtonVisible("prevArrow"));
2537 nextButton = toolBar.addAction("Next");
2538 QIcon nextIcon = new QIcon(iconPath+"forward.png");
2539 nextButton.setIcon(nextIcon);
2540 nextButton.triggered.connect(this, "nextViewedAction()");
2541 toggleNextArrowButton(Global.isToolbarButtonVisible("nextArrow"));
2543 upButton = toolBar.addAction("Up");
2544 QIcon upIcon = new QIcon(iconPath+"up.png");
2545 upButton.setIcon(upIcon);
2546 upButton.triggered.connect(this, "upAction()");
2547 toggleUpArrowButton(Global.isToolbarButtonVisible("upArrow"));
2550 downButton = toolBar.addAction("Down");
2551 QIcon downIcon = new QIcon(iconPath+"down.png");
2552 downButton.setIcon(downIcon);
2553 downButton.triggered.connect(this, "downAction()");
2554 toggleDownArrowButton(Global.isToolbarButtonVisible("downArrow"));
2556 synchronizeButton = toolBar.addAction("Synchronize");
2557 synchronizeButton.setIcon(new QIcon(iconPath+"synchronize.png"));
2558 synchronizeIconAngle = 0;
2559 synchronizeButton.triggered.connect(this, "evernoteSync()");
2560 toggleSynchronizeButton(Global.isToolbarButtonVisible("synchronize"));
2562 printButton = toolBar.addAction("Print");
2563 QIcon printIcon = new QIcon(iconPath+"print.png");
2564 printButton.setIcon(printIcon);
2565 printButton.triggered.connect(this, "printNote()");
2566 togglePrintButton(Global.isToolbarButtonVisible("print"));
2568 tagButton = toolBar.addAction("Tag");
2569 QIcon tagIcon = new QIcon(iconPath+"tag.png");
2570 tagButton.setIcon(tagIcon);
2571 tagButton.triggered.connect(browserWindow, "modifyTags()");
2572 toggleTagButton(Global.isToolbarButtonVisible("tag"));
2574 attributeButton = toolBar.addAction("Attributes");
2575 QIcon attributeIcon = new QIcon(iconPath+"attribute.png");
2576 attributeButton.setIcon(attributeIcon);
2577 attributeButton.triggered.connect(this, "toggleNoteInformation()");
2578 toggleAttributeButton(Global.isToolbarButtonVisible("attribute"));
2580 emailButton = toolBar.addAction("Email");
2581 QIcon emailIcon = new QIcon(iconPath+"email.png");
2582 emailButton.setIcon(emailIcon);
2583 emailButton.triggered.connect(this, "emailNote()");
2584 toggleEmailButton(Global.isToolbarButtonVisible("email"));
2586 deleteButton = toolBar.addAction("Delete");
2587 QIcon deleteIcon = new QIcon(iconPath+"delete.png");
2588 deleteButton.setIcon(deleteIcon);
2589 deleteButton.triggered.connect(this, "deleteNote()");
2590 toggleDeleteButton(Global.isToolbarButtonVisible("delete"));
2592 newButton = toolBar.addAction("New");
2593 QIcon newIcon = new QIcon(iconPath+"new.png");
2594 newButton.triggered.connect(this, "addNote()");
2595 newButton.setIcon(newIcon);
2596 toggleNewButton(Global.isToolbarButtonVisible("new"));
2598 allNotesButton = toolBar.addAction("All Notes");
2599 QIcon allIcon = new QIcon(iconPath+"books.png");
2600 allNotesButton.triggered.connect(this, "allNotes()");
2601 allNotesButton.setIcon(allIcon);
2602 toggleAllNotesButton(Global.isToolbarButtonVisible("allNotes"));
2604 toolBar.addSeparator();
2605 toolBar.addWidget(new QLabel(tr("Quota:")));
2606 toolBar.addWidget(quotaBar);
2607 //quotaBar.setSizePolicy(Policy.Minimum, Policy.Minimum);
2609 toolBar.addSeparator();
2612 zoomSpinner = new QSpinBox();
2613 zoomSpinner.setMinimum(10);
2614 zoomSpinner.setMaximum(1000);
2615 zoomSpinner.setAccelerated(true);
2616 zoomSpinner.setSingleStep(10);
2617 zoomSpinner.setValue(100);
2618 zoomSpinner.valueChanged.connect(this, "zoomChanged()");
2619 toolBar.addWidget(new QLabel(tr("Zoom")));
2620 toolBar.addWidget(zoomSpinner);
2622 //toolBar.addWidget(new QLabel(" "));
2623 toolBar.addSeparator();
2624 toolBar.addWidget(new QLabel(tr(" Search:")));
2625 toolBar.addWidget(searchField);
2626 QSizePolicy sizePolicy = new QSizePolicy();
2627 sizePolicy.setHorizontalPolicy(Policy.MinimumExpanding);
2628 searchField.setSizePolicy(sizePolicy);
2629 searchField.setInsertPolicy(InsertPolicy.InsertAtTop);
2631 searchClearButton = toolBar.addAction("Search Clear");
2632 QIcon searchClearIcon = new QIcon(iconPath+"searchclear.png");
2633 searchClearButton.setIcon(searchClearIcon);
2634 searchClearButton.triggered.connect(this, "searchFieldCleared()");
2635 toggleSearchClearButton(Global.isToolbarButtonVisible("searchClear"));
2637 logger.log(logger.HIGH, "Leaving NeverNote.setupToolBar");
2639 // Update the sychronize button picture
2641 public QMenu createPopupMenu() {
2642 QMenu contextMenu = super.createPopupMenu();
2644 contextMenu.addSeparator();
2645 QAction prevAction = addContextAction("prevArrow", tr("Previous Arrow"));
2646 contextMenu.addAction(prevAction);
2647 prevAction.triggered.connect(this, "togglePrevArrowButton(Boolean)");
2649 QAction nextAction = addContextAction("nextArrow", tr("Next Arrow"));
2650 contextMenu.addAction(nextAction);
2651 nextAction.triggered.connect(this, "toggleNextArrowButton(Boolean)");
2653 QAction upAction = addContextAction("upArrow", tr("Up Arrow"));
2654 contextMenu.addAction(upAction);
2655 upAction.triggered.connect(this, "toggleUpArrowButton(Boolean)");
2657 QAction downAction = addContextAction("downArrow", tr("Down Arrow"));
2658 contextMenu.addAction(downAction);
2659 downAction.triggered.connect(this, "toggleDownArrowButton(Boolean)");
2661 QAction synchronizeAction = addContextAction("synchronize", tr("Synchronize"));
2662 contextMenu.addAction(synchronizeAction);
2663 synchronizeAction.triggered.connect(this, "toggleSynchronizeButton(Boolean)");
2665 QAction printAction = addContextAction("print", tr("Print"));
2666 contextMenu.addAction(printAction);
2667 printAction.triggered.connect(this, "togglePrintButton(Boolean)");
2669 QAction tagAction = addContextAction("tag", tr("Tag"));
2670 contextMenu.addAction(tagAction);
2671 tagAction.triggered.connect(this, "toggleTagButton(Boolean)");
2673 QAction attributeAction = addContextAction("attribute", tr("Attribute"));
2674 contextMenu.addAction(attributeAction);
2675 attributeAction.triggered.connect(this, "toggleAttributeButton(Boolean)");
2677 QAction emailAction = addContextAction("email", tr("Email"));
2678 contextMenu.addAction(emailAction);
2679 emailAction.triggered.connect(this, "toggleEmailButton(Boolean)");
2681 QAction deleteAction = addContextAction("delete", tr("Delete"));
2682 contextMenu.addAction(deleteAction);
2683 deleteAction.triggered.connect(this, "toggleDeleteButton(Boolean)");
2685 QAction newAction = addContextAction("new", tr("Add"));
2686 contextMenu.addAction(newAction);
2687 newAction.triggered.connect(this, "toggleNewButton(Boolean)");
2689 QAction allNotesAction = addContextAction("allNotes", tr("All Notes"));
2690 contextMenu.addAction(allNotesAction);
2691 allNotesAction.triggered.connect(this, "toggleAllNotesButton(Boolean)");
2693 QAction searchClearAction = addContextAction("searchClear", tr("Search Clear"));
2694 contextMenu.addAction(searchClearAction);
2695 searchClearAction.triggered.connect(this, "toggleSearchClearButton(Boolean)");
2700 private QAction addContextAction(String config, String name) {
2701 QAction newAction = new QAction(this);
2702 newAction.setText(name);
2703 newAction.setCheckable(true);
2704 newAction.setChecked(Global.isToolbarButtonVisible(config));
2707 private void togglePrevArrowButton(Boolean toggle) {
2708 prevButton.setVisible(toggle);
2709 Global.saveToolbarButtonsVisible("prevArrow", toggle);
2711 private void toggleNextArrowButton(Boolean toggle) {
2712 nextButton.setVisible(toggle);
2713 Global.saveToolbarButtonsVisible("nextArrow", toggle);
2715 private void toggleUpArrowButton(Boolean toggle) {
2716 upButton.setVisible(toggle);
2717 Global.saveToolbarButtonsVisible("upArrow", toggle);
2719 private void toggleDownArrowButton(Boolean toggle) {
2720 downButton.setVisible(toggle);
2721 Global.saveToolbarButtonsVisible("downArrow", toggle);
2723 private void toggleSynchronizeButton(Boolean toggle) {
2724 synchronizeButton.setVisible(toggle);
2725 Global.saveToolbarButtonsVisible("synchronize", toggle);
2727 private void togglePrintButton(Boolean toggle) {
2728 printButton.setVisible(toggle);
2729 Global.saveToolbarButtonsVisible("print", toggle);
2731 private void toggleTagButton(Boolean toggle) {
2732 tagButton.setVisible(toggle);
2733 Global.saveToolbarButtonsVisible("tag", toggle);
2735 private void toggleAttributeButton(Boolean toggle) {
2736 attributeButton.setVisible(toggle);
2737 Global.saveToolbarButtonsVisible("attribute", toggle);
2739 private void toggleEmailButton(Boolean toggle) {
2740 emailButton.setVisible(toggle);
2741 Global.saveToolbarButtonsVisible("email", toggle);
2743 private void toggleDeleteButton(Boolean toggle) {
2744 deleteButton.setVisible(toggle);
2745 Global.saveToolbarButtonsVisible("delete", toggle);
2747 private void toggleNewButton(Boolean toggle) {
2748 newButton.setVisible(toggle);
2749 Global.saveToolbarButtonsVisible("new", toggle);
2751 private void toggleAllNotesButton(Boolean toggle) {
2752 allNotesButton.setVisible(toggle);
2753 Global.saveToolbarButtonsVisible("allNotes", toggle);
2755 private void toggleSearchClearButton(Boolean toggle) {
2756 searchClearButton.setVisible(toggle);
2757 Global.saveToolbarButtonsVisible("searchClear", toggle);
2764 @SuppressWarnings("unused")
2765 private void updateSyncButton() {
2766 /* synchronizeFrame++;
2767 if (synchronizeFrame == 4)
2768 synchronizeFrame = 0;
2769 synchronizeButton.setIcon(synchronizeAnimation.get(synchronizeFrame));
2772 QPixmap pix = new QPixmap(iconPath+"synchronize.png");
2773 QMatrix matrix = new QMatrix();
2774 synchronizeIconAngle = synchronizeIconAngle + 1.0;
2775 if (synchronizeIconAngle >= 365.0)
2776 synchronizeIconAngle = 0.0;
2777 matrix.translate(pix.size().width()/2, pix.size().height()/2);
2778 matrix.rotate( synchronizeIconAngle );
2779 matrix.translate(-pix.size().width()/2, -pix.size().height()/2);
2780 pix = pix.transformed(matrix, TransformationMode.SmoothTransformation);
2781 synchronizeButton.setIcon(pix);
2785 QPixmap pix = new QPixmap(iconPath+"synchronize.png");
2786 QPixmap rotatedPix = new QPixmap(pix.size());
2787 QPainter p = new QPainter(rotatedPix);
2789 rotatedPix.fill(toolBar.palette().color(ColorRole.Button));
2790 QSize size = pix.size();
2791 p.translate(size.width()/2, size.height()/2);
2792 synchronizeIconAngle = synchronizeIconAngle+1.0;
2793 if (synchronizeIconAngle >= 359.0)
2794 synchronizeIconAngle = 0.0;
2795 p.rotate(synchronizeIconAngle);
2796 p.setBackgroundMode(BGMode.OpaqueMode);
2797 p.translate(-size.width()/2, -size.height()/2);
2798 p.drawPixmap(0,0, pix);
2800 synchronizeButton.setIcon(rotatedPix);
2803 // Synchronize with Evernote
2804 @SuppressWarnings("unused")
2805 private void evernoteSync() {
2806 logger.log(logger.HIGH, "Entering NeverNote.evernoteSync");
2807 if (!Global.isConnected)
2809 if (Global.isConnected)
2810 synchronizeAnimationTimer.start(10);
2811 // synchronizeAnimationTimer.start(200);
2813 logger.log(logger.HIGH, "Leaving NeverNote.evernoteSync");
2815 private void updateQuotaBar() {
2816 long limit = Global.getUploadLimit();
2817 long amount = Global.getUploadAmount();
2818 if (amount>0 && limit>0) {
2819 int percent =(int)(amount*100/limit);
2820 quotaBar.setValue(percent);
2822 quotaBar.setValue(0);
2825 @SuppressWarnings("unused")
2826 private void zoomChanged() {
2827 browserWindow.getBrowser().setZoomFactor(new Double(zoomSpinner.value())/100);
2830 //****************************************************************
2831 //****************************************************************
2832 //* System Tray functions
2833 //****************************************************************
2834 //****************************************************************
2835 private void trayToggleVisible() {
2840 if (windowMaximized)
2847 @SuppressWarnings("unused")
2848 private void trayActivated(QSystemTrayIcon.ActivationReason reason) {
2849 if (reason == QSystemTrayIcon.ActivationReason.DoubleClick) {
2850 String name = QSystemTrayIcon.MessageIcon.resolve(reason.value()).name();
2851 trayToggleVisible();
2856 //***************************************************************
2857 //***************************************************************
2858 //** These functions deal with the trash tree
2859 //***************************************************************
2860 //***************************************************************
2861 // Setup the tree containing the trash.
2862 @SuppressWarnings("unused")
2863 private void trashTreeSelection() {
2864 logger.log(logger.HIGH, "Entering NeverNote.trashTreeSelection");
2866 clearNotebookFilter();
2868 clearAttributeFilter();
2869 clearSavedSearchFilter();
2871 String tempGuid = currentNoteGuid;
2873 // currentNoteGuid = "";
2874 currentNote = new Note();
2875 selectedNoteGUIDs.clear();
2876 listManager.getSelectedNotebooks().clear();
2877 listManager.getSelectedTags().clear();
2878 listManager.setSelectedSavedSearch("");
2879 browserWindow.clear();
2881 // toggle the add buttons
2882 newButton.setEnabled(!newButton.isEnabled());
2883 menuBar.noteAdd.setEnabled(newButton.isEnabled());
2884 menuBar.noteAdd.setVisible(true);
2886 List<QTreeWidgetItem> selections = trashTree.selectedItems();
2887 if (selections.size() == 0) {
2888 currentNoteGuid = trashNoteGuid;
2889 trashNoteGuid = tempGuid;
2890 Global.showDeleted = false;
2891 menuBar.noteRestoreAction.setEnabled(false);
2892 menuBar.noteRestoreAction.setVisible(false);
2895 currentNoteGuid = trashNoteGuid;
2896 trashNoteGuid = tempGuid;
2897 menuBar.noteRestoreAction.setEnabled(true);
2898 menuBar.noteRestoreAction.setVisible(true);
2899 Global.showDeleted = true;
2901 listManager.loadNotesIndex();
2902 noteIndexUpdated(false);
2903 //// browserWindow.setEnabled(newButton.isEnabled());
2904 browserWindow.setReadOnly(!newButton.isEnabled());
2905 logger.log(logger.HIGH, "Leaving NeverNote.trashTreeSelection");
2907 // Empty the trash file
2908 @SuppressWarnings("unused")
2909 private void emptyTrash() {
2910 // browserWindow.clear();
2911 listManager.emptyTrash();
2912 if (trashTree.selectedItems().size() > 0) {
2913 listManager.getSelectedNotebooks().clear();
2914 listManager.getSelectedTags().clear();
2915 listManager.setSelectedSavedSearch("");
2916 newButton.setEnabled(!newButton.isEnabled());
2917 menuBar.noteAdd.setEnabled(newButton.isEnabled());
2918 menuBar.noteAdd.setVisible(true);
2919 browserWindow.clear();
2922 clearNotebookFilter();
2923 clearSavedSearchFilter();
2924 clearAttributeFilter();
2926 Global.showDeleted = false;
2927 menuBar.noteRestoreAction.setEnabled(false);
2928 menuBar.noteRestoreAction.setVisible(false);
2930 listManager.loadNotesIndex();
2931 //--->>> noteIndexUpdated(true);
2932 noteIndexUpdated(false);
2935 // Show/Hide trash window
2936 private void toggleTrashWindow() {
2937 logger.log(logger.HIGH, "Entering NeverNote.toggleTrashWindow");
2938 if (trashTree.isVisible())
2942 menuBar.hideTrash.setChecked(trashTree.isVisible());
2944 Global.saveWindowVisible("trashTree", trashTree.isVisible());
2945 logger.log(logger.HIGH, "Leaving NeverNote.trashWindow");
2947 private void clearTrashFilter() {
2948 Global.showDeleted = false;
2949 newButton.setEnabled(true);
2950 menuBar.noteAdd.setEnabled(true);
2951 menuBar.noteAdd.setVisible(true);
2952 trashTree.blockSignals(true);
2953 trashTree.clearSelection();
2954 trashTree.blockSignals(false);
2959 //***************************************************************
2960 //***************************************************************
2961 //** These functions deal with connection settings
2962 //***************************************************************
2963 //***************************************************************
2964 // SyncRunner had a problem and things are disconnected
2965 @SuppressWarnings("unused")
2966 private void remoteErrorDisconnect() {
2967 menuBar.connectAction.setText(tr("Connect"));
2968 menuBar.connectAction.setToolTip(tr("Connect to Evernote"));
2969 menuBar.synchronizeAction.setEnabled(false);
2970 synchronizeAnimationTimer.stop();
2973 // Do a manual connect/disconnect
2974 private void remoteConnect() {
2975 logger.log(logger.HIGH, "Entering NeverNote.remoteConnect");
2977 if (Global.isConnected) {
2978 Global.isConnected = false;
2979 syncRunner.enDisconnect();
2980 setupConnectMenuOptions();
2985 AESEncrypter aes = new AESEncrypter();
2987 aes.decrypt(new FileInputStream(Global.getFileManager().getHomeDirFile("secure.txt")));
2988 } catch (FileNotFoundException e) {
2989 // File not found, so we'll just get empty strings anyway.
2991 String userid = aes.getUserid();
2992 String password = aes.getPassword();
2993 if (!userid.equals("") && !password.equals("")) {
2994 Global.username = userid;
2995 Global.password = password;
2998 // Show the login dialog box
2999 if (!Global.automaticLogin() || userid.equals("")|| password.equals("")) {
3000 LoginDialog login = new LoginDialog();
3003 if (!login.okPressed()) {
3007 Global.username = login.getUserid();
3008 Global.password = login.getPassword();
3010 syncRunner.username = Global.username;
3011 syncRunner.password = Global.password;
3012 syncRunner.userStoreUrl = Global.userStoreUrl;
3013 syncRunner.noteStoreUrl = Global.noteStoreUrl;
3014 syncRunner.noteStoreUrlBase = Global.noteStoreUrlBase;
3016 if (Global.getProxyValue("url").equals("")) {
3017 System.setProperty("http.proxyHost","") ;
3018 System.setProperty("http.proxyPort", "") ;
3019 System.setProperty("https.proxyHost","") ;
3020 System.setProperty("https.proxyPort", "") ;
3023 System.setProperty("http.proxyHost",Global.getProxyValue("url")) ;
3024 System.setProperty("http.proxyPort", Global.getProxyValue("port")) ;
3025 System.setProperty("https.proxyHost",Global.getProxyValue("url")) ;
3026 System.setProperty("https.proxyPort", Global.getProxyValue("port")) ;
3028 if (Global.getProxyValue("userid").equals("")) {
3029 Authenticator.setDefault(new Authenticator() {
3031 protected PasswordAuthentication getPasswordAuthentication() {
3033 PasswordAuthentication(Global.getProxyValue("userid"),Global.getProxyValue("password").toCharArray());
3039 syncRunner.enConnect();
3040 Global.isConnected = syncRunner.isConnected;
3042 setupConnectMenuOptions();
3043 logger.log(logger.HIGH, "Leaving NeverNote.remoteConnect");
3045 private void setupConnectMenuOptions() {
3046 logger.log(logger.HIGH, "entering NeverNote.setupConnectMenuOptions");
3047 if (!Global.isConnected) {
3048 menuBar.connectAction.setText(tr("Connect"));
3049 menuBar.connectAction.setToolTip(tr("Connect to Evernote"));
3050 menuBar.synchronizeAction.setEnabled(false);
3052 menuBar.connectAction.setText(tr("Disconnect"));
3053 menuBar.connectAction.setToolTip(tr("Disconnect from Evernote"));
3054 menuBar.synchronizeAction.setEnabled(true);
3056 logger.log(logger.HIGH, "Leaving NeverNote.setupConnectionMenuOptions");
3061 //***************************************************************
3062 //***************************************************************
3063 //** These functions deal with the GUI Attribute tree
3064 //***************************************************************
3065 //***************************************************************
3066 @SuppressWarnings("unused")
3067 private void attributeTreeClicked(QTreeWidgetItem item, Integer integer) {
3069 // clearTagFilter();
3070 // clearNotebookFilter();
3072 // clearSavedSearchFilter();
3074 if (attributeTreeSelected == null || item.nativeId() != attributeTreeSelected.nativeId()) {
3075 if (item.childCount() > 0) {
3076 item.setSelected(false);
3078 Global.createdBeforeFilter.reset();
3079 Global.createdSinceFilter.reset();
3080 Global.changedBeforeFilter.reset();
3081 Global.changedSinceFilter.reset();
3082 Global.containsFilter.reset();
3083 attributeTreeSelected = item;
3084 DateAttributeFilterTable f = null;
3085 f = findDateAttributeFilterTable(item.parent());
3087 f.select(item.parent().indexOfChild(item));
3089 Global.containsFilter.select(item.parent().indexOfChild(item));
3092 listManager.loadNotesIndex();
3093 noteIndexUpdated(false);
3096 attributeTreeSelected = null;
3097 item.setSelected(false);
3098 Global.createdBeforeFilter.reset();
3099 Global.createdSinceFilter.reset();
3100 Global.changedBeforeFilter.reset();
3101 Global.changedSinceFilter.reset();
3102 Global.containsFilter.reset();
3103 listManager.loadNotesIndex();
3104 noteIndexUpdated(false);
3106 // This determines what attribute filter we need, depending upon the selection
3107 private DateAttributeFilterTable findDateAttributeFilterTable(QTreeWidgetItem w) {
3108 if (w.parent() != null && w.childCount() > 0) {
3109 QTreeWidgetItem parent = w.parent();
3110 if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Created &&
3111 w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Since)
3112 return Global.createdSinceFilter;
3113 if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Created &&
3114 w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Before)
3115 return Global.createdBeforeFilter;
3116 if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.LastModified &&
3117 w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Since)
3118 return Global.changedSinceFilter;
3119 if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.LastModified &&
3120 w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Before)
3121 return Global.changedBeforeFilter;
3126 // Show/Hide attribute search window
3127 private void toggleAttributesWindow() {
3128 logger.log(logger.HIGH, "Entering NeverNote.toggleAttributesWindow");
3129 if (attributeTree.isVisible())
3130 attributeTree.hide();
3132 attributeTree.show();
3133 menuBar.hideAttributes.setChecked(attributeTree.isVisible());
3135 Global.saveWindowVisible("attributeTree", attributeTree.isVisible());
3136 logger.log(logger.HIGH, "Leaving NeverNote.toggleAttributeWindow");
3138 private void clearAttributeFilter() {
3139 Global.createdBeforeFilter.reset();
3140 Global.createdSinceFilter.reset();
3141 Global.changedBeforeFilter.reset();
3142 Global.changedSinceFilter.reset();
3143 Global.containsFilter.reset();
3144 attributeTreeSelected = null;
3145 attributeTree.blockSignals(true);
3146 attributeTree.clearSelection();
3147 attributeTree.blockSignals(false);
3151 //***************************************************************
3152 //***************************************************************
3153 //** These functions deal with the GUI Note index table
3154 //***************************************************************
3155 //***************************************************************
3156 // Initialize the note list table
3157 private void initializeNoteTable() {
3158 logger.log(logger.HIGH, "Entering NeverNote.initializeNoteTable");
3159 noteTableView.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection);
3160 noteTableView.selectionModel().selectionChanged.connect(this, "noteTableSelection()");
3161 logger.log(logger.HIGH, "Leaving NeverNote.initializeNoteTable");
3163 // Show/Hide trash window
3164 @SuppressWarnings("unused")
3165 private void toggleNoteListWindow() {
3166 logger.log(logger.HIGH, "Entering NeverNote.toggleNoteListWindow");
3167 if (noteTableView.isVisible())
3168 noteTableView.hide();
3170 noteTableView.show();
3171 menuBar.hideNoteList.setChecked(noteTableView.isVisible());
3173 Global.saveWindowVisible("noteList", noteTableView.isVisible());
3174 logger.log(logger.HIGH, "Leaving NeverNote.toggleNoteListWindow");
3176 // Handle the event that a user selects a note from the table
3177 @SuppressWarnings("unused")
3178 private void noteTableSelection() {
3179 logger.log(logger.HIGH, "Entering NeverNote.noteTableSelection");
3181 if (historyGuids.size() == 0) {
3182 historyGuids.add(currentNoteGuid);
3183 historyPosition = 1;
3185 noteTableView.showColumn(Global.noteTableGuidPosition);
3187 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
3188 if (!Global.isColumnVisible("guid"))
3189 noteTableView.hideColumn(Global.noteTableGuidPosition);
3191 if (selections.size() > 0) {
3193 menuBar.noteDuplicateAction.setEnabled(true);
3194 menuBar.noteOnlineHistoryAction.setEnabled(true);
3195 menuBar.noteMergeAction.setEnabled(true);
3196 selectedNoteGUIDs.clear();
3197 if (selections.size() != 1 || Global.showDeleted) {
3198 menuBar.noteDuplicateAction.setEnabled(false);
3200 if (selections.size() != 1 || !Global.isConnected) {
3201 menuBar.noteOnlineHistoryAction.setEnabled(false);
3203 if (selections.size() == 1) {
3204 menuBar.noteMergeAction.setEnabled(false);
3206 for (int i=0; i<selections.size(); i++) {
3207 int row = selections.get(i).row();
3209 upButton.setEnabled(false);
3211 upButton.setEnabled(true);
3212 if (row < listManager.getNoteTableModel().rowCount()-1)
3213 downButton.setEnabled(true);
3215 downButton.setEnabled(false);
3216 index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
3217 SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
3218 currentNoteGuid = (String)ix.values().toArray()[0];
3219 selectedNoteGUIDs.add(currentNoteGuid);
3223 nextButton.setEnabled(true);
3224 prevButton.setEnabled(true);
3226 int endPosition = historyGuids.size()-1;
3227 for (int j=historyPosition; j<=endPosition; j++) {
3228 historyGuids.remove(historyGuids.size()-1);
3230 historyGuids.add(currentNoteGuid);
3231 historyPosition = historyGuids.size();
3233 if (historyPosition <= 1)
3234 prevButton.setEnabled(false);
3235 if (historyPosition == historyGuids.size())
3236 nextButton.setEnabled(false);
3238 fromHistory = false;
3239 scrollToGuid(currentNoteGuid);
3240 refreshEvernoteNote(true);
3241 logger.log(logger.HIGH, "Leaving NeverNote.noteTableSelection");
3243 // Trigger a refresh when the note db has been updated
3244 private void noteIndexUpdated(boolean reload) {
3245 logger.log(logger.HIGH, "Entering NeverNote.noteIndexUpdated");
3247 refreshEvernoteNoteList();
3248 logger.log(logger.HIGH, "Calling note table reload in NeverNote.noteIndexUpdated() - "+reload);
3249 noteTableView.load(reload);
3250 scrollToGuid(currentNoteGuid);
3251 logger.log(logger.HIGH, "Leaving NeverNote.noteIndexUpdated");
3253 // Called when the list of notes is updated
3254 private void refreshEvernoteNoteList() {
3255 logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNoteList");
3256 browserWindow.setDisabled(false);
3257 if (selectedNoteGUIDs == null)
3258 selectedNoteGUIDs = new ArrayList<String>();
3259 selectedNoteGUIDs.clear(); // clear out old entries
3261 String saveCurrentNoteGuid = new String();
3262 String tempNoteGuid = new String();
3264 historyGuids.clear();
3265 historyPosition = 0;
3266 prevButton.setEnabled(false);
3267 nextButton.setEnabled(false);
3269 if (currentNoteGuid == null)
3270 currentNoteGuid = new String();
3272 //determine current note guid
3273 for (Note note : listManager.getNoteIndex()) {
3274 tempNoteGuid = note.getGuid();
3275 if (currentNoteGuid.equals(tempNoteGuid)) {
3276 saveCurrentNoteGuid = tempNoteGuid;
3280 if (listManager.getNoteIndex().size() == 0) {
3281 currentNoteGuid = "";
3283 browserWindow.clear();
3284 browserWindow.setDisabled(true);
3287 if (saveCurrentNoteGuid.equals("") && listManager.getNoteIndex().size() > 0) {
3288 currentNote = listManager.getNoteIndex().get(listManager.getNoteIndex().size()-1);
3289 currentNoteGuid = currentNote.getGuid();
3290 refreshEvernoteNote(true);
3292 //we can reload if note not dirty
3293 refreshEvernoteNote(!noteDirty);
3295 reloadTagTree(false);
3297 logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNoteList");
3299 // Called when the previous arrow button is clicked
3300 @SuppressWarnings("unused")
3301 private void previousViewedAction() {
3302 if (!prevButton.isEnabled())
3304 if (historyPosition == 0)
3307 if (historyPosition <= 0)
3309 String historyGuid = historyGuids.get(historyPosition-1);
3311 for (int i=0; i<noteTableView.model().rowCount(); i++) {
3312 QModelIndex modelIndex = noteTableView.model().index(i, Global.noteTableGuidPosition);
3313 if (modelIndex != null) {
3314 SortedMap<Integer, Object> ix = noteTableView.model().itemData(modelIndex);
3315 String tableGuid = (String)ix.values().toArray()[0];
3316 if (tableGuid.equals(historyGuid)) {
3317 noteTableView.selectRow(i);
3323 @SuppressWarnings("unused")
3324 private void nextViewedAction() {
3325 if (!nextButton.isEnabled())
3327 String historyGuid = historyGuids.get(historyPosition);
3330 for (int i=0; i<noteTableView.model().rowCount(); i++) {
3331 QModelIndex modelIndex = noteTableView.model().index(i, Global.noteTableGuidPosition);
3332 if (modelIndex != null) {
3333 SortedMap<Integer, Object> ix = noteTableView.model().itemData(modelIndex);
3334 String tableGuid = (String)ix.values().toArray()[0];
3335 if (tableGuid.equals(historyGuid)) {
3336 noteTableView.selectRow(i);
3342 // Called when the up arrow is clicked
3343 @SuppressWarnings("unused")
3344 private void upAction() {
3345 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
3346 int row = selections.get(0).row();
3348 noteTableView.selectRow(row-1);
3351 // Called when the down arrow is clicked
3352 @SuppressWarnings("unused")
3353 private void downAction() {
3354 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
3355 int row = selections.get(0).row();
3356 int max = listManager.getNoteTableModel().rowCount();
3358 noteTableView.selectRow(row+1);
3361 // Update a tag string for a specific note in the list
3362 @SuppressWarnings("unused")
3363 private void updateListTags(String guid, List<String> tags) {
3364 logger.log(logger.HIGH, "Entering NeverNote.updateListTags");
3365 StringBuffer tagBuffer = new StringBuffer();
3366 for (int i=0; i<tags.size(); i++) {
3367 tagBuffer.append(tags.get(i));
3368 if (i<tags.size()-1)
3369 tagBuffer.append(", ");
3372 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3373 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3374 if (modelIndex != null) {
3375 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3376 String tableGuid = (String)ix.values().toArray()[0];
3377 if (tableGuid.equals(guid)) {
3378 listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition,tagBuffer.toString());
3379 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
3380 noteTableView.proxyModel.invalidate();
3385 logger.log(logger.HIGH, "Leaving NeverNote.updateListTags");
3387 // Update a title for a specific note in the list
3388 @SuppressWarnings("unused")
3389 private void updateListAuthor(String guid, String author) {
3390 logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
3392 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3393 //QModelIndex modelIndex = noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
3394 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3395 if (modelIndex != null) {
3396 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3397 String tableGuid = (String)ix.values().toArray()[0];
3398 if (tableGuid.equals(guid)) {
3399 listManager.getNoteTableModel().setData(i, Global.noteTableAuthorPosition,author);
3400 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
3401 noteTableView.proxyModel.invalidate();
3407 logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
3409 private void updateListNoteNotebook(String guid, String notebook) {
3410 logger.log(logger.HIGH, "Entering NeverNote.updateListNoteNotebook");
3411 listManager.getNoteTableModel().updateNoteSyncStatus(guid, false);
3412 logger.log(logger.HIGH, "Leaving NeverNote.updateListNoteNotebook");
3414 // Update a title for a specific note in the list
3415 @SuppressWarnings("unused")
3416 private void updateListSourceUrl(String guid, String url) {
3417 logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
3419 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3420 //QModelIndex modelIndex = noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
3421 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3422 if (modelIndex != null) {
3423 // SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex);
3424 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3425 String tableGuid = (String)ix.values().toArray()[0];
3426 if (tableGuid.equals(guid)) {
3427 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
3428 listManager.getNoteTableModel().setData(i, Global.noteTableSourceUrlPosition,url);
3429 noteTableView.proxyModel.invalidate();
3434 logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
3436 @SuppressWarnings("unused")
3437 private void updateListGuid(String oldGuid, String newGuid) {
3438 logger.log(logger.HIGH, "Entering NeverNote.updateListTitle");
3440 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3441 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3442 if (modelIndex != null) {
3443 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3444 String tableGuid = (String)ix.values().toArray()[0];
3445 if (tableGuid.equals(oldGuid)) {
3446 listManager.getNoteTableModel().setData(i, Global.noteTableGuidPosition,newGuid);
3447 //listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
3452 logger.log(logger.HIGH, "Leaving NeverNote.updateListTitle");
3454 private void updateListTagName(String guid) {
3455 logger.log(logger.HIGH, "Entering NeverNote.updateTagName");
3457 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
3458 if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) {
3459 String newName = listManager.getTagNamesForNote(listManager.getNoteIndex().get(j));
3461 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3462 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3463 if (modelIndex != null) {
3464 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3465 String noteGuid = (String)ix.values().toArray()[0];
3466 if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) {
3467 listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition, newName);
3468 i=listManager.getNoteTableModel().rowCount();
3474 logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebook");
3476 private void removeListTagName(String guid) {
3477 logger.log(logger.HIGH, "Entering NeverNote.updateTagName");
3479 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
3480 if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) {
3481 for (int i=listManager.getNoteIndex().get(j).getTagGuids().size()-1; i>=0; i--) {
3482 if (listManager.getNoteIndex().get(j).getTagGuids().get(i).equals(guid))
3483 listManager.getNoteIndex().get(j).getTagGuids().remove(i);
3486 String newName = listManager.getTagNamesForNote(listManager.getNoteIndex().get(j));
3487 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3488 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3489 if (modelIndex != null) {
3490 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3491 String noteGuid = (String)ix.values().toArray()[0];
3492 if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) {
3493 listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition, newName);
3494 i=listManager.getNoteTableModel().rowCount();
3500 logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebook");
3502 private void updateListNotebookName(String oldName, String newName) {
3503 logger.log(logger.HIGH, "Entering NeverNote.updateListNotebookName");
3505 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3506 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableNotebookPosition);
3507 if (modelIndex != null) {
3508 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3509 String tableName = (String)ix.values().toArray()[0];
3510 if (tableName.equalsIgnoreCase(oldName)) {
3511 listManager.getNoteTableModel().setData(i, Global.noteTableNotebookPosition, newName);
3515 logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebookName");
3517 @SuppressWarnings("unused")
3518 private void updateListDateCreated(String guid, QDateTime date) {
3519 logger.log(logger.HIGH, "Entering NeverNote.updateListDateCreated");
3521 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3522 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3523 if (modelIndex != null) {
3524 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3525 String tableGuid = (String)ix.values().toArray()[0];
3526 if (tableGuid.equals(guid)) {
3527 listManager.getNoteTableModel().setData(i, Global.noteTableCreationPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
3528 noteTableView.proxyModel.invalidate();
3533 logger.log(logger.HIGH, "Leaving NeverNote.updateListDateCreated");
3535 @SuppressWarnings("unused")
3536 private void updateListDateSubject(String guid, QDateTime date) {
3537 logger.log(logger.HIGH, "Entering NeverNote.updateListDateSubject");
3539 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3540 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3541 if (modelIndex != null) {
3542 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3543 String tableGuid = (String)ix.values().toArray()[0];
3544 if (tableGuid.equals(guid)) {
3545 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
3546 listManager.getNoteTableModel().setData(i, Global.noteTableSubjectDatePosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
3547 noteTableView.proxyModel.invalidate();
3552 logger.log(logger.HIGH, "Leaving NeverNote.updateListDateCreated");
3554 private void updateListDateChanged(String guid, QDateTime date) {
3555 logger.log(logger.HIGH, "Entering NeverNote.updateListDateChanged");
3557 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3558 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3559 if (modelIndex != null) {
3560 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3561 String tableGuid = (String)ix.values().toArray()[0];
3562 if (tableGuid.equals(guid)) {
3563 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
3564 listManager.getNoteTableModel().setData(i, Global.noteTableChangedPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
3569 logger.log(logger.HIGH, "Leaving NeverNote.updateListDateChanged");
3571 private void updateListDateChanged() {
3572 logger.log(logger.HIGH, "Entering NeverNote.updateListDateChanged");
3573 QDateTime date = new QDateTime(QDateTime.currentDateTime());
3574 updateListDateChanged(currentNoteGuid, date);
3575 logger.log(logger.HIGH, "Leaving NeverNote.updateListDateChanged");
3578 private void scrollToCurrentGuid() {
3579 //scrollToGuid(currentNoteGuid);
3580 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
3581 if (selections.size() == 0)
3583 QModelIndex index = selections.get(0);
3584 int row = selections.get(0).row();
3585 String guid = (String)index.model().index(row, Global.noteTableGuidPosition).data();
3588 // Scroll to a particular index item
3589 private void scrollToGuid(String guid) {
3590 if (currentNote == null || guid == null)
3592 if (currentNote.isActive() && Global.showDeleted) {
3593 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
3594 if (!listManager.getNoteIndex().get(i).isActive()) {
3595 currentNote = listManager.getNoteIndex().get(i);
3596 currentNoteGuid = currentNote.getGuid();
3597 i = listManager.getNoteIndex().size();
3602 if (!currentNote.isActive() && !Global.showDeleted) {
3603 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
3604 if (listManager.getNoteIndex().get(i).isActive()) {
3605 currentNote = listManager.getNoteIndex().get(i);
3606 currentNoteGuid = currentNote.getGuid();
3607 i = listManager.getNoteIndex().size();
3613 for (int i=0; i<noteTableView.model().rowCount(); i++) {
3614 index = noteTableView.model().index(i, Global.noteTableGuidPosition);
3615 if (currentNoteGuid.equals(index.data())) {
3616 // noteTableView.setCurrentIndex(index);
3617 noteTableView.selectRow(i);
3618 noteTableView.scrollTo(index, ScrollHint.EnsureVisible); // This should work, but it doesn't
3619 i=listManager.getNoteTableModel().rowCount();
3622 noteTableView.repaint();
3624 // Show/Hide columns
3625 private void showColumns() {
3626 noteTableView.setColumnHidden(Global.noteTableCreationPosition, !Global.isColumnVisible("dateCreated"));
3627 noteTableView.setColumnHidden(Global.noteTableChangedPosition, !Global.isColumnVisible("dateChanged"));
3628 noteTableView.setColumnHidden(Global.noteTableSubjectDatePosition, !Global.isColumnVisible("dateSubject"));
3629 noteTableView.setColumnHidden(Global.noteTableAuthorPosition, !Global.isColumnVisible("author"));
3630 noteTableView.setColumnHidden(Global.noteTableSourceUrlPosition, !Global.isColumnVisible("sourceUrl"));
3631 noteTableView.setColumnHidden(Global.noteTableTagPosition, !Global.isColumnVisible("tags"));
3632 noteTableView.setColumnHidden(Global.noteTableNotebookPosition, !Global.isColumnVisible("notebook"));
3633 noteTableView.setColumnHidden(Global.noteTableSynchronizedPosition, !Global.isColumnVisible("synchronized"));
3634 noteTableView.setColumnHidden(Global.noteTableGuidPosition, !Global.isColumnVisible("guid"));
3635 noteTableView.setColumnHidden(Global.noteTableThumbnailPosition, !Global.isColumnVisible("thumbnail"));
3636 noteTableView.setColumnHidden(Global.noteTableTitlePosition, !Global.isColumnVisible("title"));
3638 // Title color has changed
3639 @SuppressWarnings("unused")
3640 private void titleColorChanged(Integer color) {
3641 logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
3643 QColor backgroundColor = new QColor();
3644 QColor foregroundColor = new QColor(QColor.black);
3645 backgroundColor.setRgb(color);
3647 if (backgroundColor.rgb() == QColor.black.rgb() || backgroundColor.rgb() == QColor.blue.rgb())
3648 foregroundColor.setRgb(QColor.white.rgb());
3650 if (selectedNoteGUIDs.size() == 0)
3651 selectedNoteGUIDs.add(currentNoteGuid);
3653 for (int j=0; j<selectedNoteGUIDs.size(); j++) {
3654 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3655 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3656 if (modelIndex != null) {
3657 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3658 String tableGuid = (String)ix.values().toArray()[0];
3659 if (tableGuid.equals(selectedNoteGUIDs.get(j))) {
3660 for (int k=0; k<Global.noteTableColumnCount; k++) {
3661 listManager.getNoteTableModel().setData(i, k, backgroundColor, Qt.ItemDataRole.BackgroundRole);
3662 listManager.getNoteTableModel().setData(i, k, foregroundColor, Qt.ItemDataRole.ForegroundRole);
3663 listManager.updateNoteTitleColor(selectedNoteGUIDs.get(j), backgroundColor.rgb());
3665 i=listManager.getNoteTableModel().rowCount();
3670 logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
3672 // Wide list was chosen
3673 public void narrowListView() {
3674 saveNoteColumnPositions();
3675 saveNoteIndexWidth();
3677 Global.setListView(Global.View_List_Narrow);
3679 menuBar.wideListView.blockSignals(true);
3680 menuBar.narrowListView.blockSignals(true);
3682 menuBar.wideListView.setChecked(false);
3683 menuBar.narrowListView.setChecked(true);
3685 menuBar.wideListView.blockSignals(false);
3686 menuBar.narrowListView.blockSignals(false);
3688 mainLeftRightSplitter.addWidget(noteTableView);
3689 mainLeftRightSplitter.addWidget(browserWindow);
3690 restoreWindowState(false);
3691 noteTableView.repositionColumns();
3692 noteTableView.resizeColumnWidths();
3693 noteTableView.resizeRowHeights();
3695 noteTableView.load(false);
3696 scrollToCurrentGuid();
3698 public void wideListView() {
3700 saveNoteColumnPositions();
3701 saveNoteIndexWidth();
3702 Global.setListView(Global.View_List_Wide);
3704 menuBar.wideListView.blockSignals(true);
3705 menuBar.narrowListView.blockSignals(true);
3707 menuBar.wideListView.setChecked(true);
3708 menuBar.narrowListView.setChecked(false);
3710 menuBar.wideListView.blockSignals(false);
3711 menuBar.narrowListView.blockSignals(false);
3712 browserIndexSplitter.setVisible(true);
3713 browserIndexSplitter.addWidget(noteTableView);
3714 browserIndexSplitter.addWidget(browserWindow);
3715 restoreWindowState(false);
3716 noteTableView.repositionColumns();
3717 noteTableView.resizeColumnWidths();
3718 noteTableView.resizeRowHeights();
3720 noteTableView.load(false);
3721 scrollToCurrentGuid();
3725 //***************************************************************
3726 //***************************************************************
3727 //** External editor window functions
3728 //***************************************************************
3729 //***************************************************************
3730 private void listDoubleClick() {
3732 if (externalWindows.containsKey(currentNoteGuid)) {
3733 externalWindows.get(currentNoteGuid).raise();
3736 // We have a new external editor to create
3737 QIcon appIcon = new QIcon(iconPath+"nevernote.png");
3738 ExternalBrowse newBrowser = new ExternalBrowse(conn);
3739 newBrowser.setWindowIcon(appIcon);
3740 externalWindows.put(currentNoteGuid, newBrowser);
3741 showEditorButtons(newBrowser.getBrowserWindow());
3742 loadNoteBrowserInformation(newBrowser.getBrowserWindow());
3743 setupBrowserWindowListeners(newBrowser.getBrowserWindow(), false);
3744 newBrowser.windowClosing.connect(this, "externalWindowClosing(String)");
3745 newBrowser.getBrowserWindow().noteSignal.titleChanged.connect(this, "externalWindowTitleEdited(String, String)");
3746 newBrowser.getBrowserWindow().noteSignal.tagsChanged.connect(this, "externalWindowTagsEdited(String, List)");
3747 newBrowser.contentsChanged.connect(this, "saveNoteExternalBrowser(String, String, Boolean, BrowserWindow)");
3749 browserWindow.noteSignal.tagsChanged.connect(newBrowser, "updateTags(String, List)");
3750 browserWindow.noteSignal.titleChanged.connect(newBrowser, "updateTitle(String, String)");
3751 browserWindow.noteSignal.notebookChanged.connect(newBrowser, "updateNotebook(String, String)");
3755 @SuppressWarnings("unused")
3756 private void externalWindowTitleEdited(String guid, String text) {
3757 if (guid.equals(currentNoteGuid)) {
3758 browserWindow.setTitle(text);
3761 @SuppressWarnings({ "rawtypes", "unused" })
3762 private void externalWindowTagsEdited(String guid, List values) {
3763 StringBuffer line = new StringBuffer(100);
3764 for (int i=0; i<values.size(); i++) {
3766 line.append(Global.tagDelimeter+" ");
3767 line.append(values.get(i));
3769 if (guid.equals(currentNoteGuid)) {
3770 browserWindow.setTag(line.toString());
3773 @SuppressWarnings("unused")
3774 private void externalWindowClosing(String guid) {
3775 externalWindows.remove(guid);
3780 //***************************************************************
3781 //***************************************************************
3782 //** These functions deal with Note specific things
3783 //***************************************************************
3784 //***************************************************************
3785 @SuppressWarnings("unused")
3786 private void setNoteDirty() {
3787 logger.log(logger.EXTREME, "Entering NeverNote.setNoteDirty()");
3788 // Find if the note is being edited externally. If it is, update it.
3789 if (externalWindows.containsKey(currentNoteGuid)) {
3790 QTextCodec codec = QTextCodec.codecForName("UTF-8");
3791 QByteArray unicode = codec.fromUnicode(browserWindow.getContent());
3792 ExternalBrowse window = externalWindows.get(currentNoteGuid);
3793 window.getBrowserWindow().getBrowser().setContent(unicode);
3796 // If the note is dirty, then it is unsynchronized by default.
3800 // Set the note as dirty and check if its status is synchronized in the display table
3802 for (int i=0; i<listManager.getUnsynchronizedNotes().size(); i++) {
3803 if (listManager.getUnsynchronizedNotes().get(i).equals(currentNoteGuid))
3807 // If this wasn't already marked as unsynchronized, then we need to update the table
3808 listManager.getNoteTableModel().updateNoteSyncStatus(currentNoteGuid, false);
3809 /* listManager.getUnsynchronizedNotes().add(currentNoteGuid);
3810 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3811 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3812 if (modelIndex != null) {
3813 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3814 String tableGuid = (String)ix.values().toArray()[0];
3815 if (tableGuid.equals(currentNoteGuid)) {
3816 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
3822 logger.log(logger.EXTREME, "Leaving NeverNote.setNoteDirty()");
3824 @SuppressWarnings("unused")
3825 private void saveNoteExternalBrowser(String guid, String content, Boolean save, BrowserWindow browser) {
3826 QTextCodec codec = QTextCodec.codecForName("UTF-8");
3827 QByteArray unicode = codec.fromUnicode(content);
3828 noteCache.remove(guid);
3829 noteCache.put(guid, unicode.toString());
3830 if (guid.equals(currentNoteGuid)) {
3832 browserWindow.getBrowser().setContent(unicode);
3835 thumbnailRunner.addWork("GENERATE "+ guid);
3836 saveNote(guid, browser);
3840 private void saveNote() {
3842 saveNote(currentNoteGuid, browserWindow);
3843 thumbnailRunner.addWork("GENERATE "+ currentNoteGuid);
3847 private void saveNote(String guid, BrowserWindow window) {
3848 logger.log(logger.EXTREME, "Inside NeverNote.saveNote()");
3849 logger.log(logger.EXTREME, "Note is dirty.");
3852 logger.log(logger.EXTREME, "Saving to cache");
3853 QTextCodec codec = QTextCodec.codecForLocale();
3854 // QTextDecoder decoder = codec.makeDecoder();
3855 codec = QTextCodec.codecForName("UTF-8");
3856 QByteArray unicode = codec.fromUnicode(window.getContent());
3857 noteCache.put(guid, unicode.toString());
3859 logger.log(logger.EXTREME, "updating list manager");
3860 listManager.updateNoteContent(guid, window.getContent());
3861 logger.log(logger.EXTREME, "Updating title");
3862 listManager.updateNoteTitle(guid, window.getTitle());
3863 updateListDateChanged();
3865 logger.log(logger.EXTREME, "Looking through note index for refreshed note");
3866 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
3867 if (listManager.getNoteIndex().get(i).getGuid().equals(guid)) {
3868 currentNote = listManager.getNoteIndex().get(i);
3869 i = listManager.getNoteIndex().size();
3874 // Get a note from Evernote (and put it in the browser)
3875 private void refreshEvernoteNote(boolean reload) {
3876 logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNote");
3877 if (Global.disableViewing) {
3878 browserWindow.setEnabled(false);
3882 if (!Global.showDeleted)
3883 browserWindow.setReadOnly(false);
3884 Global.cryptCounter =0;
3885 if (currentNoteGuid.equals("")) {
3886 browserWindow.setReadOnly(true);
3894 browserWindow.loadingData(true);
3896 currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true);
3897 if (currentNote == null)
3900 loadNoteBrowserInformation(browserWindow);
3903 private void loadNoteBrowserInformation(BrowserWindow browser) {
3904 NoteFormatter formatter = new NoteFormatter(logger, conn, tempFiles);
3905 formatter.setNote(currentNote, Global.pdfPreview());
3906 formatter.setHighlight(listManager.getEnSearch());
3908 if (!noteCache.containsKey(currentNoteGuid) || conn.getNoteTable().isThumbnailNeeded(currentNoteGuid)) {
3909 js = new QByteArray();
3910 // We need to prepend the note with <HEAD></HEAD> or encoded characters are ugly
3911 js.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
3912 js.append("<style type=\"text/css\">.en-crypt-temp { border-collapse:collapse; border-style:solid; border-color:blue; padding:0.0mm 0.0mm 0.0mm 0.0mm; }</style>");
3913 js.append("<style type=\"text/css\">en-hilight { background-color: rgb(255,255,0) }</style>");
3914 js.append("<style> img { max-width:100%; }</style>");
3915 js.append("<style type=\"text/css\">en-spell { text-decoration: none; border-bottom: dotted 1px #cc0000; }</style>");
3916 js.append("</head>");
3917 formatter.setNote(currentNote, Global.pdfPreview());
3918 js.append(formatter.rebuildNoteHTML());
3919 js.append("</HTML>");
3920 js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml.dtd'>", "");
3921 js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml2.dtd'>", "");
3922 js.replace("<?xml version='1.0' encoding='UTF-8'?>", "");
3923 browser.getBrowser().setContent(js);
3924 noteCache.put(currentNoteGuid, js.toString());
3926 if (formatter.resourceError)
3927 resourceErrorMessage();
3928 inkNote = formatter.readOnly;
3930 readOnlyCache.put(currentNoteGuid, true);
3932 logger.log(logger.HIGH, "Note content is being pulled from the cache");
3933 String cachedContent = formatter.modifyCachedTodoTags(noteCache.get(currentNoteGuid));
3934 js = new QByteArray(cachedContent);
3935 browser.getBrowser().setContent(js);
3936 if (readOnlyCache.containsKey(currentNoteGuid))
3939 if (conn.getNoteTable().isThumbnailNeeded(currentNoteGuid)) {
3940 thumbnailHTMLReady(currentNoteGuid, js, Global.calculateThumbnailZoom(js.toString()));
3944 browser.getBrowser().page().setContentEditable(!inkNote); // We don't allow editing of ink notes
3945 browser.setNote(currentNote);
3947 // Build a list of non-closed notebooks
3948 List<Notebook> nbooks = new ArrayList<Notebook>();
3949 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
3950 boolean found=false;
3951 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
3952 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
3956 nbooks.add(listManager.getNotebookIndex().get(i));
3959 browser.setNotebookList(nbooks);
3960 browser.setTitle(currentNote.getTitle());
3961 browser.setTag(getTagNamesForNote(currentNote));
3962 browser.setAuthor(currentNote.getAttributes().getAuthor());
3964 browser.setAltered(currentNote.getUpdated());
3965 browser.setCreation(currentNote.getCreated());
3966 if (currentNote.getAttributes().getSubjectDate() > 0)
3967 browser.setSubjectDate(currentNote.getAttributes().getSubjectDate());
3969 browser.setSubjectDate(currentNote.getCreated());
3970 browser.setUrl(currentNote.getAttributes().getSourceURL());
3971 browser.setAllTags(listManager.getTagIndex());
3972 browser.setCurrentTags(currentNote.getTagNames());
3974 scrollToGuid(currentNoteGuid);
3976 browser.loadingData(false);
3977 if (thumbnailViewer.isActiveWindow())
3980 logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNote");
3982 // Save a generated thumbnail
3983 private void toggleNoteInformation() {
3984 logger.log(logger.HIGH, "Entering NeverNote.toggleNoteInformation");
3985 browserWindow.toggleInformation();
3986 menuBar.noteAttributes.setChecked(browserWindow.isExtended());
3987 Global.saveWindowVisible("noteInformation", browserWindow.isExtended());
3988 logger.log(logger.HIGH, "Leaving NeverNote.toggleNoteInformation");
3990 // Listener triggered when a print button is pressed
3991 @SuppressWarnings("unused")
3992 private void printNote() {
3993 logger.log(logger.HIGH, "Entering NeverNote.printNote");
3995 QPrintDialog dialog = new QPrintDialog();
3996 if (dialog.exec() == QDialog.DialogCode.Accepted.value()) {
3997 QPrinter printer = dialog.printer();
3998 browserWindow.getBrowser().print(printer);
4000 logger.log(logger.HIGH, "Leaving NeverNote.printNote");
4003 // Listener triggered when the email button is pressed
4004 @SuppressWarnings("unused")
4005 private void emailNote() {
4006 logger.log(logger.HIGH, "Entering NeverNote.emailNote");
4008 if (Desktop.isDesktopSupported()) {
4009 Desktop desktop = Desktop.getDesktop();
4011 String text2 = browserWindow.getContentsToEmail();
4012 QUrl url = new QUrl("mailto:");
4013 url.addQueryItem("subject", currentNote.getTitle());
4014 // url.addQueryItem("body", QUrl.toPercentEncoding(text2).toString());
4015 url.addQueryItem("body", text2);
4016 QDesktopServices.openUrl(url);
4020 if (desktop.isSupported(Desktop.Action.MAIL)) {
4021 URI uriMailTo = null;
4023 //String text = browserWindow.getBrowser().page().currentFrame().toPlainText();
4024 String text = browserWindow.getContentsToEmail();
4025 //text = "<b>" +text +"</b>";
4026 uriMailTo = new URI("mailto", "&SUBJECT="+currentNote.getTitle()
4027 +"&BODY=" +text, null);
4028 uriMailTo = new URI("mailto", "&SUBJECT="+currentNote.getTitle()
4029 +"&ATTACHMENT=d:/test.pdf", null);
4030 desktop.mail(uriMailTo);
4031 } catch (URISyntaxException e) {
4032 e.printStackTrace();
4033 } catch (IOException e) {
4034 e.printStackTrace();
4041 logger.log(logger.HIGH, "Leaving NeverNote.emailNote");
4043 // Reindex all notes
4044 @SuppressWarnings("unused")
4045 private void fullReindex() {
4046 logger.log(logger.HIGH, "Entering NeverNote.fullReindex");
4047 // If we are deleting non-trash notes
4048 if (currentNote == null) return;
4049 if (currentNote.getDeleted() == 0) {
4050 if (QMessageBox.question(this, tr("Confirmation"), tr("This will cause all notes & attachments to be reindexed, "+
4051 "but please be aware that depending upon the size of your database updating all these records " +
4052 "can be time consuming and NeverNote will be unresponsive until it is complete. Do you wish to continue?"),
4053 QMessageBox.StandardButton.Yes,
4054 QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) {
4059 setMessage(tr("Marking notes for reindex."));
4060 conn.getNoteTable().reindexAllNotes();
4061 conn.getNoteTable().noteResourceTable.reindexAll();
4062 setMessage(tr("Database will be reindexed."));
4064 logger.log(logger.HIGH, "Leaving NeverNote.fullRefresh");
4066 // Listener when a user wants to reindex a specific note
4067 @SuppressWarnings("unused")
4068 private void reindexNote() {
4069 logger.log(logger.HIGH, "Entering NeverNote.reindexNote");
4070 for (int i=0; i<selectedNoteGUIDs.size(); i++) {
4071 conn.getNoteTable().setIndexNeeded(selectedNoteGUIDs.get(i), true);
4073 if (selectedNotebookGUIDs.size() > 1)
4074 setMessage(tr("Notes will be reindexed."));
4076 setMessage(tr("Note will be reindexed."));
4077 logger.log(logger.HIGH, "Leaving NeverNote.reindexNote");
4080 @SuppressWarnings("unused")
4081 private void deleteNote() {
4082 logger.log(logger.HIGH, "Entering NeverNote.deleteNote");
4083 if (currentNote == null)
4085 if (currentNoteGuid.equals(""))
4088 // If we are deleting non-trash notes
4089 if (currentNote.isActive()) {
4090 if (Global.verifyDelete()) {
4091 if (QMessageBox.question(this, tr("Confirmation"), tr("Delete selected note(s)?"),
4092 QMessageBox.StandardButton.Yes,
4093 QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) {
4097 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals(""))
4098 selectedNoteGUIDs.add(currentNoteGuid);
4099 for (int i=0; i<selectedNoteGUIDs.size(); i++) {
4100 listManager.deleteNote(selectedNoteGUIDs.get(i));
4103 // If we are deleting from the trash.
4104 if (Global.verifyDelete()) {
4105 if (QMessageBox.question(this, "Confirmation", "Permanently delete selected note(s)?",
4106 QMessageBox.StandardButton.Yes,
4107 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
4111 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals(""))
4112 selectedNoteGUIDs.add(currentNoteGuid);
4113 for (int i=selectedNoteGUIDs.size()-1; i>=0; i--) {
4114 for (int j=listManager.getNoteTableModel().rowCount()-1; j>=0; j--) {
4115 QModelIndex modelIndex = listManager.getNoteTableModel().index(j, Global.noteTableGuidPosition);
4116 if (modelIndex != null) {
4117 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4118 String tableGuid = (String)ix.values().toArray()[0];
4119 if (tableGuid.equals(selectedNoteGUIDs.get(i))) {
4120 listManager.getNoteTableModel().removeRow(j);
4125 listManager.expungeNote(selectedNoteGUIDs.get(i));
4128 currentNoteGuid = "";
4129 listManager.loadNotesIndex();
4130 noteIndexUpdated(false);
4131 refreshEvernoteNote(true);
4132 scrollToGuid(currentNoteGuid);
4133 logger.log(logger.HIGH, "Leaving NeverNote.deleteNote");
4136 @SuppressWarnings("unused")
4137 private void addNote() {
4138 logger.log(logger.HIGH, "Inside NeverNote.addNote");
4139 // browserWindow.setEnabled(true);
4140 browserWindow.setReadOnly(false);
4142 Calendar currentTime = new GregorianCalendar();
4143 StringBuffer noteString = new StringBuffer(100);
4144 noteString.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
4145 "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">\n" +
4148 if (Global.overrideDefaultFont()) {
4149 noteString.append("<font face=\"" +Global.getDefaultFont() +"\" >");
4150 noteString.append("<span style=\"font-size:" +Global.getDefaultFontSize() +"pt;\">");
4151 noteString.append("<br clear=\"none\" />\n");
4152 noteString.append("</span>\n</font>\n");
4154 noteString.append("<br clear=\"none\" />\n");
4155 noteString.append("</en-note>");
4157 Long l = new Long(currentTime.getTimeInMillis());
4158 String randint = new String(Long.toString(l));
4160 // Find a notebook. We first look for a selected notebook (the "All Notebooks" one doesn't count).
4162 // for the first non-archived notebook. Finally, if nothing else we
4163 // pick the first notebook in the list.
4164 String notebook = null;
4165 listManager.getNotebookIndex().get(0).getGuid();
4166 List<QTreeWidgetItem> selectedNotebook = notebookTree.selectedItems();
4167 if (selectedNotebook.size() > 0 && !selectedNotebook.get(0).text(0).equalsIgnoreCase("All Notebooks")) {
4168 QTreeWidgetItem currentSelectedNotebook = selectedNotebook.get(0);
4169 notebook = currentSelectedNotebook.text(2);
4171 boolean found = false;
4172 List<Notebook> goodNotebooks = new ArrayList<Notebook>();
4173 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
4174 boolean match = false;
4175 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
4176 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid())) {
4178 j = listManager.getArchiveNotebookIndex().size();
4182 goodNotebooks.add(listManager.getNotebookIndex().get(i).deepCopy());
4184 // Now we have a list of good notebooks, so we can look for the default
4186 for (int i=0; i<goodNotebooks.size(); i++) {
4187 if (goodNotebooks.get(i).isDefaultNotebook()) {
4188 notebook = goodNotebooks.get(i).getGuid();
4190 i = goodNotebooks.size();
4194 if (goodNotebooks.size() > 0 && !found)
4195 notebook = goodNotebooks.get(0).getGuid();
4198 notebook = listManager.getNotebookIndex().get(0).getGuid();
4201 Note newNote = new Note();
4202 newNote.setUpdateSequenceNum(0);
4203 newNote.setGuid(randint);
4204 newNote.setNotebookGuid(notebook);
4205 newNote.setTitle("");
4206 newNote.setContent(noteString.toString());
4207 newNote.setDeleted(0);
4208 newNote.setCreated(System.currentTimeMillis());
4209 newNote.setUpdated(System.currentTimeMillis());
4210 newNote.setActive(true);
4211 NoteAttributes na = new NoteAttributes();
4212 na.setLatitude(0.0);
4213 na.setLongitude(0.0);
4214 na.setAltitude(0.0);
4215 newNote.setAttributes(new NoteAttributes());
4216 newNote.setTagGuids(new ArrayList<String>());
4217 newNote.setTagNames(new ArrayList<String>());
4219 // If new notes are to be created based upon the selected tags, then we need to assign the tags
4220 if (Global.newNoteWithSelectedTags()) {
4221 List<QTreeWidgetItem> selections = tagTree.selectedItems();
4222 QTreeWidgetItem currentSelection;
4223 for (int i=0; i<selections.size(); i++) {
4224 currentSelection = selections.get(i);
4225 newNote.getTagGuids().add(currentSelection.text(2));
4226 newNote.getTagNames().add(currentSelection.text(0));
4230 conn.getNoteTable().addNote(newNote, true);
4231 listManager.getUnsynchronizedNotes().add(newNote.getGuid());
4232 listManager.addNote(newNote);
4233 // noteTableView.insertRow(newNote, true, -1);
4235 currentNote = newNote;
4236 currentNoteGuid = currentNote.getGuid();
4237 refreshEvernoteNote(true);
4238 listManager.countNotebookResults(listManager.getNoteIndex());
4239 browserWindow.titleLabel.setFocus();
4240 browserWindow.titleLabel.selectAll();
4241 // notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
4243 // If the window is hidden, then we want to popup this in an external window &
4246 logger.log(logger.HIGH, "Leaving NeverNote.addNote");
4248 // Restore a note from the trash;
4249 @SuppressWarnings("unused")
4250 private void restoreNote() {
4252 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals(""))
4253 selectedNoteGUIDs.add(currentNoteGuid);
4254 for (int i=0; i<selectedNoteGUIDs.size(); i++) {
4255 listManager.restoreNote(selectedNoteGUIDs.get(i));
4257 currentNoteGuid = "";
4258 listManager.loadNotesIndex();
4259 noteIndexUpdated(false);
4262 // Search a note for specific txt
4263 @SuppressWarnings("unused")
4264 private void findText() {
4266 find.setFocusOnTextField();
4268 @SuppressWarnings("unused")
4269 private void doFindText() {
4270 browserWindow.getBrowser().page().findText(find.getText(), find.getFlags());
4273 @SuppressWarnings("unused")
4274 private void updateNoteTitle(String guid, String title) {
4275 listManager.setNoteSynchronized(guid, false);
4277 // Signal received that note content has changed. Normally we just need the guid to remove
4278 // it from the cache.
4279 @SuppressWarnings("unused")
4280 private void invalidateNoteCache(String guid, String content) {
4281 String v = noteCache.remove(guid);
4282 if (content != null) {
4283 //noteCache.put(guid, content);
4286 // Signal received that a note guid has changed
4287 @SuppressWarnings("unused")
4288 private void noteGuidChanged(String oldGuid, String newGuid) {
4289 if (noteCache.containsKey(oldGuid)) {
4290 String cache = noteCache.get(oldGuid);
4291 noteCache.put(newGuid, cache);
4292 noteCache.remove(oldGuid);
4294 listManager.updateNoteGuid(oldGuid, newGuid, false);
4295 if (currentNoteGuid.equals(oldGuid)) {
4296 if (currentNote != null)
4297 currentNote.setGuid(newGuid);
4298 currentNoteGuid = newGuid;
4300 if (externalWindows.containsKey(oldGuid)) {
4301 ExternalBrowse b = externalWindows.get(oldGuid);
4302 externalWindows.remove(oldGuid);
4303 b.getBrowserWindow().getNote().setGuid(newGuid);
4304 externalWindows.put(newGuid, b);
4306 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
4307 if (listManager.getNoteIndex().get(i).getGuid().equals(newGuid)) {
4308 noteTableView.proxyModel.addGuid(newGuid);
4309 i=listManager.getNoteIndex().size();
4312 if (listManager.getNoteTableModel().titleColors.containsKey(oldGuid)) {
4313 int color = listManager.getNoteTableModel().titleColors.get(oldGuid);
4314 listManager.getNoteTableModel().titleColors.put(newGuid, color);
4315 listManager.getNoteTableModel().titleColors.remove(oldGuid);
4319 // Toggle the note editor button bar
4320 private void toggleEditorButtonBar() {
4321 if (browserWindow.buttonsVisible) {
4322 browserWindow.hideButtons();
4323 menuBar.showEditorBar.setChecked(browserWindow.buttonsVisible);
4324 // Global.saveWindowVisible("editorButtonBar", browserWindow.buttonsVisible);
4326 browserWindow.buttonsVisible = true;
4327 showEditorButtons(browserWindow);
4329 Global.saveWindowVisible("editorButtonBar", browserWindow.buttonsVisible);
4331 // Show editor buttons
4332 private void showEditorButtons(BrowserWindow browser) {
4333 browser.buttonLayout.setVisible(true);
4334 browser.undoAction.setVisible(false);
4336 browser.undoButton.setVisible(false);
4338 browser.undoAction.setVisible(Global.isEditorButtonVisible("undo"));
4339 browser.redoAction.setVisible(Global.isEditorButtonVisible("redo"));
4340 browser.cutAction.setVisible(Global.isEditorButtonVisible("cut"));
4341 browser.copyAction.setVisible(Global.isEditorButtonVisible("copy"));
4342 browser.pasteAction.setVisible(Global.isEditorButtonVisible("paste"));
4343 browser.strikethroughAction.setVisible(Global.isEditorButtonVisible("strikethrough"));
4344 browser.underlineAction.setVisible(Global.isEditorButtonVisible("underline"));
4345 browser.boldAction.setVisible(Global.isEditorButtonVisible("bold"));
4346 browser.italicAction.setVisible(Global.isEditorButtonVisible("italic"));
4347 browser.hlineAction.setVisible(Global.isEditorButtonVisible("hline"));
4348 browser.indentAction.setVisible(Global.isEditorButtonVisible("indent"));
4349 browser.outdentAction.setVisible(Global.isEditorButtonVisible("outdent"));
4350 browser.bulletListAction.setVisible(Global.isEditorButtonVisible("bulletList"));
4351 browser.numberListAction.setVisible(Global.isEditorButtonVisible("numberList"));
4352 browser.fontListAction.setVisible(Global.isEditorButtonVisible("font"));
4353 browser.fontSizeAction.setVisible(Global.isEditorButtonVisible("fontSize"));
4354 browser.fontColorAction.setVisible(Global.isEditorButtonVisible("fontColor"));
4355 browser.fontHilightAction.setVisible(Global.isEditorButtonVisible("fontHilight"));
4356 browser.leftAlignAction.setVisible(Global.isEditorButtonVisible("alignLeft"));
4357 browser.centerAlignAction.setVisible(Global.isEditorButtonVisible("alignCenter"));
4358 browser.rightAlignAction.setVisible(Global.isEditorButtonVisible("alignRight"));
4359 browser.spellCheckAction.setVisible(Global.isEditorButtonVisible("spellCheck"));
4360 browser.todoAction.setVisible(Global.isEditorButtonVisible("todo"));
4362 private void duplicateNote(String guid) {
4364 Note oldNote = conn.getNoteTable().getNote(guid, true, true, false, false, false);
4365 List<Resource> resList = conn.getNoteTable().noteResourceTable.getNoteResources(guid, true);
4366 oldNote.setContent(conn.getNoteTable().getNoteContentBinary(guid));
4367 oldNote.setResources(resList);
4368 duplicateNote(oldNote);
4370 private void duplicateNote(Note oldNote) {
4372 // Now that we have a good notebook guid, we need to move the conflicting note
4373 // to the local notebook
4374 Calendar currentTime = new GregorianCalendar();
4375 Long l = new Long(currentTime.getTimeInMillis());
4376 String newGuid = new String(Long.toString(l));
4378 Note newNote = oldNote.deepCopy();
4379 newNote.setUpdateSequenceNum(0);
4380 newNote.setGuid(newGuid);
4381 newNote.setDeleted(0);
4382 newNote.setActive(true);
4383 List<Resource> resList = oldNote.getResources();
4384 if (resList == null)
4385 resList = new ArrayList<Resource>();
4387 for (int i=0; i<resList.size(); i++) {
4389 while (l == prevGuid) {
4390 currentTime = new GregorianCalendar();
4391 l = new Long(currentTime.getTimeInMillis());
4394 String newResGuid = new String(Long.toString(l));
4395 resList.get(i).setNoteGuid(newGuid);
4396 resList.get(i).setGuid(newResGuid);
4397 resList.get(i).setUpdateSequenceNum(0);
4398 resList.get(i).setActive(true);
4399 conn.getNoteTable().noteResourceTable.saveNoteResource(new Resource(resList.get(i).deepCopy()), true);
4401 newNote.setResources(resList);
4402 listManager.addNote(newNote);
4403 conn.getNoteTable().addNote(newNote, true);
4404 listManager.getUnsynchronizedNotes().add(newNote.getGuid());
4405 noteTableView.insertRow(newNote, true, -1);
4406 listManager.countNotebookResults(listManager.getNoteIndex());
4410 @SuppressWarnings("unused")
4411 private void allNotes() {
4412 clearAttributeFilter();
4413 clearNotebookFilter();
4414 clearSavedSearchFilter();
4417 searchField.clear();
4418 if (Global.mimicEvernoteInterface) {
4419 notebookTree.selectGuid("");
4421 notebookTreeSelection();
4424 @SuppressWarnings("unused")
4425 private void mergeNotes() {
4426 logger.log(logger.HIGH, "Merging notes");
4429 String masterGuid = null;
4430 List<String> sources = new ArrayList<String>();
4432 for (int i=0; i<noteTableView.selectionModel().selectedRows().size(); i++) {
4433 int r = noteTableView.selectionModel().selectedRows().get(i).row();
4434 index = noteTableView.proxyModel.index(r, Global.noteTableGuidPosition);
4435 SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
4437 masterGuid = (String)ix.values().toArray()[0];
4439 sources.add((String)ix.values().toArray()[0]);
4442 logger.log(logger.EXTREME, "Master guid=" +masterGuid);
4443 logger.log(logger.EXTREME, "Children count: "+sources.size());
4444 mergeNoteContents(masterGuid, sources);
4445 currentNoteGuid = masterGuid;
4446 noteIndexUpdated(false);
4447 refreshEvernoteNote(true);
4450 private void mergeNoteContents(String targetGuid, List<String> sources) {
4451 Note target = conn.getNoteTable().getNote(targetGuid, true, false, false, false, false);
4452 String newContent = target.getContent();
4453 newContent = newContent.replace("</en-note>", "<br></br>");
4455 for (int i=0; i<sources.size(); i++) {
4456 Note source = conn.getNoteTable().getNote(sources.get(i), true, true, false, false, false);
4457 if (source.isSetTitle()) {
4458 newContent = newContent +("<table bgcolor=\"lightgrey\"><tr><td><font size=\"6\"><b>" +source.getTitle() +"</b></font></td></tr></table>");
4460 String sourceContent = source.getContent();
4461 logger.log(logger.EXTREME, "Merging contents into note");
4462 logger.log(logger.EXTREME, sourceContent);
4463 logger.log(logger.EXTREME, "End of content");
4464 int startOfNote = sourceContent.indexOf("<en-note>");
4465 sourceContent = sourceContent.substring(startOfNote+9);
4466 int endOfNote = sourceContent.indexOf("</en-note>");
4467 sourceContent = sourceContent.substring(0,endOfNote);
4468 newContent = newContent + sourceContent;
4469 logger.log(logger.EXTREME, "New note content");
4470 logger.log(logger.EXTREME, newContent);
4471 logger.log(logger.EXTREME, "End of content");
4472 for (int j=0; j<source.getResourcesSize(); j++) {
4473 logger.log(logger.EXTREME, "Reassigning resource: "+source.getResources().get(j).getGuid());
4474 Resource r = source.getResources().get(j);
4475 Resource newRes = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), true);
4477 Calendar currentTime = new GregorianCalendar();
4478 Long l = new Long(currentTime.getTimeInMillis());
4482 while (l == prevGuid) {
4483 currentTime = new GregorianCalendar();
4484 l = new Long(currentTime.getTimeInMillis());
4486 String newResGuid = new String(Long.toString(l));
4487 newRes.setNoteGuid(targetGuid);
4488 newRes.setGuid(newResGuid);
4489 newRes.setUpdateSequenceNum(0);
4490 newRes.setActive(true);
4491 conn.getNoteTable().noteResourceTable.saveNoteResource(newRes, true);
4494 logger.log(logger.EXTREME, "Updating note");
4495 conn.getNoteTable().updateNoteContent(targetGuid, newContent +"</en-note>");
4496 for (int i=0; i<sources.size(); i++) {
4497 logger.log(logger.EXTREME, "Deleting note " +sources.get(i));
4498 listManager.deleteNote(sources.get(i));
4500 logger.log(logger.EXTREME, "Exiting merge note");
4502 // A resource within a note has had a guid change
4503 @SuppressWarnings("unused")
4504 private void noteResourceGuidChanged(String noteGuid, String oldGuid, String newGuid) {
4505 if (!oldGuid.equals(newGuid))
4506 Global.resourceMap.put(oldGuid, newGuid);
4508 // View a thumbnail of the note
4509 public void thumbnailView() {
4511 String thumbnailName = Global.getFileManager().getResDirPath("thumbnail-" + currentNoteGuid + ".png");
4512 QFile thumbnail = new QFile(thumbnailName);
4513 if (!thumbnail.exists()) {
4515 QImage img = new QImage();
4516 img.loadFromData(conn.getNoteTable().getThumbnail(currentNoteGuid));
4517 thumbnailViewer.setThumbnail(img);
4519 thumbnailViewer.setThumbnail(thumbnailName);
4520 if (!thumbnailViewer.isVisible())
4521 thumbnailViewer.showFullScreen();
4523 // An error happened while saving a note. Inform the user
4524 @SuppressWarnings("unused")
4525 private void saveRunnerError(String guid, String msg) {
4527 String title = "*Unknown*";
4528 for (int i=0; i<listManager.getMasterNoteIndex().size(); i++) {
4529 if (listManager.getMasterNoteIndex().get(i).getGuid().equals(guid)) {
4530 title = listManager.getMasterNoteIndex().get(i).getTitle();
4531 i=listManager.getMasterNoteIndex().size();
4534 msg = "An error has happened while saving the note \"" +title+
4535 "\".\n\nThis is probably due to a document that is too complex for Nevernote to process. "+
4536 "As a result, changes to the note may not be saved properly in the database."+
4537 "\n\nA cached copy is being preserved so you can recover any data, but data may" +
4538 "\nbe lost. Please review the note to recover any critical data before restarting.";
4540 QMessageBox.information(this, tr("Error Saving Note"), tr(msg));
4543 private void thumbnailHTMLReady(String guid, QByteArray html, Integer zoom) {
4544 logger.log(logger.HIGH, "Entering thumnailHTMLReady()");
4545 logger.log(logger.HIGH, "Thumbnail ready for " +guid);
4546 // Find an idle preview object
4547 for (int i=0; i<thumbGenerators.size(); i++) {
4548 if (thumbGenerators.get(i).mutex.tryLock()) {
4549 logger.log(logger.EXTREME, "Idle generator found - loading thumbnail for " +guid);
4550 thumbGenerators.get(i).loadContent(guid, html, zoom);
4554 if (thumbGenerators.size() >= 1) {
4555 logger.log(logger.EXTREME, "No available thumbnail generators. Aborting " +guid);
4559 logger.log(logger.EXTREME, "Creating new thumbnail generator " +guid);
4560 Thumbnailer preview = new Thumbnailer(logger, conn, listManager, thumbnailRunner);
4561 thumbGenerators.add(preview);
4563 if (preview.mutex.tryLock()) {
4564 logger.log(logger.EXTREME, "Loading thumbnail for " +guid);
4565 preview.loadContent(guid, html, zoom);
4567 logger.log(logger.HIGH, "Exiting thumnailHTMLReady()");
4572 //**********************************************************
4573 //**********************************************************
4574 //* Online user actions
4575 //**********************************************************
4576 //**********************************************************
4577 private void setupOnlineMenu() {
4578 if (!Global.isConnected) {
4579 menuBar.noteOnlineHistoryAction.setEnabled(false);
4582 menuBar.noteOnlineHistoryAction.setEnabled(true);
4585 @SuppressWarnings("unused")
4586 private void viewNoteHistory() {
4587 if (currentNoteGuid == null || currentNoteGuid.equals(""))
4589 if (currentNote.getUpdateSequenceNum() == 0) {
4590 setMessage(tr("Note has never been synchronized."));
4591 QMessageBox.information(this, tr("Error"), tr("This note has never been sent to Evernote, so there is no history."));
4595 setMessage(tr("Getting Note History"));
4597 Note currentOnlineNote = null;
4600 if (Global.isPremium())
4601 versions = syncRunner.noteStore.listNoteVersions(syncRunner.authToken, currentNoteGuid);
4603 versions = new ArrayList<NoteVersionId>();
4604 currentOnlineNote = syncRunner.noteStore.getNote(syncRunner.authToken, currentNoteGuid, true, true, false, false);
4605 } catch (EDAMUserException e) {
4606 setMessage("EDAMUserException: " +e.getMessage());
4608 } catch (EDAMSystemException e) {
4609 setMessage("EDAMSystemException: " +e.getMessage());
4611 } catch (EDAMNotFoundException e) {
4612 setMessage(tr("Note not found on server."));
4613 QMessageBox.information(this, "Error", "This note could not be found on Evernote's servers.");
4615 } catch (TException e) {
4616 setMessage("EDAMTransactionException: " +e.getMessage());
4620 // If we've gotten this far, we have a good note.
4621 if (historyWindow == null) {
4622 historyWindow = new OnlineNoteHistory(logger, conn);
4623 historyWindow.historyCombo.activated.connect(this, "reloadHistoryWindow(String)");
4624 historyWindow.restoreAsNew.clicked.connect(this, "restoreHistoryNoteAsNew()");
4625 historyWindow.restore.clicked.connect(this, "restoreHistoryNote()");
4627 historyWindow.historyCombo.clear();
4629 boolean isDirty = conn.getNoteTable().isNoteDirty(currentNoteGuid);
4630 if (currentNote.getUpdateSequenceNum() != currentOnlineNote.getUpdateSequenceNum())
4632 historyWindow.setCurrent(isDirty);
4634 loadHistoryWindowContent(currentOnlineNote);
4635 historyWindow.load(versions);
4636 setMessage(tr("History retrieved"));
4638 historyWindow.exec();
4640 private Note reloadHistoryWindow(String selection) {
4642 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
4643 String dateTimeFormat = new String(fmt);
4644 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
4648 for (int i=0; i<versions.size(); i++) {
4649 StringBuilder versionDate = new StringBuilder(simple.format(versions.get(i).getSaved()));
4650 if (versionDate.toString().equals(selection))
4654 if (index > -1 || selection.indexOf("Current") > -1) {
4655 Note historyNote = null;
4658 usn = versions.get(index).getUpdateSequenceNum();
4659 historyNote = syncRunner.noteStore.getNoteVersion(syncRunner.authToken, currentNoteGuid, usn, true, true, true);
4661 historyNote = syncRunner.noteStore.getNote(syncRunner.authToken, currentNoteGuid, true,true,true,true);
4662 } catch (EDAMUserException e) {
4663 setMessage("EDAMUserException: " +e.getMessage());
4666 } catch (EDAMSystemException e) {
4667 setMessage("EDAMSystemException: " +e.getMessage());
4670 } catch (EDAMNotFoundException e) {
4671 setMessage("EDAMNotFoundException: " +e.getMessage());
4674 } catch (TException e) {
4675 setMessage("EDAMTransactionException: " +e.getMessage());
4681 if (historyNote != null)
4682 historyWindow.setContent(historyNote);
4688 private void loadHistoryWindowContent(Note note) {
4689 note.setUpdateSequenceNum(0);
4690 historyWindow.setContent(note);
4692 @SuppressWarnings("unused")
4693 private void restoreHistoryNoteAsNew() {
4694 setMessage(tr("Restoring as new note."));
4695 duplicateNote(reloadHistoryWindow(historyWindow.historyCombo.currentText()));
4696 setMessage(tr("Note has been restored as a new note."));
4698 @SuppressWarnings("unused")
4699 private void restoreHistoryNote() {
4700 setMessage(tr("Restoring note."));
4701 Note n = reloadHistoryWindow(historyWindow.historyCombo.currentText());
4702 conn.getNoteTable().expungeNote(n.getGuid(), true, false);
4705 for (int i=0; i<n.getResourcesSize(); i++) {
4706 n.getResources().get(i).setActive(true);
4707 conn.getNoteTable().noteResourceTable.saveNoteResource(n.getResources().get(i), true);
4709 listManager.addNote(n);
4710 conn.getNoteTable().addNote(n, true);
4711 refreshEvernoteNote(true);
4712 setMessage(tr("Note has been restored."));
4717 //**********************************************************
4718 //**********************************************************
4719 //* XML Modifying methods
4720 //**********************************************************
4721 //**********************************************************
4722 // An error has happended fetching a resource. let the user know
4723 private void resourceErrorMessage() {
4726 QMessageBox.information(this, tr("DOUGH!!!"), tr("Well, this is embarrassing."+
4727 "\n\nSome attachments or images for this note appear to be missing from my database.\n"+
4728 "In a perfect world this wouldn't happen, but it has.\n" +
4729 "It is embarasing when a program like me, designed to save all your\n"+
4730 "precious data, has a problem finding data.\n\n" +
4731 "I guess life isn't fair, but I'll survive. Somehow...\n\n" +
4732 "In the mean time, I'm not going to let you make changes to this note.\n" +
4733 "Don't get angry. I'm doing it to prevent you from messing up\n"+
4734 "this note on the Evernote servers. Sorry."+
4735 "\n\nP.S. You might want to re-synchronize to see if it corrects this problem.\nWho knows, you might get lucky."));
4737 browserWindow.setReadOnly(true);
4743 //**********************************************************
4744 //**********************************************************
4746 //**********************************************************
4747 //**********************************************************
4748 // We should now do a sync with Evernote
4749 private void syncTimer() {
4750 logger.log(logger.EXTREME, "Entering NeverNote.syncTimer()");
4751 syncRunner.syncNeeded = true;
4752 syncRunner.disableUploads = Global.disableUploads;
4754 logger.log(logger.EXTREME, "Leaving NeverNote.syncTimer()");
4756 private void syncStart() {
4757 logger.log(logger.EXTREME, "Entering NeverNote.syncStart()");
4759 if (!syncRunning && Global.isConnected) {
4760 syncRunner.setConnected(true);
4761 syncRunner.setKeepRunning(Global.keepRunning);
4762 syncRunner.syncDeletedContent = Global.synchronizeDeletedContent();
4764 if (syncThreadsReady > 0) {
4765 saveNoteIndexWidth();
4766 saveNoteColumnPositions();
4767 if (syncRunner.addWork("SYNC")) {
4769 syncRunner.syncNeeded = true;
4774 logger.log(logger.EXTREME, "Leaving NeverNote.syncStart");
4776 @SuppressWarnings("unused")
4777 private void syncThreadComplete(Boolean refreshNeeded) {
4778 setMessage(tr("Finalizing Synchronization"));
4780 syncRunning = false;
4781 syncRunner.syncNeeded = false;
4782 synchronizeAnimationTimer.stop();
4783 synchronizeButton.setIcon(new QIcon(iconPath+"synchronize.png"));
4785 if (currentNote == null) {
4786 currentNote = conn.getNoteTable().getNote(currentNoteGuid, false, false, false, false, true);
4788 listManager.setUnsynchronizedNotes(conn.getNoteTable().getUnsynchronizedGUIDs());
4789 noteIndexUpdated(false);
4790 noteTableView.selectionModel().blockSignals(true);
4791 scrollToGuid(currentNoteGuid);
4792 noteTableView.selectionModel().blockSignals(false);
4793 refreshEvernoteNote(false);
4794 scrollToGuid(currentNoteGuid);
4796 if (!syncRunner.error)
4797 setMessage(tr("Synchronization Complete"));
4799 setMessage(tr("Synchronization completed with errors. Please check the log for details."));
4800 logger.log(logger.MEDIUM, "Sync complete.");
4802 public void saveUploadAmount(long t) {
4803 Global.saveUploadAmount(t);
4805 public void saveUserInformation(User user) {
4806 Global.saveUserInformation(user);
4808 public void saveEvernoteUpdateCount(int i) {
4809 Global.saveEvernoteUpdateCount(i);
4811 public void refreshLists() {
4812 logger.log(logger.EXTREME, "Entering NeverNote.refreshLists");
4814 listManager.refreshLists(currentNote, noteDirty, browserWindow.getContent());
4815 tagIndexUpdated(true);
4816 notebookIndexUpdated();
4817 savedSearchIndexUpdated();
4818 listManager.loadNotesIndex();
4820 noteTableView.selectionModel().blockSignals(true);
4821 noteIndexUpdated(true);
4822 noteTableView.selectionModel().blockSignals(false);
4823 logger.log(logger.EXTREME, "Leaving NeverNote.refreshLists");
4827 @SuppressWarnings("unused")
4828 private void authTimer() {
4829 Calendar cal = Calendar.getInstance();
4831 // If we are not connected let's get out of here
4832 if (!Global.isConnected)
4835 // If this is the first time through, then we need to set this
4836 // if (syncRunner.authRefreshTime == 0 || cal.getTimeInMillis() > syncRunner.authRefreshTime)
4837 // syncRunner.authRefreshTime = cal.getTimeInMillis();
4839 // long now = new Date().getTime();
4840 // if (now > Global.authRefreshTime && Global.isConnected) {
4841 syncRunner.authRefreshNeeded = true;
4845 @SuppressWarnings("unused")
4846 private void authRefreshComplete(boolean goodSync) {
4847 logger.log(logger.EXTREME, "Entering NeverNote.authRefreshComplete");
4848 Global.isConnected = syncRunner.isConnected;
4850 // authTimer.start((int)syncRunner.authTimeRemaining/4);
4851 authTimer.start(1000*60*15);
4852 logger.log(logger.LOW, "Authentication token has been renewed");
4853 // setMessage("Authentication token has been renewed.");
4855 authTimer.start(1000*60*5);
4856 logger.log(logger.LOW, "Authentication token renew has failed - retry in 5 minutes.");
4857 // setMessage("Authentication token renew has failed - retry in 5 minutes.");
4859 logger.log(logger.EXTREME, "Leaving NeverNote.authRefreshComplete");
4863 @SuppressWarnings("unused")
4864 private synchronized void indexTimer() {
4865 logger.log(logger.EXTREME, "Index timer activated. Sync running="+syncRunning);
4868 // Look for any unindexed notes. We only refresh occasionally
4869 // and do one at a time to keep overhead down.
4870 if (!indexDisabled && indexRunner.getWorkQueueSize() == 0) {
4871 List<String> notes = conn.getNoteTable().getNextUnindexed(1);
4872 String unindexedNote = null;
4873 if (notes.size() > 0)
4874 unindexedNote = notes.get(0);
4875 if (unindexedNote != null && Global.keepRunning) {
4876 indexNoteContent(unindexedNote);
4878 if (notes.size()>0) {
4879 indexTimer.setInterval(100);
4882 List<String> unindexedResources = conn.getNoteTable().noteResourceTable.getNextUnindexed(1);
4883 if (unindexedResources.size() > 0 && indexRunner.getWorkQueueSize() == 0) {
4884 String unindexedResource = unindexedResources.get(0);
4885 if (unindexedResource != null && Global.keepRunning) {
4886 indexNoteResource(unindexedResource);
4889 if (unindexedResources.size() > 0) {
4890 indexTimer.setInterval(100);
4893 indexTimer.setInterval(indexTime);
4896 setMessage(tr("Index completed."));
4897 logger.log(logger.LOW, "Indexing has completed.");
4898 indexRunning = false;
4899 indexTimer.setInterval(indexTime);
4902 logger.log(logger.EXTREME, "Leaving neverNote index timer");
4904 private synchronized void indexNoteContent(String unindexedNote) {
4905 logger.log(logger.EXTREME, "Entering NeverNote.indexNoteContent()");
4906 logger.log(logger.MEDIUM, "Unindexed Note found: "+unindexedNote);
4907 indexRunner.setIndexType(indexRunner.CONTENT);
4908 indexRunner.addWork("CONTENT "+unindexedNote);
4909 if (!indexRunning) {
4910 setMessage(tr("Indexing notes."));
4911 logger.log(logger.LOW, "Beginning to index note contents.");
4912 indexRunning = true;
4914 logger.log(logger.EXTREME, "Leaving NeverNote.indexNoteContent()");
4916 private synchronized void indexNoteResource(String unindexedResource) {
4917 logger.log(logger.EXTREME, "Leaving NeverNote.indexNoteResource()");
4918 indexRunner.addWork(new String("RESOURCE "+unindexedResource));
4919 if (!indexRunning) {
4920 setMessage(tr("Indexing notes."));
4921 indexRunning = true;
4923 logger.log(logger.EXTREME, "Leaving NeverNote.indexNoteResource()");
4925 @SuppressWarnings("unused")
4926 private void indexThreadComplete(String guid) {
4927 logger.log(logger.MEDIUM, "Index complete for "+guid);
4929 @SuppressWarnings("unused")
4930 private synchronized void toggleNoteIndexing() {
4931 logger.log(logger.HIGH, "Entering NeverNote.toggleIndexing");
4932 indexDisabled = !indexDisabled;
4934 setMessage(tr("Indexing is now enabled."));
4936 setMessage(tr("Indexing is now disabled."));
4937 menuBar.disableIndexing.setChecked(indexDisabled);
4938 logger.log(logger.HIGH, "Leaving NeverNote.toggleIndexing");
4941 @SuppressWarnings("unused")
4942 private void threadMonitorCheck() {
4947 alive = listManager.threadCheck(Global.tagCounterThreadId);
4950 if (tagDeadCount > MAX)
4951 QMessageBox.information(this, tr("A thread his died."), tr("It appears as the tag counter thread has died. I recommend "+
4952 "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry."));
4956 alive = listManager.threadCheck(Global.notebookCounterThreadId);
4958 notebookThreadDeadCount++;
4959 QMessageBox.information(this, tr("A thread his died."), tr("It appears as the notebook counter thread has died. I recommend "+
4960 "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry."));
4962 notebookThreadDeadCount=0;
4964 alive = listManager.threadCheck(Global.trashCounterThreadId);
4967 QMessageBox.information(this, tr("A thread his died."), ("It appears as the trash counter thread has died. I recommend "+
4968 "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry."));
4972 alive = listManager.threadCheck(Global.saveThreadId);
4974 saveThreadDeadCount++;
4975 QMessageBox.information(this, tr("A thread his died."), tr("It appears as the note saver thread has died. I recommend "+
4976 "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry."));
4978 saveThreadDeadCount=0;
4980 if (!syncThread.isAlive()) {
4981 syncThreadDeadCount++;
4982 QMessageBox.information(this, tr("A thread his died."), tr("It appears as the synchronization thread has died. I recommend "+
4983 "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry."));
4985 syncThreadDeadCount=0;
4987 if (!indexThread.isAlive()) {
4988 indexThreadDeadCount++;
4989 QMessageBox.information(this, tr("A thread his died."), tr("It appears as the index thread has died. I recommend "+
4990 "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry."));
4992 indexThreadDeadCount=0;
4997 private void thumbnailTimer() {
4998 if (Global.enableThumbnails() && conn.getNoteTable().getThumbnailNeededCount() > 1) {
4999 thumbnailTimer.setInterval(10*1000);
5000 thumbnailRunner.addWork("SCAN");
5002 thumbnailTimer.setInterval(60*1000);
5006 //**************************************************
5007 //* Backup & Restore
5008 //**************************************************
5009 @SuppressWarnings("unused")
5010 private void databaseBackup() {
5011 QFileDialog fd = new QFileDialog(this);
5012 fd.setFileMode(FileMode.AnyFile);
5013 fd.setConfirmOverwrite(true);
5014 fd.setWindowTitle(tr("Backup Database"));
5015 fd.setFilter(tr("NeverNote Export (*.nnex);;All Files (*.*)"));
5016 fd.setAcceptMode(AcceptMode.AcceptSave);
5017 fd.setDirectory(System.getProperty("user.home"));
5018 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
5024 setMessage(tr("Backing up database"));
5026 // conn.backupDatabase(Global.getUpdateSequenceNumber(), Global.getSequenceDate());
5028 ExportData noteWriter = new ExportData(conn, true);
5029 String fileName = fd.selectedFiles().get(0);
5031 if (!fileName.endsWith(".nnex"))
5032 fileName = fileName +".nnex";
5033 noteWriter.exportData(fileName);
5034 setMessage(tr("Database backup completed."));
5039 @SuppressWarnings("unused")
5040 private void databaseRestore() {
5041 if (QMessageBox.question(this, tr("Confirmation"),
5042 tr("This is used to restore a database from backups.\n" +
5043 "It is HIGHLY recommened that this only be used to populate\n" +
5044 "an empty database. Restoring into a database that\n already has data" +
5045 " can cause problems.\n\nAre you sure you want to continue?"),
5046 QMessageBox.StandardButton.Yes,
5047 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
5052 QFileDialog fd = new QFileDialog(this);
5053 fd.setFileMode(FileMode.ExistingFile);
5054 fd.setConfirmOverwrite(true);
5055 fd.setWindowTitle(tr("Restore Database"));
5056 fd.setFilter(tr("NeverNote Export (*.nnex);;All Files (*.*)"));
5057 fd.setAcceptMode(AcceptMode.AcceptOpen);
5058 fd.setDirectory(System.getProperty("user.home"));
5059 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
5065 setMessage(tr("Restoring database"));
5066 ImportData noteReader = new ImportData(conn, true);
5067 noteReader.importData(fd.selectedFiles().get(0));
5069 if (noteReader.lastError != 0) {
5070 setMessage(noteReader.getErrorMessage());
5071 logger.log(logger.LOW, "Restore problem: " +noteReader.lastError);
5076 listManager.loadNoteTitleColors();
5078 refreshEvernoteNote(true);
5079 setMessage(tr("Database has been restored."));
5082 @SuppressWarnings("unused")
5083 private void exportNotes() {
5084 QFileDialog fd = new QFileDialog(this);
5085 fd.setFileMode(FileMode.AnyFile);
5086 fd.setConfirmOverwrite(true);
5087 fd.setWindowTitle(tr("Backup Database"));
5088 fd.setFilter(tr("NeverNote Export (*.nnex);;All Files (*.*)"));
5089 fd.setAcceptMode(AcceptMode.AcceptSave);
5090 fd.setDirectory(System.getProperty("user.home"));
5091 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
5097 setMessage(tr("Exporting Notes"));
5100 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals(""))
5101 selectedNoteGUIDs.add(currentNoteGuid);
5103 ExportData noteWriter = new ExportData(conn, false, selectedNoteGUIDs);
5104 String fileName = fd.selectedFiles().get(0);
5106 if (!fileName.endsWith(".nnex"))
5107 fileName = fileName +".nnex";
5108 noteWriter.exportData(fileName);
5109 setMessage(tr("Export completed."));
5115 @SuppressWarnings("unused")
5116 private void importNotes() {
5117 QFileDialog fd = new QFileDialog(this);
5118 fd.setFileMode(FileMode.ExistingFile);
5119 fd.setConfirmOverwrite(true);
5120 fd.setWindowTitle(tr("Import Notes"));
5121 fd.setFilter(tr("NeverNote Export (*.nnex);;All Files (*.*)"));
5122 fd.setAcceptMode(AcceptMode.AcceptOpen);
5123 fd.setDirectory(System.getProperty("user.home"));
5124 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
5130 setMessage("Importing Notes");
5133 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals(""))
5134 selectedNoteGUIDs.add(currentNoteGuid);
5136 ImportData noteReader = new ImportData(conn, false);
5137 String fileName = fd.selectedFiles().get(0);
5139 if (!fileName.endsWith(".nnex"))
5140 fileName = fileName +".nnex";
5141 if (selectedNotebookGUIDs != null && selectedNotebookGUIDs.size() > 0)
5142 noteReader.setNotebookGuid(selectedNotebookGUIDs.get(0));
5144 noteReader.setNotebookGuid(listManager.getNotebookIndex().get(0).getGuid());
5146 noteReader.importData(fileName);
5148 if (noteReader.lastError != 0) {
5149 setMessage(noteReader.getErrorMessage());
5150 logger.log(logger.LOW, "Import problem: " +noteReader.lastError);
5155 listManager.loadNoteTitleColors();
5157 refreshEvernoteNote(false);
5158 setMessage(tr("Notes have been imported."));
5161 setMessage("Import completed.");
5168 //**************************************************
5169 //* Duplicate a note
5170 //**************************************************
5171 @SuppressWarnings("unused")
5172 private void duplicateNote() {
5174 duplicateNote(currentNoteGuid);
5179 //**************************************************
5181 //**************************************************
5182 public void setupFolderImports() {
5183 List<WatchFolderRecord> records = conn.getWatchFolderTable().getAll();
5185 if (importKeepWatcher == null)
5186 importKeepWatcher = new QFileSystemWatcher();
5187 if (importDeleteWatcher == null) {
5188 importDeleteWatcher = new QFileSystemWatcher();
5189 for (int i=0; i<records.size(); i++) {
5190 if (!records.get(i).keep)
5191 folderImportDelete(records.get(i).folder);
5197 // importKeepWatcher.addPath(records.get(i).folder.replace('\\', '/'));
5198 for (int i=0; i<records.size(); i++) {
5199 if (records.get(i).keep)
5200 importKeepWatcher.addPath(records.get(i).folder);
5202 importDeleteWatcher.addPath(records.get(i).folder);
5205 importKeepWatcher.directoryChanged.connect(this, "folderImportKeep(String)");
5206 importDeleteWatcher.directoryChanged.connect(this, "folderImportDelete(String)");
5208 // Look at the files already there so we don't import them again if a new file is created
5209 if (importedFiles == null) {
5210 importedFiles = new ArrayList<String>();
5211 for (int j=0; j<records.size(); j++) {
5212 QDir dir = new QDir(records.get(j).folder);
5213 List<QFileInfo> list = dir.entryInfoList();
5214 for (int k=0; k<list.size(); k++) {
5215 if (list.get(k).isFile())
5216 importedFiles.add(list.get(k).absoluteFilePath());
5221 public void folderImport() {
5222 List<WatchFolderRecord> recs = conn.getWatchFolderTable().getAll();
5223 WatchFolder dialog = new WatchFolder(recs, listManager.getNotebookIndex());
5225 if (!dialog.okClicked())
5228 // We have some sort of update.
5229 if (importKeepWatcher.directories().size() > 0)
5230 importKeepWatcher.removePaths(importKeepWatcher.directories());
5231 if (importDeleteWatcher.directories().size() > 0)
5232 importDeleteWatcher.removePaths(importDeleteWatcher.directories());
5234 conn.getWatchFolderTable().expungeAll();
5235 // Start building from the table
5236 for (int i=0; i<dialog.table.rowCount(); i++) {
5237 QTableWidgetItem item = dialog.table.item(i, 0);
5238 String dir = item.text();
5239 item = dialog.table.item(i, 1);
5240 String notebook = item.text();
5241 item = dialog.table.item(i, 2);
5243 if (item.text().equalsIgnoreCase("Keep"))
5248 String guid = conn.getNotebookTable().findNotebookByName(notebook);
5249 conn.getWatchFolderTable().addWatchFolder(dir, guid, keep, 0);
5251 setupFolderImports();
5254 public void folderImportKeep(String dirName) throws NoSuchAlgorithmException {
5256 String whichOS = System.getProperty("os.name");
5257 if (whichOS.contains("Windows"))
5258 dirName = dirName.replace('/','\\');
5260 FileImporter importer = new FileImporter(logger, conn);
5262 QDir dir = new QDir(dirName);
5263 List<QFileInfo> list = dir.entryInfoList();
5264 String notebook = conn.getWatchFolderTable().getNotebook(dirName);
5266 for (int i=0; i<list.size(); i++){
5268 boolean redundant = false;
5269 // Check if we've already imported this one or if it existed before
5270 for (int j=0; j<importedFiles.size(); j++) {
5271 if (importedFiles.get(j).equals(list.get(i).absoluteFilePath()))
5276 importer.setFileInfo(list.get(i));
5277 importer.setFileName(list.get(i).absoluteFilePath());
5280 if (list.get(i).isFile() && importer.isValidType()) {
5282 if (!importer.importFile()) {
5283 // If we can't get to the file, it is probably locked. We'll try again later.
5284 logger.log(logger.LOW, "Unable to save externally edited file. Saving for later.");
5285 importFilesKeep.add(list.get(i).absoluteFilePath());
5289 Note newNote = importer.getNote();
5290 newNote.setNotebookGuid(notebook);
5291 newNote.setTitle(dir.at(i));
5292 listManager.addNote(newNote);
5293 conn.getNoteTable().addNote(newNote, true);
5294 listManager.getUnsynchronizedNotes().add(newNote.getGuid());
5295 noteTableView.insertRow(newNote, true, -1);
5296 listManager.updateNoteContent(newNote.getGuid(), importer.getNoteContent());
5297 listManager.countNotebookResults(listManager.getNoteIndex());
5298 importedFiles.add(list.get(i).absoluteFilePath());
5306 public void folderImportDelete(String dirName) {
5308 String whichOS = System.getProperty("os.name");
5309 if (whichOS.contains("Windows"))
5310 dirName = dirName.replace('/','\\');
5312 FileImporter importer = new FileImporter(logger, conn);
5313 QDir dir = new QDir(dirName);
5314 List<QFileInfo> list = dir.entryInfoList();
5315 String notebook = conn.getWatchFolderTable().getNotebook(dirName);
5317 for (int i=0; i<list.size(); i++){
5318 importer.setFileInfo(list.get(i));
5319 importer.setFileName(list.get(i).absoluteFilePath());
5321 if (list.get(i).isFile() && importer.isValidType()) {
5323 if (!importer.importFile()) {
5324 // If we can't get to the file, it is probably locked. We'll try again later.
5325 logger.log(logger.LOW, "Unable to save externally edited file. Saving for later.");
5326 importFilesKeep.add(list.get(i).absoluteFilePath());
5330 Note newNote = importer.getNote();
5331 newNote.setNotebookGuid(notebook);
5332 newNote.setTitle(dir.at(i));
5333 listManager.addNote(newNote);
5334 conn.getNoteTable().addNote(newNote, true);
5335 listManager.getUnsynchronizedNotes().add(newNote.getGuid());
5336 noteTableView.insertRow(newNote, true, -1);
5337 listManager.updateNoteContent(newNote.getGuid(), importer.getNoteContent());
5338 listManager.countNotebookResults(listManager.getNoteIndex());
5339 dir.remove(dir.at(i));
5345 //**************************************************
5347 //**************************************************
5348 private void externalFileEdited(String fileName) throws NoSuchAlgorithmException {
5349 logger.log(logger.HIGH, "Entering exernalFileEdited");
5351 // Strip URL prefix and base dir path
5352 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
5353 String name = fileName.replace(dPath, "");
5354 int pos = name.lastIndexOf('.');
5357 guid = guid.substring(0,pos);
5359 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
5361 guid = name.substring(0, pos);
5364 QFile file = new QFile(fileName);
5365 if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly))) {
5366 // If we can't get to the file, it is probably locked. We'll try again later.
5367 logger.log(logger.LOW, "Unable to save externally edited file. Saving for later.");
5368 externalFiles.add(fileName);
5371 QByteArray binData = file.readAll();
5373 if (binData.size() == 0) {
5374 // If we can't get to the file, it is probably locked. We'll try again later.
5375 logger.log(logger.LOW, "Unable to save externally edited file. Saving for later.");
5376 externalFiles.add(fileName);
5380 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
5382 r = conn.getNoteTable().noteResourceTable.getNoteResource(Global.resourceMap.get(guid), true);
5383 if (r == null || r.getData() == null || r.getData().getBody() == null)
5385 String oldHash = Global.byteArrayToHexString(r.getData().getBodyHash());
5386 MessageDigest md = MessageDigest.getInstance("MD5");
5387 md.update(binData.toByteArray());
5388 byte[] hash = md.digest();
5389 String newHash = Global.byteArrayToHexString(hash);
5390 if (r.getNoteGuid().equalsIgnoreCase(currentNoteGuid)) {
5391 updateResourceContentHash(browserWindow, r.getGuid(), oldHash, newHash);
5393 if (externalWindows.containsKey(r.getNoteGuid())) {
5394 updateResourceContentHash(externalWindows.get(r.getNoteGuid()).getBrowserWindow(),
5395 r.getGuid(), oldHash, newHash);
5397 conn.getNoteTable().updateResourceContentHash(r.getNoteGuid(), oldHash, newHash);
5398 Data data = r.getData();
5399 data.setBody(binData.toByteArray());
5400 data.setBodyHash(hash);
5401 logger.log(logger.LOW, "externalFileEdited: " +data.getSize() +" bytes");
5403 conn.getNoteTable().noteResourceTable.updateNoteResource(r,true);
5405 if (r.getNoteGuid().equals(currentNoteGuid)) {
5406 QWebSettings.setMaximumPagesInCache(0);
5407 QWebSettings.setObjectCacheCapacities(0, 0, 0);
5408 refreshEvernoteNote(true);
5409 browserWindow.getBrowser().triggerPageAction(WebAction.Reload);
5412 if (externalWindows.containsKey(r.getNoteGuid())) {
5413 QWebSettings.setMaximumPagesInCache(0);
5414 QWebSettings.setObjectCacheCapacities(0, 0, 0);
5415 externalWindows.get(r.getNoteGuid()).getBrowserWindow().getBrowser().triggerPageAction(WebAction.Reload);
5419 logger.log(logger.HIGH, "Exiting externalFielEdited");
5421 // This is a timer event that tries to save any external files that were edited. This
5422 // is only needed if we couldn't save a file earlier.
5423 public void externalFileEditedSaver() {
5424 for (int i=externalFiles.size()-1; i>=0; i--) {
5426 logger.log(logger.MEDIUM, "Trying to save " +externalFiles.get(i));
5427 externalFileEdited(externalFiles.get(i));
5428 externalFiles.remove(i);
5429 } catch (NoSuchAlgorithmException e) {e.printStackTrace();}
5431 for (int i=0; i<importFilesKeep.size(); i++) {
5433 logger.log(logger.MEDIUM, "Trying to save " +importFilesKeep.get(i));
5434 folderImportKeep(importFilesKeep.get(i));
5435 importFilesKeep.remove(i);
5436 } catch (NoSuchAlgorithmException e) {e.printStackTrace();}
5438 for (int i=0; i<importFilesDelete.size(); i++) {
5439 logger.log(logger.MEDIUM, "Trying to save " +importFilesDelete.get(i));
5440 folderImportDelete(importFilesDelete.get(i));
5441 importFilesDelete.remove(i);
5448 // If an attachment on the current note was edited, we need to update the current notes's hash
5449 // Update a note content's hash. This happens if a resource is edited outside of NN
5450 public void updateResourceContentHash(BrowserWindow browser, String guid, String oldHash, String newHash) {
5451 int position = browserWindow.getContent().indexOf("en-tag=\"en-media\" guid=\""+guid+"\" type=");
5453 for (;position>-1;) {
5454 endPos = browser.getContent().indexOf(">", position+1);
5455 String oldSegment = browser.getContent().substring(position,endPos);
5456 int hashPos = oldSegment.indexOf("hash=\"");
5457 int hashEnd = oldSegment.indexOf("\"", hashPos+7);
5458 String hash = oldSegment.substring(hashPos+6, hashEnd);
5459 if (hash.equalsIgnoreCase(oldHash)) {
5460 String newSegment = oldSegment.replace(oldHash, newHash);
5461 String content = browser.getContent().substring(0,position) +
5463 browser.getContent().substring(endPos);
5464 browser.getBrowser().setContent(new QByteArray(content));;
5467 position = browser.getContent().indexOf("en-tag=\"en-media\" guid=\""+guid+"\" type=", position+1);
5472 //*************************************************
5473 //* Minimize to tray
5474 //*************************************************
5476 public void changeEvent(QEvent e) {
5477 if (e.type() == QEvent.Type.WindowStateChange) {
5478 if (isMinimized() && Global.showTrayIcon()) {
5480 QTimer.singleShot(10, this, "hide()");
5484 windowMaximized = true;
5486 windowMaximized = false;
5490 //*************************************************
5491 //* Check database userid & passwords
5492 //*************************************************
5493 private static boolean databaseCheck(String url,String userid, String userPassword, String cypherPassword) {
5494 Connection connection;
5497 Class.forName("org.h2.Driver");
5498 } catch (ClassNotFoundException e1) {
5499 e1.printStackTrace();
5504 String passwordString = null;
5505 if (cypherPassword==null || cypherPassword.trim().equals(""))
5506 passwordString = userPassword;
5508 passwordString = cypherPassword+" "+userPassword;
5509 connection = DriverManager.getConnection(url,userid,passwordString);
5510 } catch (SQLException e) {
5515 } catch (SQLException e) {
5516 e.printStackTrace();