2 * This file is part of NixNote
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.io.FileOutputStream;
25 import java.net.Authenticator;
26 import java.net.PasswordAuthentication;
27 import java.security.MessageDigest;
28 import java.security.NoSuchAlgorithmException;
29 import java.sql.Connection;
30 import java.sql.DriverManager;
31 import java.sql.SQLException;
32 import java.sql.Statement;
33 import java.text.SimpleDateFormat;
34 import java.util.ArrayList;
35 import java.util.Calendar;
36 import java.util.Collection;
37 import java.util.Collections;
38 import java.util.Comparator;
39 import java.util.Date;
40 import java.util.GregorianCalendar;
41 import java.util.HashMap;
42 import java.util.Iterator;
43 import java.util.List;
44 import java.util.SortedMap;
45 import java.util.Vector;
47 import org.apache.log4j.Level;
48 import org.apache.log4j.Logger;
49 import org.apache.thrift.TException;
50 import org.h2.tools.ChangeFileEncryption;
52 import com.evernote.edam.error.EDAMNotFoundException;
53 import com.evernote.edam.error.EDAMSystemException;
54 import com.evernote.edam.error.EDAMUserException;
55 import com.evernote.edam.notestore.NoteFilter;
56 import com.evernote.edam.notestore.NoteVersionId;
57 import com.evernote.edam.type.Data;
58 import com.evernote.edam.type.LinkedNotebook;
59 import com.evernote.edam.type.Note;
60 import com.evernote.edam.type.NoteAttributes;
61 import com.evernote.edam.type.Notebook;
62 import com.evernote.edam.type.Publishing;
63 import com.evernote.edam.type.QueryFormat;
64 import com.evernote.edam.type.Resource;
65 import com.evernote.edam.type.SavedSearch;
66 import com.evernote.edam.type.Tag;
67 import com.evernote.edam.type.User;
68 import com.trolltech.qt.QThread;
69 import com.trolltech.qt.core.QByteArray;
70 import com.trolltech.qt.core.QDateTime;
71 import com.trolltech.qt.core.QDir;
72 import com.trolltech.qt.core.QEvent;
73 import com.trolltech.qt.core.QFile;
74 import com.trolltech.qt.core.QFileInfo;
75 import com.trolltech.qt.core.QFileSystemWatcher;
76 import com.trolltech.qt.core.QIODevice;
77 import com.trolltech.qt.core.QIODevice.OpenModeFlag;
78 import com.trolltech.qt.core.QLocale;
79 import com.trolltech.qt.core.QMimeData;
80 import com.trolltech.qt.core.QModelIndex;
81 import com.trolltech.qt.core.QSize;
82 import com.trolltech.qt.core.QTemporaryFile;
83 import com.trolltech.qt.core.QTextCodec;
84 import com.trolltech.qt.core.QThreadPool;
85 import com.trolltech.qt.core.QTimer;
86 import com.trolltech.qt.core.QTranslator;
87 import com.trolltech.qt.core.QUrl;
88 import com.trolltech.qt.core.Qt;
89 import com.trolltech.qt.core.Qt.BGMode;
90 import com.trolltech.qt.core.Qt.ItemDataRole;
91 import com.trolltech.qt.core.Qt.KeyboardModifier;
92 import com.trolltech.qt.core.Qt.MouseButton;
93 import com.trolltech.qt.core.Qt.SortOrder;
94 import com.trolltech.qt.core.Qt.WidgetAttribute;
95 import com.trolltech.qt.gui.QAbstractItemView;
96 import com.trolltech.qt.gui.QAbstractItemView.ScrollHint;
97 import com.trolltech.qt.gui.QAction;
98 import com.trolltech.qt.gui.QApplication;
99 import com.trolltech.qt.gui.QClipboard;
100 import com.trolltech.qt.gui.QCloseEvent;
101 import com.trolltech.qt.gui.QColor;
102 import com.trolltech.qt.gui.QComboBox;
103 import com.trolltech.qt.gui.QCursor;
104 import com.trolltech.qt.gui.QDesktopServices;
105 import com.trolltech.qt.gui.QDialog;
106 import com.trolltech.qt.gui.QFileDialog;
107 import com.trolltech.qt.gui.QFileDialog.AcceptMode;
108 import com.trolltech.qt.gui.QFileDialog.FileMode;
109 import com.trolltech.qt.gui.QGridLayout;
110 import com.trolltech.qt.gui.QHBoxLayout;
111 import com.trolltech.qt.gui.QIcon;
112 import com.trolltech.qt.gui.QImage;
113 import com.trolltech.qt.gui.QKeySequence;
114 import com.trolltech.qt.gui.QLabel;
115 import com.trolltech.qt.gui.QMainWindow;
116 import com.trolltech.qt.gui.QMenu;
117 import com.trolltech.qt.gui.QMessageBox;
118 import com.trolltech.qt.gui.QMessageBox.StandardButton;
119 import com.trolltech.qt.gui.QPainter;
120 import com.trolltech.qt.gui.QPalette.ColorRole;
121 import com.trolltech.qt.gui.QPixmap;
122 import com.trolltech.qt.gui.QPrintDialog;
123 import com.trolltech.qt.gui.QPrinter;
124 import com.trolltech.qt.gui.QShortcut;
125 import com.trolltech.qt.gui.QSizePolicy;
126 import com.trolltech.qt.gui.QSizePolicy.Policy;
127 import com.trolltech.qt.gui.QSpinBox;
128 import com.trolltech.qt.gui.QSplashScreen;
129 import com.trolltech.qt.gui.QSplitter;
130 import com.trolltech.qt.gui.QStatusBar;
131 import com.trolltech.qt.gui.QSystemTrayIcon;
132 import com.trolltech.qt.gui.QTableWidgetItem;
133 import com.trolltech.qt.gui.QTextEdit;
134 import com.trolltech.qt.gui.QToolBar;
135 import com.trolltech.qt.gui.QTreeWidgetItem;
136 import com.trolltech.qt.network.QNetworkAccessManager;
137 import com.trolltech.qt.network.QNetworkProxy;
138 import com.trolltech.qt.network.QNetworkProxy.ProxyType;
139 import com.trolltech.qt.network.QNetworkReply;
140 import com.trolltech.qt.network.QNetworkRequest;
141 import com.trolltech.qt.webkit.QWebPage.WebAction;
142 import com.trolltech.qt.webkit.QWebSettings;
144 import cx.fbn.nevernote.config.InitializationException;
145 import cx.fbn.nevernote.config.StartupConfig;
146 import cx.fbn.nevernote.dialog.AccountDialog;
147 import cx.fbn.nevernote.dialog.ConfigDialog;
148 import cx.fbn.nevernote.dialog.DBEncryptDialog;
149 import cx.fbn.nevernote.dialog.DatabaseLoginDialog;
150 import cx.fbn.nevernote.dialog.DatabaseStatus;
151 import cx.fbn.nevernote.dialog.FindDialog;
152 import cx.fbn.nevernote.dialog.IgnoreSync;
153 import cx.fbn.nevernote.dialog.LogFileDialog;
154 import cx.fbn.nevernote.dialog.NotebookArchive;
155 import cx.fbn.nevernote.dialog.NotebookEdit;
156 import cx.fbn.nevernote.dialog.OnlineNoteHistory;
157 import cx.fbn.nevernote.dialog.PublishNotebook;
158 import cx.fbn.nevernote.dialog.SavedSearchEdit;
159 import cx.fbn.nevernote.dialog.SetIcon;
160 import cx.fbn.nevernote.dialog.ShareNotebook;
161 import cx.fbn.nevernote.dialog.SharedNotebookSyncError;
162 import cx.fbn.nevernote.dialog.StackNotebook;
163 import cx.fbn.nevernote.dialog.SynchronizationRequiredWarning;
164 import cx.fbn.nevernote.dialog.TagEdit;
165 import cx.fbn.nevernote.dialog.TagMerge;
166 import cx.fbn.nevernote.dialog.ThumbnailViewer;
167 import cx.fbn.nevernote.dialog.UpgradeAvailableDialog;
168 import cx.fbn.nevernote.dialog.WatchFolder;
169 import cx.fbn.nevernote.evernote.NoteMetadata;
170 import cx.fbn.nevernote.filters.FilterEditorNotebooks;
171 import cx.fbn.nevernote.filters.FilterEditorTags;
172 import cx.fbn.nevernote.gui.AttributeTreeWidget;
173 import cx.fbn.nevernote.gui.BrowserWindow;
174 import cx.fbn.nevernote.gui.DateAttributeFilterTable;
175 import cx.fbn.nevernote.gui.ExternalBrowse;
176 import cx.fbn.nevernote.gui.MainMenuBar;
177 import cx.fbn.nevernote.gui.NotebookTreeWidget;
178 import cx.fbn.nevernote.gui.SavedSearchTreeWidget;
179 import cx.fbn.nevernote.gui.SearchPanel;
180 import cx.fbn.nevernote.gui.TableView;
181 import cx.fbn.nevernote.gui.TagTreeWidget;
182 import cx.fbn.nevernote.gui.Thumbnailer;
183 import cx.fbn.nevernote.gui.TrashTreeWidget;
184 import cx.fbn.nevernote.gui.controls.QuotaProgressBar;
185 import cx.fbn.nevernote.oauth.OAuthTokenizer;
186 import cx.fbn.nevernote.oauth.OAuthWindow;
187 import cx.fbn.nevernote.sql.DatabaseConnection;
188 import cx.fbn.nevernote.sql.WatchFolderRecord;
189 import cx.fbn.nevernote.threads.IndexRunner;
190 import cx.fbn.nevernote.threads.SyncRunner;
191 import cx.fbn.nevernote.threads.ThumbnailRunner;
192 import cx.fbn.nevernote.utilities.AESEncrypter;
193 import cx.fbn.nevernote.utilities.ApplicationLogger;
194 import cx.fbn.nevernote.utilities.FileImporter;
195 import cx.fbn.nevernote.utilities.FileUtils;
196 import cx.fbn.nevernote.utilities.ListManager;
197 import cx.fbn.nevernote.utilities.SyncTimes;
198 import cx.fbn.nevernote.xml.ExportData;
199 import cx.fbn.nevernote.xml.ImportData;
200 import cx.fbn.nevernote.xml.ImportEnex;
201 import cx.fbn.nevernote.xml.NoteFormatter;
204 public class NeverNote extends QMainWindow{
206 QStatusBar statusBar; // Application status bar
208 DatabaseConnection conn;
210 MainMenuBar menuBar; // Main menu bar
211 FindDialog find; // Text search in note dialog
212 List<String> emitLog; // Messages displayed in the status bar;
213 QSystemTrayIcon trayIcon; // little tray icon
214 QMenu trayMenu; // System tray menu
215 QAction trayExitAction; // Exit the application
216 QAction trayShowAction; // toggle the show/hide action
217 QAction trayAddNoteAction; // Add a note from the system tray
218 QNetworkAccessManager versionChecker; // Used when checking for new versions
220 NotebookTreeWidget notebookTree; // List of notebooks
221 AttributeTreeWidget attributeTree; // List of note attributes
222 TagTreeWidget tagTree; // list of user created tags
223 SavedSearchTreeWidget savedSearchTree; // list of saved searches
224 TrashTreeWidget trashTree; // Trashcan
225 TableView noteTableView; // List of notes (the widget).
227 public BrowserWindow browserWindow; // Window containing browser & labels
228 public QToolBar toolBar; // The tool bar under the menu
229 QComboBox searchField; // search filter bar on the toolbar;
230 QShortcut searchShortcut; // Shortcut to search bar
231 boolean searchPerformed = false; // Search was done?
232 QuotaProgressBar quotaBar; // The current quota usage
234 ApplicationLogger logger;
235 List<String> selectedNotebookGUIDs; // List of notebook GUIDs
236 List<String> selectedTagGUIDs; // List of selected tag GUIDs
237 List<String> selectedNoteGUIDs; // List of selected notes
238 String selectedSavedSearchGUID; // Currently selected saved searches
239 private final HashMap<String, ExternalBrowse> externalWindows; // Notes being edited by an external window;
241 NoteFilter filter; // Note filter
242 String currentNoteGuid; // GUID of the current note
243 Note currentNote; // The currently viewed note
244 boolean noteDirty; // Has the note been changed?
245 boolean inkNote; // if this is an ink note, it is read only
246 boolean readOnly; // Is this note read-only?
249 ListManager listManager; // DB runnable task
251 List<QTemporaryFile> tempFiles; // Array of temporary files;
253 QTimer indexTimer; // timer to start the index thread
254 IndexRunner indexRunner; // thread to index notes
257 QTimer syncTimer; // Sync on an interval
258 QTimer syncDelayTimer; // Sync delay to free up database
259 SyncRunner syncRunner; // thread to do a sync.
260 QThread syncThread; // Thread which talks to evernote
261 ThumbnailRunner thumbnailRunner; // Runner for thumbnail thread
262 QThread thumbnailThread; // Thread that generates pretty pictures
263 QTimer saveTimer; // Timer to save note contents
265 QTimer authTimer; // Refresh authentication
266 QTimer externalFileSaveTimer; // Save files altered externally
267 QTimer thumbnailTimer; // Wakeup & scan for thumbnails
269 List<String> externalFiles; // External files to save later
270 List<String> importFilesKeep; // Auto-import files to save later
271 List<String> importFilesDelete; // Auto-import files to save later
273 int indexTime; // how often to try and index
274 boolean indexRunning; // Is indexing running?
275 boolean indexDisabled; // Is indexing disabled?
277 int syncThreadsReady; // number of sync threads that are free
278 int syncTime; // Sync interval
279 boolean syncRunning; // Is sync running?
280 boolean automaticSync; // do sync automatically?
281 QTreeWidgetItem attributeTreeSelected;
283 QAction prevButton; // Go to the previous item viewed
284 QAction nextButton; // Go to the next item in the history
285 QAction downButton; // Go to the next item in the list
286 QAction upButton; // Go to the prev. item in the list;
287 QAction synchronizeButton; // Synchronize with Evernote
288 QAction allNotesButton; // Reset & view all notes
289 QTimer synchronizeAnimationTimer; // Timer to change animation button
290 int synchronizeIconAngle; // Used to rotate sync icon
291 QAction printButton; // Print Button
292 QAction tagButton; // Tag edit button
293 QAction attributeButton; // Attribute information button
294 QAction emailButton; // Email button
295 QAction deleteButton; // Delete button
296 QAction newButton; // new Note Button;
297 QSpinBox zoomSpinner; // Zoom zoom
298 QAction searchClearButton; // Clear the search field
300 SearchPanel searchLayout; // Widget to hold search field, zoom, & quota
302 QSplitter mainLeftRightSplitter; // main splitter for left/right side
303 QSplitter leftSplitter1; // first left hand splitter
304 QSplitter browserIndexSplitter; // splitter between note index & note text
306 QFileSystemWatcher importKeepWatcher; // Watch & keep auto-import
307 QFileSystemWatcher importDeleteWatcher; // Watch & Delete auto-import
308 List<String> importedFiles; // History of imported files (so we don't import twice)
310 OnlineNoteHistory historyWindow; // online history window
311 List<NoteVersionId> versions; // history versions
313 QTimer threadMonitorTimer; // Timer to watch threads.
314 int dbThreadDeadCount=0; // number of consecutive dead times for the db thread
315 int syncThreadDeadCount=0; // number of consecutive dead times for the sync thread
316 int indexThreadDeadCount=0; // number of consecutive dead times for the index thread
317 int notebookThreadDeadCount=0; // number of consecutive dead times for the notebook thread
318 int tagDeadCount=0; // number of consecutive dead times for the tag thread
319 int trashDeadCount=0; // number of consecutive dead times for the trash thread
320 int saveThreadDeadCount=0; // number of consecutive dead times for the save thread
321 boolean disableTagThreadCheck=false;
322 boolean disableNotebookThreadCheck=false;
323 boolean disableTrashThreadCheck=false;
324 boolean disableSaveThreadCheck=false;
325 boolean disableSyncThreadCheck=false;
326 boolean disableIndexThreadCheck=false;
328 HashMap<String, String> noteCache; // Cash of note content
329 HashMap<String, Boolean> readOnlyCache; // List of cashe notes that are read-only
330 HashMap<String, Boolean> inkNoteCache; // List of cache notes that are ink notes
331 List<String> historyGuids; // GUIDs of previously viewed items
332 int historyPosition; // Position within the viewed items
333 boolean fromHistory; // Is this from the history queue?
334 String trashNoteGuid; // Guid to restore / set into or out of trash to save position
335 List<Thumbnailer> thumbGenerators; // generate preview image
336 ThumbnailViewer thumbnailViewer; // View preview thumbnail;
337 boolean encryptOnShutdown; // should I encrypt when I close?
338 boolean decryptOnShutdown; // should I decrypt on shutdown;
339 String encryptCipher; // What cipher should I use?
340 //Signal0 minimizeToTray;
341 boolean windowMaximized = false; // Keep track of the window state for restores
342 List<String> pdfReadyQueue; // Queue of PDFs that are ready to be rendered.
343 List<QPixmap> syncIcons; // Array of icons used in sync animation
344 private boolean closeAction = false; // Used to say when to close or when to minimize
345 private static Logger log = Logger.getLogger(NeverNote.class);
346 private String saveLastPath; // last path we used
347 private final QTimer messageTimer; // Timer to clear the status message.
348 private QTimer blockTimer;
349 BrowserWindow blockingWindow;
351 String iconPath = new String("classpath:cx/fbn/nevernote/icons/");
354 //***************************************************************
355 //***************************************************************
356 //** Constructor & main entry point
357 //***************************************************************
358 //***************************************************************
359 // Application Constructor
360 @SuppressWarnings("static-access")
361 public NeverNote(DatabaseConnection dbConn) {
363 if (conn.getConnection() == null) {
364 String msg = new String(tr("Unable to connect to the database.\n\nThe most probable reason is that some other process\n" +
365 "is accessing the database or NixNote is already running.\n\n" +
366 "Please end any other process or shutdown the other NixNote before starting.\n\nExiting program."));
368 QMessageBox.critical(null, tr("Database Connection Error") ,msg);
371 setObjectName("mainWindow");
372 // thread().setPriority(Thread.MAX_PRIORITY);
374 logger = new ApplicationLogger("nevernote.log");
375 logger.log(logger.HIGH, "Starting Application");
377 decryptOnShutdown = false;
378 encryptOnShutdown = false;
379 conn.checkDatabaseVersion();
383 // Start building the invalid XML tables
384 Global.invalidElements = conn.getInvalidXMLTable().getInvalidElements();
385 List<String> elements = conn.getInvalidXMLTable().getInvalidAttributeElements();
387 for (int i=0; i<elements.size(); i++) {
388 Global.invalidAttributes.put(elements.get(i), conn.getInvalidXMLTable().getInvalidAttributes(elements.get(i)));
391 logger.log(logger.EXTREME, "Starting GUI build");
393 QTranslator nevernoteTranslator = new QTranslator();
394 nevernoteTranslator.load(Global.getFileManager().getTranslateFilePath("nevernote_" + QLocale.system().name() + ".qm"));
395 QApplication.instance().installTranslator(nevernoteTranslator);
397 Global.originalPalette = QApplication.palette();
398 QApplication.setStyle(Global.getStyle());
399 if (Global.useStandardPalette())
400 QApplication.setPalette(QApplication.style().standardPalette());
401 setWindowTitle(tr("NixNote"));
403 mainLeftRightSplitter = new QSplitter();
404 setCentralWidget(mainLeftRightSplitter);
405 leftSplitter1 = new QSplitter();
406 leftSplitter1.setOrientation(Qt.Orientation.Vertical);
408 browserIndexSplitter = new QSplitter();
409 browserIndexSplitter.setOrientation(Qt.Orientation.Vertical);
411 //* Setup threads & thread timers
412 // int indexRunnerCount = Global.getIndexThreads();
413 // indexRunnerCount = 1;
414 QThreadPool.globalInstance().setMaxThreadCount(Global.threadCount); // increase max thread count
416 logger.log(logger.EXTREME, "Building list manager");
417 listManager = new ListManager(conn, logger);
419 logger.log(logger.EXTREME, "Building index runners & timers");
420 indexRunner = new IndexRunner("indexRunner.log",
421 Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(),
422 Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
423 indexThread = new QThread(indexRunner, "Index Thread");
424 indexRunner.indexAttachmentsLocally = Global.indexAttachmentsLocally();
425 indexRunner.indexImageRecognition = Global.indexImageRecognition();
426 indexRunner.indexNoteBody = Global.indexNoteBody();
427 indexRunner.indexNoteTitle = Global.indexNoteTitle();
428 indexRunner.specialIndexCharacters = Global.getSpecialIndexCharacters();
431 synchronizeAnimationTimer = new QTimer();
432 synchronizeAnimationTimer.timeout.connect(this, "updateSyncButton()");
434 indexTimer = new QTimer();
435 indexTime = 1000*Global.getIndexThreadSleepInterval();
436 indexTimer.start(indexTime); // Start indexing timer
437 indexTimer.timeout.connect(this, "indexTimer()");
438 indexDisabled = false;
439 indexRunning = false;
441 logger.log(logger.EXTREME, "Setting sync thread & timers");
443 syncRunner = new SyncRunner("syncRunner.log",
444 Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(),
445 Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
446 syncTime = new SyncTimes().timeValue(Global.getSyncInterval());
447 syncTimer = new QTimer();
448 syncTimer.timeout.connect(this, "syncTimer()");
449 syncRunner.status.message.connect(this, "setMessage(String)");
450 syncRunner.syncSignal.finished.connect(this, "syncThreadComplete(Boolean)");
451 syncRunner.syncSignal.errorDisconnect.connect(this, "remoteErrorDisconnect()");
454 automaticSync = true;
455 syncTimer.start(syncTime*60*1000);
457 automaticSync = false;
460 syncRunner.setEvernoteUpdateCount(Global.getEvernoteUpdateCount());
461 syncThread = new QThread(syncRunner, "Synchronization Thread");
465 logger.log(logger.EXTREME, "Starting thumnail thread");
466 pdfReadyQueue = new ArrayList<String>();
467 thumbnailRunner = new ThumbnailRunner("thumbnailRunner.log",
468 Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(),
469 Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
470 thumbnailThread = new QThread(thumbnailRunner, "Thumbnail Thread");
471 thumbnailRunner.noteSignal.thumbnailPageReady.connect(this, "thumbnailHTMLReady(String,QByteArray,Integer)");
472 thumbnailThread.start();
473 thumbGenerators = new ArrayList<Thumbnailer>();
474 thumbnailTimer = new QTimer();
475 thumbnailTimer.timeout.connect(this, "thumbnailTimer()");
477 thumbnailTimer.setInterval(500*1000); // Thumbnail every minute
478 thumbnailTimer.start();
480 // debugTimer = new QTimer();
481 // debugTimer.timeout.connect(this, "debugDirty()");
482 // debugTimer.start(1000*60);
484 logger.log(logger.EXTREME, "Starting authentication timer");
485 authTimer = new QTimer();
486 authTimer.timeout.connect(this, "authTimer()");
487 authTimer.start(1000*60*15);
488 syncRunner.syncSignal.authRefreshComplete.connect(this, "authRefreshComplete(boolean)");
490 logger.log(logger.EXTREME, "Setting save note timer");
491 saveTimer = new QTimer();
492 saveTimer.timeout.connect(this, "saveNote()");
493 if (Global.getAutoSaveInterval() > 0) {
494 saveTimer.setInterval(1000*60*Global.getAutoSaveInterval());
497 listManager.saveRunner.noteSignals.noteSaveRunnerError.connect(this, "saveRunnerError(String, String)");
499 logger.log(logger.EXTREME, "Starting external file monitor timer");
500 externalFileSaveTimer = new QTimer();
501 externalFileSaveTimer.timeout.connect(this, "externalFileEditedSaver()");
502 externalFileSaveTimer.setInterval(1000*5); // save every 5 seconds;
503 externalFiles = new ArrayList<String>();
504 importFilesDelete = new ArrayList<String>();
505 importFilesKeep = new ArrayList<String>();
506 externalFileSaveTimer.start();
508 notebookTree = new NotebookTreeWidget(conn);
509 attributeTree = new AttributeTreeWidget();
510 tagTree = new TagTreeWidget(conn);
511 savedSearchTree = new SavedSearchTreeWidget();
512 trashTree = new TrashTreeWidget();
513 noteTableView = new TableView(logger, listManager);
515 searchField = new QComboBox();
516 searchField.setObjectName("searchField");
517 //setStyleSheet("QComboBox#searchField { background-color: yellow }");
518 searchField.setEditable(true);
519 searchField.activatedIndex.connect(this, "searchFieldChanged()");
520 searchField.setDuplicatesEnabled(false);
521 searchField.editTextChanged.connect(this,"searchFieldTextChanged(String)");
522 searchShortcut = new QShortcut(this);
523 setupShortcut(searchShortcut, "Focus_Search");
524 searchShortcut.activated.connect(this, "focusSearch()");
526 quotaBar = new QuotaProgressBar();
528 zoomSpinner = new QSpinBox();
529 zoomSpinner.setMinimum(10);
530 zoomSpinner.setMaximum(1000);
531 zoomSpinner.setAccelerated(true);
532 zoomSpinner.setSingleStep(10);
533 zoomSpinner.setValue(100);
534 zoomSpinner.valueChanged.connect(this, "zoomChanged()");
536 searchLayout = new SearchPanel(searchField, quotaBar, notebookTree, zoomSpinner);
539 QGridLayout leftGrid = new QGridLayout();
540 leftSplitter1.setContentsMargins(5, 0, 0, 7);
541 leftSplitter1.setLayout(leftGrid);
542 leftGrid.addWidget(searchLayout,1,1);
543 leftGrid.addWidget(tagTree,2,1);
544 leftGrid.addWidget(attributeTree,3,1);
545 leftGrid.addWidget(savedSearchTree,4,1);
546 leftGrid.addWidget(trashTree,5, 1);
548 // Setup the browser window
549 noteCache = new HashMap<String,String>();
550 readOnlyCache = new HashMap<String, Boolean>();
551 inkNoteCache = new HashMap<String, Boolean>();
552 browserWindow = new BrowserWindow(conn);
554 mainLeftRightSplitter.addWidget(leftSplitter1);
555 mainLeftRightSplitter.addWidget(browserIndexSplitter);
557 if (Global.getListView() == Global.View_List_Wide) {
558 browserIndexSplitter.addWidget(noteTableView);
559 browserIndexSplitter.addWidget(browserWindow);
561 mainLeftRightSplitter.addWidget(noteTableView);
562 mainLeftRightSplitter.addWidget(browserWindow);
565 // Setup the thumbnail viewer
566 thumbnailViewer = new ThumbnailViewer();
567 thumbnailViewer.upArrow.connect(this, "upAction()");
568 thumbnailViewer.downArrow.connect(this, "downAction()");
569 thumbnailViewer.leftArrow.connect(this, "nextViewedAction()");
570 thumbnailViewer.rightArrow.connect(this, "previousViewedAction()");
572 //Setup external browser manager
573 externalWindows = new HashMap<String, ExternalBrowse>();
575 listManager.loadNotesIndex();
576 initializeNotebookTree();
578 initializeSavedSearchTree();
579 attributeTree.itemClicked.connect(this, "attributeTreeClicked(QTreeWidgetItem, Integer)");
580 attributeTreeSelected = null;
581 initializeNoteTable();
583 selectedNoteGUIDs = new ArrayList<String>();
584 statusBar = new QStatusBar();
585 setStatusBar(statusBar);
586 menuBar = new MainMenuBar(this);
587 emitLog = new ArrayList<String>();
589 tagTree.setDeleteAction(menuBar.tagDeleteAction);
590 tagTree.setMergeAction(menuBar.tagMergeAction);
591 tagTree.setEditAction(menuBar.tagEditAction);
592 tagTree.setAddAction(menuBar.tagAddAction);
593 tagTree.setIconAction(menuBar.tagIconAction);
594 tagTree.setVisible(Global.isWindowVisible("tagTree"));
595 leftSplitter1.setVisible(Global.isWindowVisible("leftPanel"));
596 tagTree.noteSignal.tagsAdded.connect(this, "tagsAdded(String, String)");
597 menuBar.hideTags.setChecked(Global.isWindowVisible("tagTree"));
598 listManager.tagSignal.listChanged.connect(this, "reloadTagTree()");
600 if (!Global.isWindowVisible("zoom")) {
601 searchLayout.hideZoom();
602 menuBar.hideZoom.setChecked(false);
605 notebookTree.setDeleteAction(menuBar.notebookDeleteAction);
606 notebookTree.setEditAction(menuBar.notebookEditAction);
607 notebookTree.setAddAction(menuBar.notebookAddAction);
608 notebookTree.setIconAction(menuBar.notebookIconAction);
609 notebookTree.setStackAction(menuBar.notebookStackAction);
610 notebookTree.setPublishAction(menuBar.notebookPublishAction);
611 notebookTree.setShareAction(menuBar.notebookShareAction);
612 notebookTree.setVisible(Global.isWindowVisible("notebookTree"));
613 notebookTree.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
614 notebookTree.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)");
615 notebookTree.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)");
616 menuBar.hideNotebooks.setChecked(Global.isWindowVisible("notebookTree"));
618 savedSearchTree.setAddAction(menuBar.savedSearchAddAction);
619 savedSearchTree.setEditAction(menuBar.savedSearchEditAction);
620 savedSearchTree.setDeleteAction(menuBar.savedSearchDeleteAction);
621 savedSearchTree.setIconAction(menuBar.savedSearchIconAction);
622 savedSearchTree.itemSelectionChanged.connect(this, "updateSavedSearchSelection()");
623 savedSearchTree.setVisible(Global.isWindowVisible("savedSearchTree"));
624 menuBar.hideSavedSearches.setChecked(Global.isWindowVisible("savedSearchTree"));
626 noteTableView.setAddAction(menuBar.noteAdd);
627 noteTableView.setDeleteAction(menuBar.noteDelete);
628 noteTableView.setRestoreAction(menuBar.noteRestoreAction);
629 noteTableView.setNoteDuplicateAction(menuBar.noteDuplicateAction);
630 noteTableView.setNoteHistoryAction(menuBar.noteOnlineHistoryAction);
631 noteTableView.noteSignal.titleColorChanged.connect(this, "titleColorChanged(Integer)");
632 noteTableView.noteSignal.notePinned.connect(this, "notePinned()");
633 noteTableView.setMergeNotesAction(menuBar.noteMergeAction);
634 noteTableView.setCopyAsUrlAction(menuBar.noteCopyAsUrlAction);
635 noteTableView.doubleClicked.connect(this, "listDoubleClick()");
636 listManager.trashSignal.countChanged.connect(trashTree, "updateCounts(Integer)");
638 quotaBar.setMouseClickAction(menuBar.accountAction);
641 trashTree.itemSelectionChanged.connect(this, "trashTreeSelection()");
642 trashTree.setEmptyAction(menuBar.emptyTrashAction);
643 trashTree.setVisible(Global.isWindowVisible("trashTree"));
644 menuBar.hideTrash.setChecked(Global.isWindowVisible("trashTree"));
645 trashTree.updateCounts(listManager.getTrashCount());
646 attributeTree.setVisible(Global.isWindowVisible("attributeTree"));
647 menuBar.hideAttributes.setChecked(Global.isWindowVisible("attributeTree"));
649 noteTableView.setVisible(Global.isWindowVisible("noteList"));
650 menuBar.hideNoteList.setChecked(Global.isWindowVisible("noteList"));
652 if (!Global.isWindowVisible("editorButtonBar"))
653 toggleEditorButtonBar();
654 if (!Global.isWindowVisible("leftPanel"))
655 menuBar.hideLeftSide.setChecked(true);
656 if (Global.isWindowVisible("noteInformation"))
657 toggleNoteInformation();
658 quotaBar.setVisible(Global.isWindowVisible("quota"));
659 if (!quotaBar.isVisible())
660 menuBar.hideQuota.setChecked(false);
661 searchField.setVisible(Global.isWindowVisible("searchField"));
662 if (!searchField.isVisible())
663 menuBar.hideSearch.setChecked(false);
665 if (searchField.isHidden() && quotaBar.isHidden() && zoomSpinner.isHidden() && notebookTree.isHidden())
670 find = new FindDialog();
671 find.getOkButton().clicked.connect(this, "doFindText()");
673 // Setup the tray icon menu bar
674 trayShowAction = new QAction(tr("Show/Hide"), this);
675 trayExitAction = new QAction(tr("Exit"), this);
676 trayAddNoteAction = new QAction(tr("Add Note"), this);
678 trayExitAction.triggered.connect(this, "closeNeverNote()");
679 trayAddNoteAction.triggered.connect(this, "addNote()");
680 trayShowAction.triggered.connect(this, "trayToggleVisible()");
682 trayMenu = new QMenu(this);
683 trayMenu.addAction(trayAddNoteAction);
684 trayMenu.addAction(trayShowAction);
685 trayMenu.addAction(trayExitAction);
688 trayIcon = new QSystemTrayIcon(this);
689 trayIcon.setToolTip(tr("NixNote"));
690 trayIcon.setContextMenu(trayMenu);
691 trayIcon.activated.connect(this, "trayActivated(com.trolltech.qt.gui.QSystemTrayIcon$ActivationReason)");
694 currentNoteGuid = Global.getLastViewedNoteGuid();
695 historyGuids = new ArrayList<String>();
699 if (!currentNoteGuid.trim().equals("")) {
700 currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true);
703 noteIndexUpdated(true);
705 menuBar.showEditorBar.setChecked(Global.isWindowVisible("editorButtonBar"));
706 if (menuBar.showEditorBar.isChecked())
707 showEditorButtons(browserWindow);
708 tagIndexUpdated(true);
709 savedSearchIndexUpdated();
710 notebookIndexUpdated();
712 setupSyncSignalListeners();
713 setupBrowserSignalListeners();
714 setupIndexListeners();
717 tagTree.tagSignal.listChanged.connect(this, "tagIndexUpdated()");
718 tagTree.showAllTags(true);
720 QIcon appIcon = new QIcon(iconPath+"nevernote.png");
721 if (QSystemTrayIcon.isSystemTrayAvailable()) {
722 setWindowIcon(appIcon);
723 trayIcon.setIcon(appIcon);
724 if (Global.showTrayIcon() || Global.minimizeOnClose())
730 scrollToGuid(currentNoteGuid);
731 if (Global.automaticLogin()) {
733 if (Global.isConnected)
736 setupFolderImports();
739 restoreWindowState(true);
741 if (Global.mimicEvernoteInterface) {
742 notebookTree.selectGuid("");
745 threadMonitorTimer = new QTimer();
746 threadMonitorTimer.timeout.connect(this, "threadMonitorCheck()");
747 threadMonitorTimer.start(1000*10); // Check for threads every 10 seconds;
749 historyGuids.add(currentNoteGuid);
752 menuBar.blockSignals(true);
753 menuBar.narrowListView.blockSignals(true);
754 menuBar.wideListView.blockSignals(true);
755 if (Global.getListView() == Global.View_List_Narrow) {
756 menuBar.narrowListView.setChecked(true);
759 menuBar.wideListView.setChecked(true);
761 menuBar.blockSignals(false);
762 menuBar.narrowListView.blockSignals(false);
763 menuBar.wideListView.blockSignals(false);
765 if (Global.getListView() == Global.View_List_Wide) {
766 browserIndexSplitter.addWidget(noteTableView);
767 browserIndexSplitter.addWidget(browserWindow);
769 mainLeftRightSplitter.addWidget(noteTableView);
770 mainLeftRightSplitter.addWidget(browserWindow);
773 messageTimer = new QTimer();
774 messageTimer.timeout.connect(this, "clearMessage()");
775 messageTimer.setInterval(1000*15);
778 int sortCol = Global.getSortColumn();
779 int sortOrder = Global.getSortOrder();
780 noteTableView.proxyModel.blocked = true;
781 // We sort the table twice to fix a bug. For some reaosn the table won't sort properly if it is in narrow
782 // list view and sorted descending on the date created. By sorting it twice it forces the proper sort. Ugly.
783 if (sortCol == 0 && sortOrder == 1 && Global.getListView() == Global.View_List_Narrow)
784 noteTableView.sortByColumn(sortCol, SortOrder.resolve(0));
785 noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder));
786 noteTableView.proxyModel.blocked = false;
787 noteTableView.proxyModel.sortChanged.connect(this, "tableSortOrderChanged(Integer,Integer)");
789 // Set the startup notebook
790 String defaultNotebook = Global.getStartupNotebook();
791 if (!defaultNotebook.equals("AllNotebooks") && !defaultNotebook.equals("")) {
792 for (int k=0; k<listManager.getNotebookIndex().size(); k++) {
793 if (listManager.getNotebookIndex().get(k).isDefaultNotebook()) {
794 notebookTree.clearSelection();
795 notebookTree.selectGuid(listManager.getNotebookIndex().get(k).getGuid());
796 notebookTree.selectionSignal.emit();
804 if (Global.checkVersionUpgrade())
809 public void debugDirty() {
810 List<Note> dirty = conn.getNoteTable().getDirty();
811 logger.log(logger.LOW, "------ Dirty Notes List Begin ------");
812 for (int i=0; i<dirty.size(); i++) {
813 logger.log(logger.LOW, "GUID: " +dirty.get(i).getGuid() + " Title:" + dirty.get(i).getTitle());
815 logger.log(logger.LOW, "------ Dirty Notes List End ------");
819 public static void main(String[] args) {
820 log.setLevel(Level.FATAL);
821 QApplication.initialize(args);
822 QPixmap pixmap = new QPixmap("classpath:cx/fbn/nevernote/icons/splash_logo.png");
823 QSplashScreen splash = new QSplashScreen(pixmap);
826 DatabaseConnection dbConn;
829 initializeGlobalSettings(args);
831 showSplash = Global.isWindowVisible("SplashScreen");
835 dbConn = setupDatabaseConnection();
837 // Must be last stage of setup - only safe once DB is open hence we know we are the only instance running
838 Global.getFileManager().purgeResDirectory(true);
840 } catch (InitializationException e) {
843 QMessageBox.critical(null, "Startup error", "Aborting: " + e.getMessage());
848 String proxyUrl = Global.getProxyValue("url");
849 String proxyPort = Global.getProxyValue("port");
850 String proxyUserid = Global.getProxyValue("userid");
851 String proxyPassword = Global.getProxyValue("password");
852 boolean proxySet = false;
853 QNetworkProxy proxy = new QNetworkProxy();
854 proxy.setType(ProxyType.HttpProxy);
855 if (!proxyUrl.trim().equals("")) {
856 System.out.println("Proxy URL found: " +proxyUrl);
858 proxy.setHostName(proxyUrl);
860 if (!proxyPort.trim().equals("")) {
861 System.out.println("Proxy Port found: " +proxyPort);
863 proxy.setPort(Integer.parseInt(proxyPort));
865 if (!proxyUserid.trim().equals("")) {
866 System.out.println("Proxy Userid found: " +proxyUserid);
868 proxy.setUser(proxyUserid);
870 if (!proxyPassword.trim().equals("")) {
871 System.out.println("Proxy URL found: " +proxyPassword);
873 proxy.setPassword(proxyPassword);
876 QNetworkProxy.setApplicationProxy(proxy);
880 NeverNote application = new NeverNote(dbConn);
881 if (Global.syncOnly) {
882 System.out.println("Performing synchronization only.");
883 application.remoteConnect();
884 if (Global.isConnected) {
885 application.syncRunner.syncNeeded = true;
886 application.syncRunner.addWork("SYNC");
887 application.syncRunner.addWork("STOP");
888 while(!application.syncRunner.isIdle());
889 application.closeNeverNote();
894 application.setAttribute(WidgetAttribute.WA_DeleteOnClose, true);
895 if (Global.startMinimized())
896 application.showMinimized();
898 if (Global.wasWindowMaximized())
899 application.showMaximized();
905 splash.finish(application);
907 System.out.println("Goodbye.");
912 * Open the internal database, or create if not present
914 * @throws InitializationException when opening the database fails, e.g. because another process has it locked
916 private static DatabaseConnection setupDatabaseConnection() throws InitializationException {
917 ApplicationLogger logger = new ApplicationLogger("nevernote-database.log");
919 File f = Global.getFileManager().getDbDirFile(Global.databaseName + ".h2.db");
920 File fr = Global.getFileManager().getDbDirFile(Global.resourceDatabaseName + ".h2.db");
921 File fi = Global.getFileManager().getDbDirFile(Global.resourceDatabaseName + ".h2.db");
923 Global.setDatabaseUrl("");
925 Global.setResourceDatabaseUrl("");
927 Global.setIndexDatabaseUrl("");
929 if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") > -1) {
930 boolean goodCheck = false;
932 DatabaseLoginDialog dialog = new DatabaseLoginDialog();
934 if (!dialog.okPressed())
936 Global.cipherPassword = dialog.getPassword();
937 goodCheck = databaseCheck(Global.getDatabaseUrl(), Global.getDatabaseUserid(),
938 Global.getDatabaseUserPassword(), Global.cipherPassword);
941 DatabaseConnection dbConn = new DatabaseConnection(logger,Global.getDatabaseUrl(),
942 Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(),
943 Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword, 0);
947 // Encrypt the database upon shutdown
948 private void encryptOnShutdown() {
949 String dbPath= Global.getFileManager().getDbDirPath("");
952 Statement st = conn.getConnection().createStatement();
953 st.execute("shutdown");
954 st = conn.getResourceConnection().createStatement();
955 st.execute("shutdown");
956 st = conn.getIndexConnection().createStatement();
957 st.execute("shutdown");
958 if (QMessageBox.question(this, tr("Are you sure"),
959 tr("Are you sure you wish to encrypt the database?"),
960 QMessageBox.StandardButton.Yes,
961 QMessageBox.StandardButton.No) == StandardButton.Yes.value()) {
962 ChangeFileEncryption.execute(dbPath, "NeverNote", encryptCipher, null, Global.cipherPassword.toCharArray(), true);
963 ChangeFileEncryption.execute(dbPath, "Resources", encryptCipher, null, Global.cipherPassword.toCharArray(), true);
964 ChangeFileEncryption.execute(dbPath, "Index", encryptCipher, null, Global.cipherPassword.toCharArray(), true);
965 Global.setDatabaseUrl(Global.getDatabaseUrl() + ";CIPHER="+encryptCipher);
966 Global.setResourceDatabaseUrl(Global.getResourceDatabaseUrl() + ";CIPHER="+encryptCipher);
967 Global.setIndexDatabaseUrl(Global.getIndexDatabaseUrl() + ";CIPHER="+encryptCipher);
969 QMessageBox.information(this, tr("Encryption Complete"), tr("Encryption is complete"));
971 } catch (SQLException e) {
976 // Decrypt the database upon shutdown
977 private void decryptOnShutdown() {
978 String dbPath= Global.getFileManager().getDbDirPath("");
979 String dbName = "NeverNote";
981 Statement st = conn.getConnection().createStatement();
982 st.execute("shutdown");
983 if (Global.getDatabaseUrl().toUpperCase().indexOf(";CIPHER=AES") > -1)
984 encryptCipher = "AES";
986 encryptCipher = "XTEA";
987 if (QMessageBox.question(this, tr("Confirmation"), tr("Are you sure",
988 "Are you sure you wish to decrypt the database?"),
989 QMessageBox.StandardButton.Yes,
990 QMessageBox.StandardButton.No) == StandardButton.Yes.value()) {
992 ChangeFileEncryption.execute(dbPath, dbName, encryptCipher, Global.cipherPassword.toCharArray(), null, true);
993 Global.setDatabaseUrl("");
994 Global.setResourceDatabaseUrl("");
995 Global.setIndexDatabaseUrl("");
996 QMessageBox.information(this, tr("Decryption Complete"), tr("Decryption is complete"));
998 } catch (SQLException e) {
1003 * Encrypt/Decrypt the local database
1005 public void doDatabaseEncrypt() {
1006 // The database is not currently encrypted
1007 if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") == -1) {
1008 if (QMessageBox.question(this, tr("Confirmation"), tr("Encrypting the database is used" +
1009 "to enhance security and is performed\nupon shutdown, but please be aware that if"+
1010 " you lose the password your\nis lost forever.\n\nIt is highly recommended you " +
1011 "perform a backup and/or fully synchronize\n prior to executing this funtction.\n\n" +
1012 "Do you wish to proceed?"),
1013 QMessageBox.StandardButton.Yes,
1014 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1017 DBEncryptDialog dialog = new DBEncryptDialog();
1019 if (dialog.okPressed()) {
1020 Global.cipherPassword = dialog.getPassword();
1021 encryptOnShutdown = true;
1022 encryptCipher = dialog.getEncryptionMethod();
1025 DBEncryptDialog dialog = new DBEncryptDialog();
1026 dialog.setWindowTitle(tr("Database Decryption"));
1027 dialog.hideEncryption();
1029 if (dialog.okPressed()) {
1030 if (!dialog.getPassword().equals(Global.cipherPassword)) {
1031 QMessageBox.critical(null, tr("Incorrect Password"), tr("Incorrect Password"));
1034 decryptOnShutdown = true;
1041 private static void initializeGlobalSettings(String[] args) throws InitializationException {
1042 StartupConfig startupConfig = new StartupConfig();
1044 for (String arg : args) {
1045 String lower = arg.toLowerCase();
1046 if (lower.startsWith("--name="))
1047 startupConfig.setName(arg.substring(arg.indexOf('=') + 1));
1048 if (lower.startsWith("--home="))
1049 startupConfig.setHomeDirPath(arg.substring(arg.indexOf('=') + 1));
1050 if (lower.startsWith("--disable-viewing"))
1051 startupConfig.setDisableViewing(true);
1052 if (lower.startsWith("--sync-only=true"))
1053 startupConfig.setSyncOnly(true);
1055 Global.setup(startupConfig);
1061 public void closeEvent(QCloseEvent event) {
1062 if (Global.minimizeOnClose() && !closeAction) {
1067 logger.log(logger.HIGH, "Entering NeverNote.closeEvent");
1070 if (currentNote!= null & browserWindow!=null) {
1071 if (currentNote.getTitle() != null && browserWindow != null
1072 && !currentNote.getTitle().equals(browserWindow.getTitle()))
1073 conn.getNoteTable().updateNoteTitle(currentNote.getGuid(), browserWindow.getTitle());
1076 setMessage(tr("Beginning shutdown."));
1078 // Close down external windows
1079 Collection<ExternalBrowse> windows = externalWindows.values();
1080 Iterator<ExternalBrowse> iterator = windows.iterator();
1081 while (iterator.hasNext()) {
1082 ExternalBrowse browser = iterator.next();
1083 browser.windowClosing.disconnect();
1088 externalFileEditedSaver();
1089 if (Global.isConnected && Global.synchronizeOnClose()) {
1090 setMessage(tr("Performing synchronization before closing."));
1091 syncRunner.syncNeeded = true;
1092 syncRunner.addWork("SYNC");
1094 syncRunner.keepRunning = false;
1096 syncRunner.addWork("STOP");
1097 setMessage("Closing Program.");
1098 threadMonitorTimer.stop();
1100 thumbnailRunner.addWork("STOP");
1101 indexRunner.addWork("STOP");
1106 if (tempFiles != null)
1109 browserWindow.noteSignal.tagsChanged.disconnect();
1110 browserWindow.noteSignal.titleChanged.disconnect();
1111 browserWindow.noteSignal.noteChanged.disconnect();
1112 browserWindow.noteSignal.notebookChanged.disconnect();
1113 browserWindow.noteSignal.createdDateChanged.disconnect();
1114 browserWindow.noteSignal.alteredDateChanged.disconnect();
1115 syncRunner.searchSignal.listChanged.disconnect();
1116 syncRunner.tagSignal.listChanged.disconnect();
1117 syncRunner.notebookSignal.listChanged.disconnect();
1118 syncRunner.noteIndexSignal.listChanged.disconnect();
1121 Global.saveWindowVisible("toolBar", toolBar.isVisible());
1122 saveNoteColumnPositions();
1123 saveNoteIndexWidth();
1125 int width = notebookTree.columnWidth(0);
1126 Global.setColumnWidth("notebookTreeName", width);
1127 width = tagTree.columnWidth(0);
1128 Global.setColumnWidth("tagTreeName", width);
1130 Global.saveWindowMaximized(isMaximized());
1131 Global.saveCurrentNoteGuid(currentNoteGuid);
1133 int sortCol = noteTableView.proxyModel.sortColumn();
1134 int sortOrder = noteTableView.proxyModel.sortOrder().value();
1135 Global.setSortColumn(sortCol);
1136 Global.setSortOrder(sortOrder);
1140 Global.keepRunning = false;
1142 logger.log(logger.MEDIUM, "Waiting for indexThread to stop");
1143 if (indexRunner.thread().isAlive())
1144 indexRunner.thread().join(50);
1145 if (!indexRunner.thread().isAlive())
1146 logger.log(logger.MEDIUM, "Index thread has stopped");
1148 logger.log(logger.MEDIUM, "Index thread still running - interrupting");
1149 indexRunner.thread().interrupt();
1151 } catch (InterruptedException e1) {
1152 e1.printStackTrace();
1155 if (!syncRunner.thread().isAlive()) {
1156 logger.log(logger.MEDIUM, "Waiting for syncThread to stop");
1157 if (syncRunner.thread().isAlive()) {
1158 System.out.println(tr("Synchronizing. Please be patient."));
1159 for(;syncRunner.thread().isAlive();) {
1162 } catch (InterruptedException e) {
1163 e.printStackTrace();
1167 logger.log(logger.MEDIUM, "Sync thread has stopped");
1170 if (encryptOnShutdown) {
1171 encryptOnShutdown();
1173 if (decryptOnShutdown) {
1174 decryptOnShutdown();
1177 Global.getFileManager().purgeResDirectory(false);
1178 } catch (InitializationException e) {
1179 System.out.println(tr("Empty res directory purge failed"));
1180 e.printStackTrace();
1182 logger.log(logger.HIGH, "Leaving NeverNote.closeEvent");
1186 private void closeNeverNote() {
1190 public void setMessage(String s) {
1192 logger.log(logger.HIGH, "Entering NeverNote.setMessage");
1194 System.out.println("*** ERROR *** " +s);
1196 if (statusBar != null) {
1199 logger.log(logger.HIGH, "Message: " +s);
1200 statusBar.showMessage(s);
1201 if (emitLog != null)
1204 if (messageTimer != null) {
1205 messageTimer.stop();
1206 messageTimer.setSingleShot(true);
1207 messageTimer.start();
1212 logger.log(logger.HIGH, "Leaving NeverNote.setMessage");
1215 private void clearMessage() {
1216 statusBar.clearMessage();
1220 private void waitCursor(boolean wait) {
1222 if (QApplication.overrideCursor() == null)
1223 QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.WaitCursor));
1226 while (QApplication.overrideCursor() != null)
1227 QApplication.restoreOverrideCursor();
1229 listManager.refreshCounters();
1232 private void setupIndexListeners() {
1233 // indexRunner.noteSignal.noteIndexed.connect(this, "indexThreadComplete(String)");
1234 // indexRunner.resourceSignal.resourceIndexed.connect(this, "indexThreadComplete(String)");
1235 indexRunner.signal.indexStarted.connect(this, "indexStarted()");
1236 indexRunner.signal.indexFinished.connect(this, "indexComplete()");
1238 private void setupSyncSignalListeners() {
1239 syncRunner.tagSignal.listChanged.connect(this, "tagIndexUpdated()");
1240 syncRunner.searchSignal.listChanged.connect(this, "savedSearchIndexUpdated()");
1241 syncRunner.notebookSignal.listChanged.connect(this, "notebookIndexUpdated()");
1242 syncRunner.noteIndexSignal.listChanged.connect(this, "noteIndexUpdated(boolean)");
1243 syncRunner.noteSignal.quotaChanged.connect(this, "updateQuotaBar()");
1245 syncRunner.syncSignal.saveUploadAmount.connect(this,"saveUploadAmount(long)");
1246 syncRunner.syncSignal.saveUserInformation.connect(this,"saveUserInformation(User)");
1247 syncRunner.syncSignal.saveEvernoteUpdateCount.connect(this,"saveEvernoteUpdateCount(int)");
1249 syncRunner.noteSignal.guidChanged.connect(this, "noteGuidChanged(String, String)");
1250 syncRunner.noteSignal.noteChanged.connect(this, "invalidateNoteCache(String, String)");
1251 syncRunner.resourceSignal.resourceGuidChanged.connect(this, "noteResourceGuidChanged(String,String,String)");
1252 syncRunner.noteSignal.noteDownloaded.connect(listManager, "noteDownloaded(Note)");
1253 syncRunner.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
1255 syncRunner.syncSignal.refreshLists.connect(this, "refreshLists()");
1258 private void setupBrowserSignalListeners() {
1259 setupBrowserWindowListeners(browserWindow, true);
1262 private void setupBrowserWindowListeners(BrowserWindow browser, boolean master) {
1263 browser.fileWatcher.fileChanged.connect(this, "externalFileEdited(String)");
1264 browser.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)");
1265 browser.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)");
1266 if (master) browser.noteSignal.noteChanged.connect(this, "setNoteDirty()");
1267 browser.noteSignal.titleChanged.connect(listManager, "updateNoteTitle(String, String)");
1268 browser.noteSignal.titleChanged.connect(this, "updateNoteTitle(String, String)");
1269 browser.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
1270 browser.noteSignal.createdDateChanged.connect(listManager, "updateNoteCreatedDate(String, QDateTime)");
1271 browser.noteSignal.alteredDateChanged.connect(listManager, "updateNoteAlteredDate(String, QDateTime)");
1272 browser.noteSignal.subjectDateChanged.connect(listManager, "updateNoteSubjectDate(String, QDateTime)");
1273 browser.noteSignal.authorChanged.connect(listManager, "updateNoteAuthor(String, String)");
1274 browser.noteSignal.geoChanged.connect(listManager, "updateNoteGeoTag(String, Double,Double,Double)");
1275 browser.noteSignal.geoChanged.connect(this, "setNoteDirty()");
1276 browser.noteSignal.sourceUrlChanged.connect(listManager, "updateNoteSourceUrl(String, String)");
1277 browser.blockApplication.connect(this, "blockApplication(BrowserWindow)");
1278 browser.unblockApplication.connect(this, "unblockApplication()");
1279 if (master) browser.focusLost.connect(this, "saveNote()");
1280 browser.resourceSignal.contentChanged.connect(this, "externalFileEdited(String)");
1281 browser.evernoteLinkClicked.connect(this, "evernoteLinkClick(String, String)");
1284 //**************************************************
1286 //**************************************************
1287 private void setupShortcut(QShortcut action, String text) {
1288 if (!Global.shortcutKeys.containsAction(text))
1290 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
1293 //***************************************************************
1294 //***************************************************************
1295 //* Settings and look & feel
1296 //***************************************************************
1297 //***************************************************************
1298 @SuppressWarnings("unused")
1299 private void settings() {
1300 logger.log(logger.HIGH, "Entering NeverNote.settings");
1301 saveNoteColumnPositions();
1302 saveNoteIndexWidth();
1304 ConfigDialog settings = new ConfigDialog(this);
1305 String dateFormat = Global.getDateFormat();
1306 String timeFormat = Global.getTimeFormat();
1308 indexTime = 1000*Global.getIndexThreadSleepInterval();
1309 indexTimer.start(indexTime); // reset indexing timer
1312 indexRunner.indexAttachmentsLocally = Global.indexAttachmentsLocally();
1313 indexRunner.indexNoteBody = Global.indexNoteBody();
1314 indexRunner.indexNoteTitle = Global.indexNoteTitle();
1315 indexRunner.specialIndexCharacters = Global.getSpecialIndexCharacters();
1316 indexRunner.indexImageRecognition = Global.indexImageRecognition();
1317 if (Global.showTrayIcon() || Global.minimizeOnClose())
1322 if (menuBar.showEditorBar.isChecked())
1323 showEditorButtons(browserWindow);
1325 // Reset the save timer
1326 if (Global.getAutoSaveInterval() > 0)
1327 saveTimer.setInterval(1000*60*Global.getAutoSaveInterval());
1332 // Set special reloads
1333 if (settings.getDebugPage().reloadSharedNotebooksClicked()) {
1334 conn.executeSql("Delete from LinkedNotebook");
1335 conn.executeSql("delete from SharedNotebook");
1336 conn.executeSql("Delete from Notebook where linked=true");
1337 conn.executeSql("Insert into Sync (key, value) values ('FullLinkedNotebookSync', 'true')");
1338 conn.executeSql("Insert into Sync (key, value) values ('FullSharedNotebookSync', 'true')");
1343 readOnlyCache.clear();
1344 inkNoteCache.clear();
1345 noteIndexUpdated(true);
1347 logger.log(logger.HIGH, "Leaving NeverNote.settings");
1349 // Restore things to the way they were
1350 private void restoreWindowState(boolean mainWindow) {
1351 // We need to name things or this doesn't work.
1352 setObjectName("NeverNote");
1353 restoreState(Global.restoreState(objectName()));
1354 mainLeftRightSplitter.setObjectName("mainLeftRightSplitter");
1355 browserIndexSplitter.setObjectName("browserIndexSplitter");
1356 leftSplitter1.setObjectName("leftSplitter1");
1358 // Restore the actual positions.
1360 restoreGeometry(Global.restoreGeometry(objectName()));
1361 mainLeftRightSplitter.restoreState(Global.restoreState(mainLeftRightSplitter.objectName()));
1362 browserIndexSplitter.restoreState(Global.restoreState(browserIndexSplitter.objectName()));
1363 leftSplitter1.restoreState(Global.restoreState(leftSplitter1.objectName()));
1366 // Save window positions for the next start
1367 private void saveWindowState() {
1368 Global.saveGeometry(objectName(), saveGeometry());
1369 Global.saveState(mainLeftRightSplitter.objectName(), mainLeftRightSplitter.saveState());
1370 Global.saveState(browserIndexSplitter.objectName(), browserIndexSplitter.saveState());
1371 Global.saveState(leftSplitter1.objectName(), leftSplitter1.saveState());
1372 Global.saveState(objectName(), saveState());
1374 // Load the style sheet
1375 private void loadStyleSheet() {
1376 String styleSheetName = "default.qss";
1377 if (Global.getStyle().equalsIgnoreCase("cleanlooks"))
1378 styleSheetName = "default-cleanlooks.qss";
1379 String fileName = Global.getFileManager().getQssDirPathUser("default.qss");
1380 QFile file = new QFile(fileName);
1382 // If a user default.qss doesn't exist, we use the one shipped with NeverNote
1383 if (!file.exists()) {
1384 fileName = Global.getFileManager().getQssDirPath(styleSheetName);
1385 file = new QFile(fileName);
1387 file.open(OpenModeFlag.ReadOnly);
1388 String styleSheet = file.readAll().toString();
1390 setStyleSheet(styleSheet);
1392 // Save column positions for the next time
1393 private void saveNoteColumnPositions() {
1394 int position = noteTableView.header.visualIndex(Global.noteTableCreationPosition);
1395 Global.setColumnPosition("noteTableCreationPosition", position);
1396 position = noteTableView.header.visualIndex(Global.noteTableTagPosition);
1397 Global.setColumnPosition("noteTableTagPosition", position);
1398 position = noteTableView.header.visualIndex(Global.noteTableNotebookPosition);
1399 Global.setColumnPosition("noteTableNotebookPosition", position);
1400 position = noteTableView.header.visualIndex(Global.noteTableChangedPosition);
1401 Global.setColumnPosition("noteTableChangedPosition", position);
1402 position = noteTableView.header.visualIndex(Global.noteTableAuthorPosition);
1403 Global.setColumnPosition("noteTableAuthorPosition", position);
1404 position = noteTableView.header.visualIndex(Global.noteTableSourceUrlPosition);
1405 Global.setColumnPosition("noteTableSourceUrlPosition", position);
1406 position = noteTableView.header.visualIndex(Global.noteTableSubjectDatePosition);
1407 Global.setColumnPosition("noteTableSubjectDatePosition", position);
1408 position = noteTableView.header.visualIndex(Global.noteTableTitlePosition);
1409 Global.setColumnPosition("noteTableTitlePosition", position);
1410 position = noteTableView.header.visualIndex(Global.noteTableSynchronizedPosition);
1411 Global.setColumnPosition("noteTableSynchronizedPosition", position);
1412 position = noteTableView.header.visualIndex(Global.noteTableGuidPosition);
1413 Global.setColumnPosition("noteTableGuidPosition", position);
1414 position = noteTableView.header.visualIndex(Global.noteTableThumbnailPosition);
1415 Global.setColumnPosition("noteTableThumbnailPosition", position);
1416 position = noteTableView.header.visualIndex(Global.noteTablePinnedPosition);
1417 Global.setColumnPosition("noteTablePinnedPosition", position);
1420 // Save column widths for the next time
1421 private void saveNoteIndexWidth() {
1423 width = noteTableView.getColumnWidth(Global.noteTableCreationPosition);
1424 Global.setColumnWidth("noteTableCreationPosition", width);
1425 width = noteTableView.getColumnWidth(Global.noteTableChangedPosition);
1426 Global.setColumnWidth("noteTableChangedPosition", width);
1427 width = noteTableView.getColumnWidth(Global.noteTableGuidPosition);
1428 Global.setColumnWidth("noteTableGuidPosition", width);
1429 width = noteTableView.getColumnWidth(Global.noteTableNotebookPosition);
1430 Global.setColumnWidth("noteTableNotebookPosition", width);
1431 width = noteTableView.getColumnWidth(Global.noteTableTagPosition);
1432 Global.setColumnWidth("noteTableTagPosition", width);
1433 width = noteTableView.getColumnWidth(Global.noteTableTitlePosition);
1434 Global.setColumnWidth("noteTableTitlePosition", width);
1435 width = noteTableView.getColumnWidth(Global.noteTableSourceUrlPosition);
1436 Global.setColumnWidth("noteTableSourceUrlPosition", width);
1437 width = noteTableView.getColumnWidth(Global.noteTableAuthorPosition);
1438 Global.setColumnWidth("noteTableAuthorPosition", width);
1439 width = noteTableView.getColumnWidth(Global.noteTableSubjectDatePosition);
1440 Global.setColumnWidth("noteTableSubjectDatePosition", width);
1441 width = noteTableView.getColumnWidth(Global.noteTableSynchronizedPosition);
1442 Global.setColumnWidth("noteTableSynchronizedPosition", width);
1443 width = noteTableView.getColumnWidth(Global.noteTableThumbnailPosition);
1444 Global.setColumnWidth("noteTableThumbnailPosition", width);
1445 width = noteTableView.getColumnWidth(Global.noteTableGuidPosition);
1446 Global.setColumnWidth("noteTableGuidPosition", width);
1447 width = noteTableView.getColumnWidth(Global.noteTablePinnedPosition);
1448 Global.setColumnWidth("noteTablePinnedPosition", width);
1451 @SuppressWarnings("unused")
1452 private void toggleSearchWindow() {
1453 logger.log(logger.HIGH, "Entering NeverNote.toggleSearchWindow");
1454 searchLayout.toggleSearchField();
1455 menuBar.hideSearch.setChecked(searchField.isVisible());
1456 Global.saveWindowVisible("searchField", searchField.isVisible());
1457 logger.log(logger.HIGH, "Leaving NeverNote.toggleSearchWindow");
1459 @SuppressWarnings("unused")
1460 private void toggleQuotaWindow() {
1461 logger.log(logger.HIGH, "Entering NeverNote.toggleQuotaWindow");
1462 searchLayout.toggleQuotaBar();
1463 menuBar.hideQuota.setChecked(quotaBar.isVisible());
1464 Global.saveWindowVisible("quota", quotaBar.isVisible());
1465 logger.log(logger.HIGH, "Leaving NeverNote.toggleQuotaWindow");
1467 @SuppressWarnings("unused")
1468 private void toggleZoomWindow() {
1469 logger.log(logger.HIGH, "Entering NeverNote.toggleZoomWindow");
1470 searchLayout.toggleZoom();
1471 menuBar.hideZoom.setChecked(zoomSpinner.isVisible());
1472 Global.saveWindowVisible("zoom", zoomSpinner.isVisible());
1473 logger.log(logger.HIGH, "Leaving NeverNote.toggleZoomWindow");
1478 //***************************************************************
1479 //***************************************************************
1480 //** These functions deal with Notebook menu items
1481 //***************************************************************
1482 //***************************************************************
1483 // Setup the tree containing the user's notebooks.
1484 private void initializeNotebookTree() {
1485 logger.log(logger.HIGH, "Entering NeverNote.initializeNotebookTree");
1486 // notebookTree.itemClicked.connect(this, "notebookTreeSelection()");
1487 notebookTree.selectionSignal.connect(this, "notebookTreeSelection()");
1488 listManager.notebookSignal.refreshNotebookTreeCounts.connect(notebookTree, "updateCounts(List, List)");
1489 logger.log(logger.HIGH, "Leaving NeverNote.initializeNotebookTree");
1491 // Listener when a notebook is selected
1492 private void notebookTreeSelection() {
1493 logger.log(logger.HIGH, "Entering NeverNote.notebookTreeSelection");
1494 noteTableView.proxyModel.blocked = true;
1497 clearAttributeFilter();
1498 clearSavedSearchFilter();
1499 if (Global.mimicEvernoteInterface) {
1501 //searchField.clear();
1502 searchField.clearEditText();
1504 menuBar.noteRestoreAction.setVisible(false);
1505 menuBar.notebookEditAction.setEnabled(true);
1506 menuBar.notebookDeleteAction.setEnabled(true);
1507 menuBar.notebookPublishAction.setEnabled(true);
1508 menuBar.notebookShareAction.setEnabled(true);
1509 menuBar.notebookIconAction.setEnabled(true);
1510 menuBar.notebookStackAction.setEnabled(true);
1511 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1512 selectedNotebookGUIDs.clear();
1514 String stackName = "";
1515 if (selections.size() > 0) {
1516 guid = (selections.get(0).text(2));
1517 stackName = selections.get(0).text(0);
1519 if (!Global.mimicEvernoteInterface) {
1520 // If no notebooks are selected, we make it look like the "all notebooks" one was selected
1521 if (selections.size()==0) {
1522 selectedNotebookGUIDs.clear();
1523 for (int i=0; i < listManager.getNotebookIndex().size(); i++) {
1524 selectedNotebookGUIDs.add(listManager.getNotebookIndex().get(i).getGuid());
1526 menuBar.notebookEditAction.setEnabled(false);
1527 menuBar.notebookDeleteAction.setEnabled(false);
1528 menuBar.notebookStackAction.setEnabled(false);
1529 menuBar.notebookIconAction.setEnabled(false);
1532 if (!guid.equals("") && !guid.equals("STACK")) {
1533 selectedNotebookGUIDs.add(guid);
1534 menuBar.notebookIconAction.setEnabled(true);
1536 menuBar.notebookIconAction.setEnabled(true);
1537 for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1538 Notebook book = listManager.getNotebookIndex().get(j);
1539 if (book.getStack() != null && book.getStack().equalsIgnoreCase(stackName))
1540 selectedNotebookGUIDs.add(book.getGuid());
1543 listManager.setSelectedNotebooks(selectedNotebookGUIDs);
1544 listManager.loadNotesIndex();
1545 noteIndexUpdated(false);
1546 refreshEvernoteNote(true);
1547 listManager.refreshCounters = true;
1548 listManager.refreshCounters();
1549 if (selectedNotebookGUIDs.size() == 1) {
1550 int col = conn.getNotebookTable().getSortColumn(selectedNotebookGUIDs.get(0));
1551 int order = conn.getNotebookTable().getSortOrder(selectedNotebookGUIDs.get(0));
1553 noteTableView.proxyModel.blocked = true;
1555 noteTableView.sortByColumn(col, Qt.SortOrder.DescendingOrder);
1557 noteTableView.sortByColumn(col, Qt.SortOrder.AscendingOrder);
1560 noteTableView.proxyModel.blocked = false;
1561 logger.log(logger.HIGH, "Leaving NeverNote.notebookTreeSelection");
1564 private void clearNotebookFilter() {
1565 notebookTree.blockSignals(true);
1566 notebookTree.clearSelection();
1567 menuBar.noteRestoreAction.setVisible(false);
1568 menuBar.notebookEditAction.setEnabled(false);
1569 menuBar.notebookDeleteAction.setEnabled(false);
1570 selectedNotebookGUIDs.clear();
1571 listManager.setSelectedNotebooks(selectedNotebookGUIDs);
1572 notebookTree.blockSignals(false);
1574 // Triggered when the notebook DB has been updated
1575 private void notebookIndexUpdated() {
1576 logger.log(logger.HIGH, "Entering NeverNote.notebookIndexUpdated");
1578 // Get the possible icons
1579 HashMap<String, QIcon> icons = conn.getNotebookTable().getAllIcons();
1580 notebookTree.setIcons(icons);
1582 if (selectedNotebookGUIDs == null)
1583 selectedNotebookGUIDs = new ArrayList<String>();
1584 List<Notebook> books = conn.getNotebookTable().getAll();
1585 for (int i=books.size()-1; i>=0; i--) {
1586 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1587 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(books.get(i).getGuid())) {
1589 j=listManager.getArchiveNotebookIndex().size();
1595 listManager.countNotebookResults(listManager.getNoteIndex());
1596 notebookTree.blockSignals(true);
1597 notebookTree.load(books, listManager.getLocalNotebooks());
1598 for (int i=selectedNotebookGUIDs.size()-1; i>=0; i--) {
1599 boolean found = notebookTree.selectGuid(selectedNotebookGUIDs.get(i));
1601 selectedNotebookGUIDs.remove(i);
1603 listManager.refreshCounters = true;
1604 listManager.refreshCounters();
1605 notebookTree.blockSignals(false);
1607 logger.log(logger.HIGH, "Leaving NeverNote.notebookIndexUpdated");
1609 // Show/Hide note information
1610 @SuppressWarnings("unused")
1611 private void toggleNotebookWindow() {
1612 logger.log(logger.HIGH, "Entering NeverNote.toggleNotebookWindow");
1613 searchLayout.toggleNotebook();
1614 menuBar.hideNotebooks.setChecked(notebookTree.isVisible());
1615 Global.saveWindowVisible("notebookTree", notebookTree.isVisible());
1616 logger.log(logger.HIGH, "Leaving NeverNote.toggleNotebookWindow");
1618 // Add a new notebook
1619 @SuppressWarnings("unused")
1620 private void addNotebook() {
1621 logger.log(logger.HIGH, "Inside NeverNote.addNotebook");
1622 NotebookEdit edit = new NotebookEdit();
1623 edit.setNotebooks(listManager.getNotebookIndex());
1626 if (!edit.okPressed())
1629 Calendar currentTime = new GregorianCalendar();
1630 Long l = new Long(currentTime.getTimeInMillis());
1631 String randint = new String(Long.toString(l));
1633 Notebook newBook = new Notebook();
1634 newBook.setUpdateSequenceNum(0);
1635 newBook.setGuid(randint);
1636 newBook.setName(edit.getNotebook());
1637 newBook.setServiceCreated(new Date().getTime());
1638 newBook.setServiceUpdated(new Date().getTime());
1639 newBook.setDefaultNotebook(false);
1640 newBook.setPublished(false);
1642 listManager.getNotebookIndex().add(newBook);
1644 listManager.getLocalNotebooks().add(newBook.getGuid());
1645 conn.getNotebookTable().addNotebook(newBook, true, edit.isLocal());
1646 notebookIndexUpdated();
1647 listManager.countNotebookResults(listManager.getNoteIndex());
1648 // notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
1649 logger.log(logger.HIGH, "Leaving NeverNote.addNotebook");
1651 // Edit an existing notebook
1652 @SuppressWarnings("unused")
1653 private void stackNotebook() {
1654 logger.log(logger.HIGH, "Entering NeverNote.stackNotebook");
1655 StackNotebook edit = new StackNotebook();
1657 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1658 QTreeWidgetItem currentSelection;
1659 for (int i=0; i<selections.size(); i++) {
1660 currentSelection = selections.get(0);
1661 String guid = currentSelection.text(2);
1662 if (guid.equalsIgnoreCase("")) {
1663 QMessageBox.critical(this, tr("Unable To Stack") ,tr("You can't stack the \"All Notebooks\" item."));
1666 if (guid.equalsIgnoreCase("STACK")) {
1667 QMessageBox.critical(this, tr("Unable To Stack") ,tr("You can't stack a stack."));
1672 edit.setStackNames(conn.getNotebookTable().getAllStackNames());
1677 if (!edit.okPressed())
1680 String stack = edit.getStackName();
1682 for (int i=0; i<selections.size(); i++) {
1683 currentSelection = selections.get(i);
1684 String guid = currentSelection.text(2);
1685 listManager.updateNotebookStack(guid, stack);
1687 notebookIndexUpdated();
1688 logger.log(logger.HIGH, "Leaving NeverNote.stackNotebook");
1690 // Edit an existing notebook
1691 @SuppressWarnings("unused")
1692 private void editNotebook() {
1693 logger.log(logger.HIGH, "Entering NeverNote.editNotebook");
1694 NotebookEdit edit = new NotebookEdit();
1696 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1697 QTreeWidgetItem currentSelection;
1698 currentSelection = selections.get(0);
1699 edit.setNotebook(currentSelection.text(0));
1701 String guid = currentSelection.text(2);
1702 if (!guid.equalsIgnoreCase("STACK")) {
1703 edit.setTitle(tr("Edit Notebook"));
1704 edit.setNotebooks(listManager.getNotebookIndex());
1705 edit.setLocalCheckboxEnabled(false);
1706 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1707 if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
1708 edit.setDefaultNotebook(listManager.getNotebookIndex().get(i).isDefaultNotebook());
1709 i=listManager.getNotebookIndex().size();
1713 edit.setTitle(tr("Edit Stack"));
1714 edit.setStacks(conn.getNotebookTable().getAllStackNames());
1715 edit.hideLocalCheckbox();
1716 edit.hideDefaultCheckbox();
1721 if (!edit.okPressed())
1725 if (guid.equalsIgnoreCase("STACK")) {
1726 conn.getNotebookTable().renameStacks(currentSelection.text(0), edit.getNotebook());
1727 for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1728 if (listManager.getNotebookIndex().get(j).getStack() != null &&
1729 listManager.getNotebookIndex().get(j).getStack().equalsIgnoreCase(currentSelection.text(0)))
1730 listManager.getNotebookIndex().get(j).setStack(edit.getNotebook());
1732 conn.getNotebookTable().renameStacks(currentSelection.text(0), edit.getNotebook());
1733 currentSelection.setText(0, edit.getNotebook());
1737 updateListNotebookName(currentSelection.text(0), edit.getNotebook());
1738 currentSelection.setText(0, edit.getNotebook());
1740 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1741 if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
1742 listManager.getNotebookIndex().get(i).setName(edit.getNotebook());
1743 if (!listManager.getNotebookIndex().get(i).isDefaultNotebook() && edit.isDefaultNotebook()) {
1744 for (int j=0; j<listManager.getNotebookIndex().size(); j++)
1745 listManager.getNotebookIndex().get(j).setDefaultNotebook(false);
1746 listManager.getNotebookIndex().get(i).setDefaultNotebook(true);
1747 conn.getNotebookTable().setDefaultNotebook(listManager.getNotebookIndex().get(i).getGuid());
1749 conn.getNotebookTable().updateNotebook(listManager.getNotebookIndex().get(i), true);
1750 if (conn.getNotebookTable().isLinked(listManager.getNotebookIndex().get(i).getGuid())) {
1751 LinkedNotebook linkedNotebook = conn.getLinkedNotebookTable().getByNotebookGuid(listManager.getNotebookIndex().get(i).getGuid());
1752 linkedNotebook.setShareName(edit.getNotebook());
1753 conn.getLinkedNotebookTable().updateNotebook(linkedNotebook, true);
1755 i=listManager.getNotebookIndex().size();
1759 // Build a list of non-closed notebooks
1760 List<Notebook> nbooks = new ArrayList<Notebook>();
1761 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1762 boolean found=false;
1763 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1764 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
1768 nbooks.add(listManager.getNotebookIndex().get(i));
1772 FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger);
1773 List<Notebook> filteredBooks = notebookFilter.getValidNotebooks(currentNote, listManager.getNotebookIndex());
1774 browserWindow.setNotebookList(filteredBooks);
1775 Iterator<String> set = externalWindows.keySet().iterator();
1776 while(set.hasNext())
1777 externalWindows.get(set.next()).getBrowserWindow().setNotebookList(filteredBooks);
1778 logger.log(logger.HIGH, "Leaving NeverNote.editNotebook");
1780 // Publish a notebook
1781 @SuppressWarnings("unused")
1782 private void publishNotebook() {
1783 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1784 QTreeWidgetItem currentSelection;
1785 currentSelection = selections.get(0);
1786 String guid = currentSelection.text(2);
1788 if (guid.equalsIgnoreCase("STACK") || guid.equalsIgnoreCase(""))
1793 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1794 if (guid.equals(listManager.getNotebookIndex().get(i).getGuid())) {
1795 n = listManager.getNotebookIndex().get(i);
1797 i = listManager.getNotebookIndex().size();
1803 PublishNotebook publish = new PublishNotebook(Global.username, Global.getServer(), n);
1806 if (!publish.okClicked())
1809 Publishing p = publish.getPublishing();
1810 boolean isPublished = !publish.isStopPressed();
1811 conn.getNotebookTable().setPublishing(n.getGuid(), isPublished, p);
1812 n.setPublished(isPublished);
1814 listManager.getNotebookIndex().set(position, n);
1815 notebookIndexUpdated();
1817 // Publish a notebook
1818 @SuppressWarnings("unused")
1819 private void shareNotebook() {
1820 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1821 QTreeWidgetItem currentSelection;
1822 currentSelection = selections.get(0);
1823 String guid = currentSelection.text(2);
1825 if (guid.equalsIgnoreCase("STACK") || guid.equalsIgnoreCase(""))
1829 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1830 if (guid.equals(listManager.getNotebookIndex().get(i).getGuid())) {
1831 n = listManager.getNotebookIndex().get(i);
1832 i = listManager.getNotebookIndex().size();
1836 String authToken = null;
1837 if (syncRunner.isConnected)
1838 authToken = syncRunner.authToken;
1839 ShareNotebook share = new ShareNotebook(n.getName(), conn, n, syncRunner);
1844 // Delete an existing notebook
1845 @SuppressWarnings("unused")
1846 private void deleteNotebook() {
1847 logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
1848 boolean stacksFound = false;
1849 boolean notebooksFound = false;
1850 boolean assigned = false;
1851 // Check if any notes have this notebook
1852 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1853 for (int i=0; i<selections.size(); i++) {
1854 QTreeWidgetItem currentSelection;
1855 currentSelection = selections.get(i);
1856 String guid = currentSelection.text(2);
1857 if (!guid.equalsIgnoreCase("STACK")) {
1858 notebooksFound = true;
1859 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
1860 String noteGuid = listManager.getNoteIndex().get(j).getNotebookGuid();
1861 if (noteGuid.equals(guid)) {
1863 j=listManager.getNoteIndex().size();
1864 i=selections.size();
1872 QMessageBox.information(this, tr("Unable to Delete"), tr("Some of the selected notebook(s) contain notes.\n"+
1873 "Please delete the notes or move them to another notebook before deleting any notebooks."));
1877 if (conn.getNotebookTable().getAll().size() == 1) {
1878 QMessageBox.information(this, tr("Unable to Delete"), tr("You must have at least one notebook."));
1882 // If all notebooks are clear, verify the delete
1883 String msg1 = new String(tr("Delete selected notebooks?"));
1884 String msg2 = new String(tr("Remove selected stacks (notebooks will not be deleted)?"));
1885 String msg3 = new String(tr("Delete selected notebooks & remove stacks? Notebooks under the stacks are" +
1886 " not deleted unless selected?"));
1888 if (stacksFound && notebooksFound)
1890 if (!stacksFound && notebooksFound)
1892 if (stacksFound && !notebooksFound)
1894 if (QMessageBox.question(this, tr("Confirmation"), msg,
1895 QMessageBox.StandardButton.Yes,
1896 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1900 // If confirmed, delete the notebook
1901 for (int i=selections.size()-1; i>=0; i--) {
1902 QTreeWidgetItem currentSelection;
1903 currentSelection = selections.get(i);
1904 String guid = currentSelection.text(2);
1905 if (currentSelection.text(2).equalsIgnoreCase("STACK")) {
1906 conn.getNotebookTable().renameStacks(currentSelection.text(0), "");
1907 listManager.renameStack(currentSelection.text(0), "");
1909 conn.getNotebookTable().expungeNotebook(guid, true);
1910 listManager.deleteNotebook(guid);
1914 notebookIndexUpdated();
1915 // notebookTreeSelection();
1916 // notebookTree.load(listManager.getNotebookIndex(), listManager.getLocalNotebooks());
1917 // listManager.countNotebookResults(listManager.getNoteIndex());
1918 logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
1920 // A note's notebook has been updated
1921 @SuppressWarnings("unused")
1922 private void updateNoteNotebook(String guid, String notebookGuid) {
1924 // Update the list manager
1925 listManager.updateNoteNotebook(guid, notebookGuid);
1926 listManager.countNotebookResults(listManager.getNoteIndex());
1927 // notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
1929 // Find the name of the notebook
1930 String notebookName = null;
1931 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1932 if (listManager.getNotebookIndex().get(i).getGuid().equals(notebookGuid)) {
1933 notebookName = listManager.getNotebookIndex().get(i).getName();
1938 // If we found the name, update the browser window
1939 if (notebookName != null) {
1940 updateListNoteNotebook(guid, notebookName);
1941 if (guid.equals(currentNoteGuid)) {
1942 int pos = browserWindow.notebookBox.findText(notebookName);
1944 browserWindow.notebookBox.setCurrentIndex(pos);
1948 // If we're dealing with the current note, then we need to be sure and update the notebook there
1949 if (guid.equals(currentNoteGuid)) {
1950 if (currentNote != null) {
1951 currentNote.setNotebookGuid(notebookGuid);
1955 // Open/close notebooks
1956 @SuppressWarnings("unused")
1957 private void closeNotebooks() {
1958 NotebookArchive na = new NotebookArchive(listManager.getNotebookIndex(), listManager.getArchiveNotebookIndex());
1960 if (!na.okClicked())
1964 listManager.getArchiveNotebookIndex().clear();
1966 for (int i=na.getClosedBookList().count()-1; i>=0; i--) {
1967 String text = na.getClosedBookList().takeItem(i).text();
1968 for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1969 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
1970 Notebook n = listManager.getNotebookIndex().get(j);
1971 conn.getNotebookTable().setArchived(n.getGuid(),true);
1972 listManager.getArchiveNotebookIndex().add(n);
1973 j=listManager.getNotebookIndex().size();
1978 for (int i=na.getOpenBookList().count()-1; i>=0; i--) {
1979 String text = na.getOpenBookList().takeItem(i).text();
1980 for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1981 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
1982 Notebook n = listManager.getNotebookIndex().get(j);
1983 conn.getNotebookTable().setArchived(n.getGuid(),false);
1984 j=listManager.getNotebookIndex().size();
1988 notebookTreeSelection();
1989 listManager.loadNotesIndex();
1990 notebookIndexUpdated();
1991 noteIndexUpdated(false);
1992 reloadTagTree(true);
1993 // noteIndexUpdated(false);
1995 // Build a list of non-closed notebooks
1996 List<Notebook> nbooks = new ArrayList<Notebook>();
1997 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1998 boolean found=false;
1999 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
2000 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
2004 nbooks.add(listManager.getNotebookIndex().get(i));
2007 FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger);
2008 List<Notebook> filteredBooks = notebookFilter.getValidNotebooks(currentNote, listManager.getNotebookIndex());
2009 browserWindow.setNotebookList(filteredBooks);
2011 // Update any external windows
2012 Iterator<String> set = externalWindows.keySet().iterator();
2013 while(set.hasNext())
2014 externalWindows.get(set.next()).getBrowserWindow().setNotebookList(filteredBooks);
2018 // Change the notebook's icon
2019 @SuppressWarnings("unused")
2020 private void setNotebookIcon() {
2021 boolean stackSelected = false;
2022 boolean allNotebookSelected = false;
2024 QTreeWidgetItem currentSelection;
2025 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
2026 if (selections.size() == 0)
2029 currentSelection = selections.get(0);
2030 String guid = currentSelection.text(2);
2031 if (guid.equalsIgnoreCase(""))
2032 allNotebookSelected = true;
2033 if (guid.equalsIgnoreCase("STACK"))
2034 stackSelected = true;
2036 QIcon currentIcon = currentSelection.icon(0);
2040 if (!stackSelected && !allNotebookSelected) {
2041 icon = conn.getNotebookTable().getIcon(guid);
2043 dialog = new SetIcon(currentIcon, saveLastPath);
2044 dialog.setUseDefaultIcon(true);
2046 dialog = new SetIcon(icon, saveLastPath);
2047 dialog.setUseDefaultIcon(false);
2050 if (stackSelected) {
2051 icon = conn.getSystemIconTable().getIcon(currentSelection.text(0), "STACK");
2053 icon = conn.getSystemIconTable().getIcon(currentSelection.text(0), "ALLNOTEBOOK");
2056 dialog = new SetIcon(currentIcon, saveLastPath);
2057 dialog.setUseDefaultIcon(true);
2059 dialog = new SetIcon(icon, saveLastPath);
2060 dialog.setUseDefaultIcon(false);
2064 if (dialog.okPressed()) {
2065 saveLastPath = dialog.getPath();
2067 QIcon newIcon = dialog.getIcon();
2068 if (stackSelected) {
2069 conn.getSystemIconTable().setIcon(currentSelection.text(0), "STACK", newIcon, dialog.getFileType());
2070 if (newIcon == null) {
2071 newIcon = new QIcon(iconPath+"books2.png");
2073 currentSelection.setIcon(0,newIcon);
2076 if (allNotebookSelected) {
2077 conn.getSystemIconTable().setIcon(currentSelection.text(0), "ALLNOTEBOOK", newIcon, dialog.getFileType());
2078 if (newIcon == null) {
2079 newIcon = new QIcon(iconPath+"notebook-green.png");
2081 currentSelection.setIcon(0,newIcon);
2084 conn.getNotebookTable().setIcon(guid, newIcon, dialog.getFileType());
2085 if (newIcon == null) {
2086 boolean isPublished = false;;
2087 boolean found = false;
2088 for (int i=0; i<listManager.getNotebookIndex().size() && !found; i++) {
2089 if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
2090 isPublished = listManager.getNotebookIndex().get(i).isPublished();
2094 newIcon = notebookTree.findDefaultIcon(guid, currentSelection.text(1), listManager.getLocalNotebooks(), isPublished);
2096 currentSelection.setIcon(0, newIcon);
2102 //***************************************************************
2103 //***************************************************************
2104 //** These functions deal with Tag menu items
2105 //***************************************************************
2106 //***************************************************************
2107 // Add a new notebook
2108 @SuppressWarnings("unused")
2109 private void addTag() {
2110 logger.log(logger.HIGH, "Inside NeverNote.addTag");
2111 TagEdit edit = new TagEdit();
2112 edit.setTagList(listManager.getTagIndex());
2114 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2115 QTreeWidgetItem currentSelection = null;
2116 if (selections.size() > 0) {
2117 currentSelection = selections.get(0);
2118 edit.setParentTag(currentSelection.text(0));
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 Tag newTag = new Tag();
2131 newTag.setUpdateSequenceNum(0);
2132 newTag.setGuid(randint);
2133 newTag.setName(edit.getTag());
2134 if (edit.getParentTag().isChecked()) {
2135 newTag.setParentGuid(currentSelection.text(2));
2136 newTag.setParentGuidIsSet(true);
2137 currentSelection.setExpanded(true);
2139 conn.getTagTable().addTag(newTag, true);
2140 listManager.getTagIndex().add(newTag);
2141 reloadTagTree(true);
2143 logger.log(logger.HIGH, "Leaving NeverNote.addTag");
2145 @SuppressWarnings("unused")
2146 private void reloadTagTree() {
2147 reloadTagTree(false);
2149 private void reloadTagTree(boolean reload) {
2150 logger.log(logger.HIGH, "Entering NeverNote.reloadTagTree");
2151 tagIndexUpdated(reload);
2152 boolean filter = false;
2154 listManager.countTagResults(listManager.getNoteIndex());
2155 if (notebookTree.selectedItems().size() > 0
2156 && !notebookTree.selectedItems().get(0).text(0).equalsIgnoreCase("All Notebooks"))
2158 if (tagTree.selectedItems().size() > 0)
2160 tagTree.showAllTags(!filter);
2161 tagIndexUpdated(false);
2162 logger.log(logger.HIGH, "Leaving NeverNote.reloadTagTree");
2164 // Edit an existing tag
2165 @SuppressWarnings("unused")
2166 private void editTag() {
2167 logger.log(logger.HIGH, "Entering NeverNote.editTag");
2168 TagEdit edit = new TagEdit();
2169 edit.setTitle("Edit Tag");
2170 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2171 QTreeWidgetItem currentSelection;
2172 currentSelection = selections.get(0);
2173 edit.setTag(currentSelection.text(0));
2174 edit.setTagList(listManager.getTagIndex());
2177 if (!edit.okPressed())
2180 String guid = currentSelection.text(2);
2181 currentSelection.setText(0,edit.getTag());
2183 for (int i=0; i<listManager.getTagIndex().size(); i++) {
2184 if (listManager.getTagIndex().get(i).getGuid().equals(guid)) {
2185 listManager.getTagIndex().get(i).setName(edit.getTag());
2186 conn.getTagTable().updateTag(listManager.getTagIndex().get(i), true);
2187 updateListTagName(guid);
2188 if (currentNote != null && currentNote.getTagGuids().contains(guid))
2189 browserWindow.setTag(getTagNamesForNote(currentNote));
2190 logger.log(logger.HIGH, "Leaving NeverNote.editTag");
2194 listManager.reloadNoteTagNames(guid, edit.getTag());
2195 noteIndexUpdated(true);
2196 refreshEvernoteNote(true);
2197 browserWindow.setTag(getTagNamesForNote(currentNote));
2198 logger.log(logger.HIGH, "Leaving NeverNote.editTag...");
2200 // Delete an existing tag
2201 @SuppressWarnings("unused")
2202 private void deleteTag() {
2203 logger.log(logger.HIGH, "Entering NeverNote.deleteTag");
2205 if (QMessageBox.question(this, tr("Confirmation"), tr("Delete the selected tags?"),
2206 QMessageBox.StandardButton.Yes,
2207 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
2211 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2212 for (int i=selections.size()-1; i>=0; i--) {
2213 QTreeWidgetItem currentSelection;
2214 currentSelection = selections.get(i);
2215 removeTagItem(currentSelection.text(2));
2217 tagIndexUpdated(true);
2219 listManager.countTagResults(listManager.getNoteIndex());
2220 // tagTree.updateCounts(listManager.getTagCounter());
2221 logger.log(logger.HIGH, "Leaving NeverNote.deleteTag");
2223 // Remove a tag tree item. Go recursively down & remove the children too
2224 private void removeTagItem(String guid) {
2225 for (int j=listManager.getTagIndex().size()-1; j>=0; j--) {
2226 String parent = listManager.getTagIndex().get(j).getParentGuid();
2227 if (parent != null && parent.equals(guid)) {
2228 //Remove this tag's children
2229 removeTagItem(listManager.getTagIndex().get(j).getGuid());
2232 //Now, remove this tag
2233 removeListTagName(guid);
2234 conn.getTagTable().expungeTag(guid, true);
2235 for (int a=0; a<listManager.getTagIndex().size(); a++) {
2236 if (listManager.getTagIndex().get(a).getGuid().equals(guid)) {
2237 listManager.getTagIndex().remove(a);
2242 // Setup the tree containing the user's tags
2243 private void initializeTagTree() {
2244 logger.log(logger.HIGH, "Entering NeverNote.initializeTagTree");
2245 // tagTree.itemSelectionChanged.connect(this, "tagTreeSelection()");
2246 // tagTree.itemClicked.connect(this, "tagTreeSelection()");
2247 tagTree.selectionSignal.connect(this, "tagTreeSelection()");
2248 listManager.tagSignal.refreshTagTreeCounts.connect(tagTree, "updateCounts(List)");
2249 logger.log(logger.HIGH, "Leaving NeverNote.initializeTagTree");
2251 // Listener when a tag is selected
2252 private void tagTreeSelection() {
2253 logger.log(logger.HIGH, "Entering NeverNote.tagTreeSelection");
2256 clearAttributeFilter();
2257 clearSavedSearchFilter();
2259 menuBar.noteRestoreAction.setVisible(false);
2261 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2262 QTreeWidgetItem currentSelection;
2263 selectedTagGUIDs.clear();
2264 for (int i=0; i<selections.size(); i++) {
2265 currentSelection = selections.get(i);
2266 selectedTagGUIDs.add(currentSelection.text(2));
2268 if (selections.size() > 0) {
2269 menuBar.tagEditAction.setEnabled(true);
2270 menuBar.tagDeleteAction.setEnabled(true);
2271 menuBar.tagIconAction.setEnabled(true);
2274 menuBar.tagEditAction.setEnabled(false);
2275 menuBar.tagDeleteAction.setEnabled(false);
2276 menuBar.tagIconAction.setEnabled(true);
2278 if (selections.size() > 1)
2279 menuBar.tagMergeAction.setEnabled(true);
2281 menuBar.tagMergeAction.setEnabled(false);
2282 listManager.setSelectedTags(selectedTagGUIDs);
2283 listManager.loadNotesIndex();
2284 noteIndexUpdated(false);
2285 refreshEvernoteNote(true);
2286 listManager.refreshCounters = true;
2287 listManager.refreshCounters();
2288 logger.log(logger.HIGH, "Leaving NeverNote.tagTreeSelection");
2290 // trigger the tag index to be refreshed
2291 @SuppressWarnings("unused")
2292 private void tagIndexUpdated() {
2293 tagIndexUpdated(true);
2295 private void tagIndexUpdated(boolean reload) {
2296 logger.log(logger.HIGH, "Entering NeverNote.tagIndexUpdated");
2297 if (selectedTagGUIDs == null)
2298 selectedTagGUIDs = new ArrayList<String>();
2300 listManager.reloadTagIndex();
2302 tagTree.blockSignals(true);
2304 tagTree.setIcons(conn.getTagTable().getAllIcons());
2305 tagTree.load(listManager.getTagIndex());
2308 for (int i=selectedTagGUIDs.size()-1; i>=0; i--) {
2309 boolean found = tagTree.selectGuid(selectedTagGUIDs.get(i));
2311 selectedTagGUIDs.remove(i);
2313 tagTree.blockSignals(false);
2315 browserWindow.setTag(getTagNamesForNote(currentNote));
2316 logger.log(logger.HIGH, "Leaving NeverNote.tagIndexUpdated");
2318 // Show/Hide note information
2319 @SuppressWarnings("unused")
2320 private void toggleTagWindow() {
2321 logger.log(logger.HIGH, "Entering NeverNote.toggleTagWindow");
2322 if (tagTree.isVisible())
2326 menuBar.hideTags.setChecked(tagTree.isVisible());
2327 Global.saveWindowVisible("tagTree", tagTree.isVisible());
2328 logger.log(logger.HIGH, "Leaving NeverNote.toggleTagWindow");
2330 // A note's tags have been updated
2331 @SuppressWarnings("unused")
2332 private void updateNoteTags(String guid, List<String> tags) {
2333 // Save any new tags. We'll need them later.
2334 List<String> newTags = new ArrayList<String>();
2335 for (int i=0; i<tags.size(); i++) {
2336 if (conn.getTagTable().findTagByName(tags.get(i))==null)
2337 newTags.add(tags.get(i));
2340 listManager.saveNoteTags(guid, tags);
2341 listManager.countTagResults(listManager.getNoteIndex());
2342 StringBuffer names = new StringBuffer("");
2343 for (int i=0; i<tags.size(); i++) {
2344 names = names.append(tags.get(i));
2345 if (i<tags.size()-1) {
2346 names.append(Global.tagDelimeter + " ");
2349 browserWindow.setTag(names.toString());
2352 // Now, we need to add any new tags to the tag tree
2353 for (int i=0; i<newTags.size(); i++)
2354 tagTree.insertTag(newTags.get(i), conn.getTagTable().findTagByName(newTags.get(i)));
2356 // Get a string containing all tag names for a note
2357 private String getTagNamesForNote(Note n) {
2358 logger.log(logger.HIGH, "Entering NeverNote.getTagNamesForNote");
2359 if (n==null || n.getGuid() == null || n.getGuid().equals(""))
2361 StringBuffer buffer = new StringBuffer(100);
2362 Vector<String> v = new Vector<String>();
2363 List<String> guids = n.getTagGuids();
2368 for (int i=0; i<guids.size(); i++) {
2369 v.add(listManager.getTagNameByGuid(guids.get(i)));
2371 Comparator<String> comparator = Collections.reverseOrder();
2372 Collections.sort(v,comparator);
2373 Collections.reverse(v);
2375 for (int i = 0; i<v.size(); i++) {
2377 buffer.append(", ");
2378 buffer.append(v.get(i));
2381 logger.log(logger.HIGH, "Leaving NeverNote.getTagNamesForNote");
2382 return buffer.toString();
2384 // Tags were added via dropping notes from the note list
2385 @SuppressWarnings("unused")
2386 private void tagsAdded(String noteGuid, String tagGuid) {
2387 String tagName = null;
2388 for (int i=0; i<listManager.getTagIndex().size(); i++) {
2389 if (listManager.getTagIndex().get(i).getGuid().equals(tagGuid)) {
2390 tagName = listManager.getTagIndex().get(i).getName();
2391 i=listManager.getTagIndex().size();
2394 if (tagName == null)
2397 for (int i=0; i<listManager.getMasterNoteIndex().size(); i++) {
2398 if (listManager.getMasterNoteIndex().get(i).getGuid().equals(noteGuid)) {
2399 List<String> tagNames = new ArrayList<String>();
2400 tagNames.add(new String(tagName));
2401 Note n = listManager.getMasterNoteIndex().get(i);
2402 for (int j=0; j<n.getTagNames().size(); j++) {
2403 tagNames.add(new String(n.getTagNames().get(j)));
2405 listManager.getNoteTableModel().updateNoteTags(noteGuid, n.getTagGuids(), tagNames);
2406 if (n.getGuid().equals(currentNoteGuid)) {
2407 Collections.sort(tagNames);
2408 String display = "";
2409 for (int j=0; j<tagNames.size(); j++) {
2410 display = display+tagNames.get(j);
2411 if (j+2<tagNames.size())
2412 display = display+Global.tagDelimeter+" ";
2414 browserWindow.setTag(display);
2416 i=listManager.getMasterNoteIndex().size();
2421 listManager.getNoteTableModel().updateNoteSyncStatus(noteGuid, false);
2423 private void clearTagFilter() {
2424 tagTree.blockSignals(true);
2425 tagTree.clearSelection();
2426 menuBar.noteRestoreAction.setVisible(false);
2427 menuBar.tagEditAction.setEnabled(false);
2428 menuBar.tagMergeAction.setEnabled(false);
2429 menuBar.tagDeleteAction.setEnabled(false);
2430 menuBar.tagIconAction.setEnabled(false);
2431 selectedTagGUIDs.clear();
2432 listManager.setSelectedTags(selectedTagGUIDs);
2433 tagTree.blockSignals(false);
2435 // Change the icon for a tag
2436 @SuppressWarnings("unused")
2437 private void setTagIcon() {
2438 QTreeWidgetItem currentSelection;
2439 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2440 if (selections.size() == 0)
2443 currentSelection = selections.get(0);
2444 String guid = currentSelection.text(2);
2446 QIcon currentIcon = currentSelection.icon(0);
2447 QIcon icon = conn.getTagTable().getIcon(guid);
2450 dialog = new SetIcon(currentIcon, saveLastPath);
2451 dialog.setUseDefaultIcon(true);
2453 dialog = new SetIcon(icon, saveLastPath);
2454 dialog.setUseDefaultIcon(false);
2457 if (dialog.okPressed()) {
2458 saveLastPath = dialog.getPath();
2459 QIcon newIcon = dialog.getIcon();
2460 conn.getTagTable().setIcon(guid, newIcon, dialog.getFileType());
2461 if (newIcon == null)
2462 newIcon = new QIcon(iconPath+"tag.png");
2463 currentSelection.setIcon(0, newIcon);
2468 @SuppressWarnings("unused")
2469 private void mergeTags() {
2470 List<Tag> tags = new ArrayList<Tag>();
2471 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2472 for (int i=0; i<selections.size(); i++) {
2473 Tag record = new Tag();
2474 record.setGuid(selections.get(i).text(2));
2475 record.setName(selections.get(i).text(0));
2479 TagMerge mergeDialog = new TagMerge(tags);
2481 if (!mergeDialog.okClicked())
2483 String newGuid = mergeDialog.getNewTagGuid();
2485 for (int i=0; i<tags.size(); i++) {
2486 if (!tags.get(i).getGuid().equals(newGuid)) {
2487 List<String> noteGuids = conn.getNoteTable().noteTagsTable.getTagNotes(tags.get(i).getGuid());
2488 for (int j=0; j<noteGuids.size(); j++) {
2489 String noteGuid = noteGuids.get(j);
2490 conn.getNoteTable().noteTagsTable.deleteNoteTag(noteGuid);
2491 if (!conn.getNoteTable().noteTagsTable.checkNoteNoteTags(noteGuid, newGuid))
2492 conn.getNoteTable().noteTagsTable.saveNoteTag(noteGuid, newGuid);
2496 listManager.reloadIndexes();
2499 //***************************************************************
2500 //***************************************************************
2501 //** These functions deal with Saved Search menu items
2502 //***************************************************************
2503 //***************************************************************
2504 // Add a new notebook
2505 @SuppressWarnings("unused")
2506 private void addSavedSearch() {
2507 logger.log(logger.HIGH, "Inside NeverNote.addSavedSearch");
2508 SavedSearchEdit edit = new SavedSearchEdit();
2509 edit.setSearchList(listManager.getSavedSearchIndex());
2512 if (!edit.okPressed())
2515 Calendar currentTime = new GregorianCalendar();
2516 Long l = new Long(currentTime.getTimeInMillis());
2517 String randint = new String(Long.toString(l));
2519 SavedSearch search = new SavedSearch();
2520 search.setUpdateSequenceNum(0);
2521 search.setGuid(randint);
2522 search.setName(edit.getName());
2523 search.setQuery(edit.getQuery());
2524 search.setFormat(QueryFormat.USER);
2525 listManager.getSavedSearchIndex().add(search);
2526 conn.getSavedSearchTable().addSavedSearch(search, true);
2527 savedSearchIndexUpdated();
2528 logger.log(logger.HIGH, "Leaving NeverNote.addSavedSearch");
2530 // Edit an existing tag
2531 @SuppressWarnings("unused")
2532 private void editSavedSearch() {
2533 logger.log(logger.HIGH, "Entering NeverNote.editSavedSearch");
2534 SavedSearchEdit edit = new SavedSearchEdit();
2535 edit.setTitle(tr("Edit Search"));
2536 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2537 QTreeWidgetItem currentSelection;
2538 currentSelection = selections.get(0);
2539 String guid = currentSelection.text(1);
2540 SavedSearch s = conn.getSavedSearchTable().getSavedSearch(guid);
2541 edit.setName(currentSelection.text(0));
2542 edit.setQuery(s.getQuery());
2543 edit.setSearchList(listManager.getSavedSearchIndex());
2546 if (!edit.okPressed())
2549 List<SavedSearch> list = listManager.getSavedSearchIndex();
2550 SavedSearch search = null;
2551 boolean found = false;
2552 for (int i=0; i<list.size(); i++) {
2553 search = list.get(i);
2554 if (search.getGuid().equals(guid)) {
2561 search.setName(edit.getName());
2562 search.setQuery(edit.getQuery());
2563 conn.getSavedSearchTable().updateSavedSearch(search, true);
2564 savedSearchIndexUpdated();
2565 logger.log(logger.HIGH, "Leaving NeverNote.editSavedSearch");
2567 // Delete an existing tag
2568 @SuppressWarnings("unused")
2569 private void deleteSavedSearch() {
2570 logger.log(logger.HIGH, "Entering NeverNote.deleteSavedSearch");
2572 if (QMessageBox.question(this, tr("Confirmation"), tr("Delete the selected search?"),
2573 QMessageBox.StandardButton.Yes,
2574 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
2578 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2579 for (int i=selections.size()-1; i>=0; i--) {
2580 QTreeWidgetItem currentSelection;
2581 currentSelection = selections.get(i);
2582 for (int j=0; j<listManager.getSavedSearchIndex().size(); j++) {
2583 if (listManager.getSavedSearchIndex().get(j).getGuid().equals(currentSelection.text(1))) {
2584 conn.getSavedSearchTable().expungeSavedSearch(listManager.getSavedSearchIndex().get(j).getGuid(), true);
2585 listManager.getSavedSearchIndex().remove(j);
2586 j=listManager.getSavedSearchIndex().size()+1;
2589 selections.remove(i);
2591 savedSearchIndexUpdated();
2592 logger.log(logger.HIGH, "Leaving NeverNote.deleteSavedSearch");
2594 // Setup the tree containing the user's tags
2595 private void initializeSavedSearchTree() {
2596 logger.log(logger.HIGH, "Entering NeverNote.initializeSavedSearchTree");
2597 savedSearchTree.itemSelectionChanged.connect(this, "savedSearchTreeSelection()");
2598 logger.log(logger.HIGH, "Leaving NeverNote.initializeSavedSearchTree");
2600 // Listener when a tag is selected
2601 @SuppressWarnings("unused")
2602 private void savedSearchTreeSelection() {
2603 logger.log(logger.HIGH, "Entering NeverNote.savedSearchTreeSelection");
2605 clearNotebookFilter();
2608 clearAttributeFilter();
2610 String currentGuid = selectedSavedSearchGUID;
2611 menuBar.savedSearchEditAction.setEnabled(true);
2612 menuBar.savedSearchDeleteAction.setEnabled(true);
2613 menuBar.savedSearchIconAction.setEnabled(true);
2614 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2615 QTreeWidgetItem currentSelection;
2616 selectedSavedSearchGUID = "";
2617 for (int i=0; i<selections.size(); i++) {
2618 currentSelection = selections.get(i);
2619 if (currentSelection.text(1).equals(currentGuid)) {
2620 currentSelection.setSelected(false);
2622 selectedSavedSearchGUID = currentSelection.text(1);
2624 // i = selections.size() +1;
2627 // There is the potential for no notebooks to be selected if this
2628 // happens then we make it look like all notebooks were selecetd.
2629 // If that happens, just select the "all notebooks"
2630 if (selections.size()==0) {
2631 clearSavedSearchFilter();
2633 listManager.setSelectedSavedSearch(selectedSavedSearchGUID);
2635 logger.log(logger.HIGH, "Leaving NeverNote.savedSearchTreeSelection");
2637 private void clearSavedSearchFilter() {
2638 menuBar.savedSearchEditAction.setEnabled(false);
2639 menuBar.savedSearchDeleteAction.setEnabled(false);
2640 menuBar.savedSearchIconAction.setEnabled(false);
2641 savedSearchTree.blockSignals(true);
2642 savedSearchTree.clearSelection();
2643 savedSearchTree.blockSignals(false);
2644 selectedSavedSearchGUID = "";
2645 searchField.setEditText("");
2646 searchPerformed = false;
2647 listManager.setSelectedSavedSearch(selectedSavedSearchGUID);
2649 // trigger the tag index to be refreshed
2650 private void savedSearchIndexUpdated() {
2651 if (selectedSavedSearchGUID == null)
2652 selectedSavedSearchGUID = new String();
2653 savedSearchTree.blockSignals(true);
2654 savedSearchTree.setIcons(conn.getSavedSearchTable().getAllIcons());
2655 savedSearchTree.load(listManager.getSavedSearchIndex());
2656 savedSearchTree.selectGuid(selectedSavedSearchGUID);
2657 savedSearchTree.blockSignals(false);
2659 // trigger when the saved search selection changes
2660 @SuppressWarnings("unused")
2661 private void updateSavedSearchSelection() {
2662 logger.log(logger.HIGH, "Entering NeverNote.updateSavedSearchSelection()");
2664 menuBar.savedSearchEditAction.setEnabled(true);
2665 menuBar.savedSearchDeleteAction.setEnabled(true);
2666 menuBar.savedSearchIconAction.setEnabled(true);
2667 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2669 if (selections.size() > 0) {
2670 menuBar.savedSearchEditAction.setEnabled(true);
2671 menuBar.savedSearchDeleteAction.setEnabled(true);
2672 menuBar.savedSearchIconAction.setEnabled(true);
2673 selectedSavedSearchGUID = selections.get(0).text(1);
2674 SavedSearch s = conn.getSavedSearchTable().getSavedSearch(selectedSavedSearchGUID);
2675 searchField.setEditText(s.getQuery());
2677 menuBar.savedSearchEditAction.setEnabled(false);
2678 menuBar.savedSearchDeleteAction.setEnabled(false);
2679 menuBar.savedSearchIconAction.setEnabled(false);
2680 selectedSavedSearchGUID = "";
2681 searchField.setEditText("");
2683 searchFieldChanged();
2685 logger.log(logger.HIGH, "Leaving NeverNote.updateSavedSearchSelection()");
2689 // Show/Hide note information
2690 @SuppressWarnings("unused")
2691 private void toggleSavedSearchWindow() {
2692 logger.log(logger.HIGH, "Entering NeverNote.toggleSavedSearchWindow");
2693 if (savedSearchTree.isVisible())
2694 savedSearchTree.hide();
2696 savedSearchTree.show();
2697 menuBar.hideSavedSearches.setChecked(savedSearchTree.isVisible());
2699 Global.saveWindowVisible("savedSearchTree", savedSearchTree.isVisible());
2700 logger.log(logger.HIGH, "Leaving NeverNote.toggleSavedSearchWindow");
2702 // Change the icon for a saved search
2703 @SuppressWarnings("unused")
2704 private void setSavedSearchIcon() {
2705 QTreeWidgetItem currentSelection;
2706 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2707 if (selections.size() == 0)
2710 currentSelection = selections.get(0);
2711 String guid = currentSelection.text(1);
2713 QIcon currentIcon = currentSelection.icon(0);
2714 QIcon icon = conn.getSavedSearchTable().getIcon(guid);
2717 dialog = new SetIcon(currentIcon, saveLastPath);
2718 dialog.setUseDefaultIcon(true);
2720 dialog = new SetIcon(icon, saveLastPath);
2721 dialog.setUseDefaultIcon(false);
2724 if (dialog.okPressed()) {
2725 saveLastPath = dialog.getPath();
2726 QIcon newIcon = dialog.getIcon();
2727 conn.getSavedSearchTable().setIcon(guid, newIcon, dialog.getFileType());
2728 if (newIcon == null)
2729 newIcon = new QIcon(iconPath+"search.png");
2730 currentSelection.setIcon(0, newIcon);
2738 //***************************************************************
2739 //***************************************************************
2740 //** These functions deal with Help menu & tool menu items
2741 //***************************************************************
2742 //***************************************************************
2743 // Show database status
2744 @SuppressWarnings("unused")
2745 private void databaseStatus() {
2747 indexRunner.interrupt = true;
2748 int dirty = conn.getNoteTable().getDirtyCount();
2749 int unindexed = conn.getNoteTable().getUnindexedCount();
2750 DatabaseStatus status = new DatabaseStatus();
2751 status.setUnsynchronized(dirty);
2752 status.setUnindexed(unindexed);
2753 status.setNoteCount(conn.getNoteTable().getNoteCount());
2754 status.setNotebookCount(listManager.getNotebookIndex().size());
2755 status.setUnindexedResourceCount(conn.getNoteTable().noteResourceTable.getUnindexedCount());
2756 status.setSavedSearchCount(listManager.getSavedSearchIndex().size());
2757 status.setTagCount(listManager.getTagIndex().size());
2758 status.setResourceCount(conn.getNoteTable().noteResourceTable.getResourceCount());
2759 status.setWordCount(conn.getWordsTable().getWordCount());
2763 // Compact the database
2764 @SuppressWarnings("unused")
2765 private void compactDatabase() {
2766 logger.log(logger.HIGH, "Entering NeverNote.compactDatabase");
2767 if (QMessageBox.question(this, tr("Confirmation"), tr("This will free unused space in the database, "+
2768 "but please be aware that depending upon the size of your database this can be time consuming " +
2769 "and NixNote will be unresponsive until it is complete. Do you wish to continue?"),
2770 QMessageBox.StandardButton.Yes,
2771 QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) {
2774 setMessage("Compacting database.");
2776 listManager.compactDatabase();
2778 setMessage("Database compact is complete.");
2779 logger.log(logger.HIGH, "Leaving NeverNote.compactDatabase");
2781 @SuppressWarnings("unused")
2782 private void accountInformation() {
2783 logger.log(logger.HIGH, "Entering NeverNote.accountInformation");
2784 AccountDialog dialog = new AccountDialog();
2786 logger.log(logger.HIGH, "Leaving NeverNote.accountInformation");
2788 @SuppressWarnings("unused")
2789 private void releaseNotes() {
2790 logger.log(logger.HIGH, "Entering NeverNote.releaseNotes");
2791 QDialog dialog = new QDialog(this);
2792 QHBoxLayout layout = new QHBoxLayout();
2793 QTextEdit textBox = new QTextEdit();
2794 layout.addWidget(textBox);
2795 textBox.setReadOnly(true);
2796 QFile file = new QFile(Global.getFileManager().getProgramDirPath("release.txt"));
2797 if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly,
2798 QIODevice.OpenModeFlag.Text)))
2800 textBox.setText(file.readAll().toString());
2802 dialog.setWindowTitle(tr("Release Notes"));
2803 dialog.setLayout(layout);
2805 logger.log(logger.HIGH, "Leaving NeverNote.releaseNotes");
2807 // Called when user picks Log from the help menu
2808 @SuppressWarnings("unused")
2809 private void logger() {
2810 logger.log(logger.HIGH, "Entering NeverNote.logger");
2811 LogFileDialog dialog = new LogFileDialog(emitLog);
2813 logger.log(logger.HIGH, "Leaving NeverNote.logger");
2815 // Menu option "help/about" was selected
2816 @SuppressWarnings("unused")
2817 private void about() {
2818 logger.log(logger.HIGH, "Entering NeverNote.about");
2819 QMessageBox.about(this,
2820 tr("About NixNote"),
2821 tr("<h4><center><b>NixNote</b></center></h4><hr><center>Version ")
2825 +"Open Source Evernote Client.<br><br>"
2826 +"Licensed under GPL v2. <br><hr><br>"
2827 +"</center>Evernote is copyright 2001-2012 by Evernote Corporation<br>"
2828 +"Jambi and QT are the licensed trademark of Nokia Corporation<br>"
2829 +"PDFRenderer is licened under the LGPL<br>"
2830 +"JTidy is copyrighted under the World Wide Web Consortium<br>"
2831 +"Apache Common Utilities licensed under the Apache License Version 2.0<br>"
2832 +"Jazzy is licened under the LGPL<br>"
2833 +"Java is a registered trademark of Oracle Corporation.<br><hr>"
2834 +"Special thanks to:<br>BitRock InstallBuilder for the Windows installer"
2835 +"<br>CodeCogs (www.codecogs.com) for the LaTeX image rendering."));
2836 logger.log(logger.HIGH, "Leaving NeverNote.about");
2838 // Hide the entire left hand side
2839 @SuppressWarnings("unused")
2840 private void toggleLeftSide() {
2843 hidden = !menuBar.hideLeftSide.isChecked();
2844 menuBar.hideLeftSide.setChecked(!hidden);
2847 leftSplitter1.setHidden(true);
2849 leftSplitter1.setHidden(false);
2851 Global.saveWindowVisible("leftPanel", hidden);
2854 public void checkForUpdates() {
2855 // Send off thread to check for a new version
2856 versionChecker = new QNetworkAccessManager(this);
2857 versionChecker.finished.connect(this, "upgradeFileRead(QNetworkReply)");
2858 QNetworkRequest request = new QNetworkRequest();
2859 request.setUrl(new QUrl(Global.getUpdatesAvailableUrl()));
2860 versionChecker.get(request);
2862 @SuppressWarnings("unused")
2863 private void upgradeFileRead(QNetworkReply reply) {
2864 if (!reply.isReadable())
2867 String winVersion = Global.version;
2868 String osxVersion = Global.version;
2869 String linuxVersion = Global.version;
2870 String linux64Version = Global.version;
2871 String version = Global.version;
2873 // Determine the versions available
2874 QByteArray data = reply.readLine();
2875 while (data != null && !reply.atEnd()) {
2876 String line = data.toString();
2878 if (line.contains(":"))
2879 lineVersion = line.substring(line.indexOf(":")+1).replace(" ", "").replace("\n", "");
2882 if (line.toLowerCase().contains("windows"))
2883 winVersion = lineVersion;
2884 else if (line.toLowerCase().contains("os-x"))
2885 osxVersion = lineVersion;
2886 else if (line.toLowerCase().contains("linux amd64"))
2887 linux64Version = lineVersion;
2888 else if (line.toLowerCase().contains("linux i386"))
2889 linuxVersion = lineVersion;
2890 else if (line.toLowerCase().contains("default"))
2891 version = lineVersion;
2893 // Read the next line
2894 data = reply.readLine();
2897 // Now we need to determine what system we are on.
2898 if (System.getProperty("os.name").toLowerCase().contains("windows"))
2899 version = winVersion;
2900 if (System.getProperty("os.name").toLowerCase().contains("mac os"))
2901 version = osxVersion;
2902 if (System.getProperty("os.name").toLowerCase().contains("Linux")) {
2903 if (System.getProperty("os.arch").contains("amd64") ||
2904 System.getProperty("os.arch").contains("x86_64"))
2905 version = linux64Version;
2907 version = linuxVersion;
2911 for (String validVersion : Global.validVersions) {
2912 if (version.equals(validVersion))
2916 UpgradeAvailableDialog dialog = new UpgradeAvailableDialog();
2918 if (dialog.remindMe())
2919 Global.setCheckVersionUpgrade(true);
2921 Global.setCheckVersionUpgrade(false);
2925 //***************************************************************
2926 //***************************************************************
2927 //** These functions deal with the Toolbar
2928 //***************************************************************
2929 //***************************************************************
2930 @SuppressWarnings("unused")
2931 private void focusSearch() {
2932 searchField.setFocus();
2935 // Text in the search bar has been cleared
2936 private void searchFieldCleared() {
2939 // This is done because we want to force a reload of
2940 // images. Some images we may want to highlight the text.
2941 readOnlyCache.clear();
2942 inkNoteCache.clear();
2944 QWebSettings.setMaximumPagesInCache(0);
2945 QWebSettings.setObjectCacheCapacities(0, 0, 0);
2947 searchField.setEditText("");
2948 saveNoteColumnPositions();
2949 saveNoteIndexWidth();
2950 noteIndexUpdated(true);
2951 if (currentNote == null && listManager.getNoteIndex().size() > 0) {
2952 currentNote = listManager.getNoteIndex().get(0);
2953 currentNoteGuid = currentNote.getGuid();
2955 refreshEvernoteNote(true);
2956 if (currentNote != null)
2957 loadNoteBrowserInformation(browserWindow, currentNoteGuid, currentNote);
2959 // text in the search bar changed. We only use this to tell if it was cleared,
2960 // otherwise we trigger off searchFieldChanged.
2961 @SuppressWarnings("unused")
2962 private void searchFieldTextChanged(String text) {
2963 QWebSettings.setMaximumPagesInCache(0);
2964 QWebSettings.setObjectCacheCapacities(0, 0, 0);
2966 if (text.trim().equals("")) {
2967 searchFieldCleared();
2968 if (searchPerformed) {
2970 // This is done because we want to force a reload of
2971 // images. Some images we may want to highlight the text.
2973 readOnlyCache.clear();
2974 inkNoteCache.clear();
2976 listManager.setEnSearch("");
2977 listManager.loadNotesIndex();
2978 refreshEvernoteNote(true);
2979 noteIndexUpdated(false);
2980 refreshEvernoteNote(true);
2982 searchPerformed = false;
2985 // Text in the toolbar has changed
2986 private void searchFieldChanged() {
2987 logger.log(logger.HIGH, "Entering NeverNote.searchFieldChanged");
2989 readOnlyCache.clear();
2990 inkNoteCache.clear();
2991 saveNoteColumnPositions();
2992 saveNoteIndexWidth();
2993 String text = searchField.currentText();
2994 listManager.setEnSearch(text.trim());
2995 listManager.loadNotesIndex();
2996 noteIndexUpdated(false);
2998 refreshEvernoteNote(true);
2999 searchPerformed = true;
3001 logger.log(logger.HIGH, "Leaving NeverNote.searchFieldChanged");
3004 // Build the window tool bar
3005 private void setupToolBar() {
3006 logger.log(logger.HIGH, "Entering NeverNote.setupToolBar");
3007 toolBar = addToolBar(tr("Tool Bar"));
3008 toolBar.setObjectName("toolBar");
3009 menuBar.setupToolBarVisible();
3010 if (!Global.isWindowVisible("toolBar"))
3011 toolBar.setVisible(false);
3013 toolBar.setVisible(true);
3015 // toolBar.addWidget(menuBar);
3016 // menuBar.setSizePolicy(Policy.Minimum, Policy.Minimum);
3017 // toolBar.addSeparator();
3018 prevButton = toolBar.addAction(tr("Previous"));
3019 QIcon prevIcon = new QIcon(iconPath+"back.png");
3020 prevButton.setIcon(prevIcon);
3021 prevButton.triggered.connect(this, "previousViewedAction()");
3022 togglePrevArrowButton(Global.isToolbarButtonVisible("prevArrow"));
3024 nextButton = toolBar.addAction(tr("Next"));
3025 QIcon nextIcon = new QIcon(iconPath+"forward.png");
3026 nextButton.setIcon(nextIcon);
3027 nextButton.triggered.connect(this, "nextViewedAction()");
3028 toggleNextArrowButton(Global.isToolbarButtonVisible("nextArrow"));
3030 upButton = toolBar.addAction(tr("Up"));
3031 QIcon upIcon = new QIcon(iconPath+"up.png");
3032 upButton.setIcon(upIcon);
3033 upButton.triggered.connect(this, "upAction()");
3034 toggleUpArrowButton(Global.isToolbarButtonVisible("upArrow"));
3037 downButton = toolBar.addAction(tr("Down"));
3038 QIcon downIcon = new QIcon(iconPath+"down.png");
3039 downButton.setIcon(downIcon);
3040 downButton.triggered.connect(this, "downAction()");
3041 toggleDownArrowButton(Global.isToolbarButtonVisible("downArrow"));
3043 synchronizeButton = toolBar.addAction(tr("Synchronize"));
3044 synchronizeButton.setIcon(new QIcon(iconPath+"synchronize.png"));
3045 synchronizeIconAngle = 0;
3046 synchronizeButton.triggered.connect(this, "evernoteSync()");
3047 toggleSynchronizeButton(Global.isToolbarButtonVisible("synchronize"));
3049 printButton = toolBar.addAction(tr("Print"));
3050 QIcon printIcon = new QIcon(iconPath+"print.png");
3051 printButton.setIcon(printIcon);
3052 printButton.triggered.connect(this, "printNote()");
3053 togglePrintButton(Global.isToolbarButtonVisible("print"));
3055 tagButton = toolBar.addAction(tr("Tag"));
3056 QIcon tagIcon = new QIcon(iconPath+"tag.png");
3057 tagButton.setIcon(tagIcon);
3058 tagButton.triggered.connect(browserWindow, "modifyTags()");
3059 toggleTagButton(Global.isToolbarButtonVisible("tag"));
3061 attributeButton = toolBar.addAction(tr("Attributes"));
3062 QIcon attributeIcon = new QIcon(iconPath+"attribute.png");
3063 attributeButton.setIcon(attributeIcon);
3064 attributeButton.triggered.connect(this, "toggleNoteInformation()");
3065 toggleAttributeButton(Global.isToolbarButtonVisible("attribute"));
3067 emailButton = toolBar.addAction(tr("Email"));
3068 QIcon emailIcon = new QIcon(iconPath+"email.png");
3069 emailButton.setIcon(emailIcon);
3070 emailButton.triggered.connect(this, "emailNote()");
3071 toggleEmailButton(Global.isToolbarButtonVisible("email"));
3073 deleteButton = toolBar.addAction(tr("Delete"));
3074 QIcon deleteIcon = new QIcon(iconPath+"delete.png");
3075 deleteButton.setIcon(deleteIcon);
3076 deleteButton.triggered.connect(this, "deleteNote()");
3077 toggleDeleteButton(Global.isToolbarButtonVisible("delete"));
3079 newButton = toolBar.addAction(tr("New"));
3080 QIcon newIcon = new QIcon(iconPath+"new.png");
3081 newButton.triggered.connect(this, "addNote()");
3082 newButton.setIcon(newIcon);
3083 toggleNewButton(Global.isToolbarButtonVisible("new"));
3085 allNotesButton = toolBar.addAction(tr("All Notes"));
3086 QIcon allIcon = new QIcon(iconPath+"books.png");
3087 allNotesButton.triggered.connect(this, "allNotes()");
3088 allNotesButton.setIcon(allIcon);
3089 toggleAllNotesButton(Global.isToolbarButtonVisible("allNotes"));
3091 //toolBar.addSeparator();
3092 //toolBar.addWidget(new QLabel(tr("Quota:")));
3093 //toolBar.addWidget(quotaBar);
3094 //quotaBar.setSizePolicy(Policy.Minimum, Policy.Minimum);
3096 //toolBar.addSeparator();
3098 //toolBar.addWidget(new QLabel(tr("Zoom")));
3099 //toolBar.addWidget(zoomSpinner);
3101 //toolBar.addWidget(new QLabel(" "));
3102 //toolBar.addSeparator();
3103 //toolBar.addWidget(new QLabel(tr(" Search:")));
3104 //toolBar.addWidget(searchField);
3105 QSizePolicy sizePolicy = new QSizePolicy();
3106 sizePolicy.setHorizontalPolicy(Policy.MinimumExpanding);
3107 QLabel spacer = new QLabel("");
3108 spacer.setSizePolicy(sizePolicy);
3109 toolBar.addWidget(spacer);
3110 //searchField.setInsertPolicy(InsertPolicy.InsertAtTop);
3112 //searchClearButton = toolBar.addAction("Search Clear");
3113 //QIcon searchClearIcon = new QIcon(iconPath+"searchclear.png");
3114 //searchClearButton.setIcon(searchClearIcon);
3115 //searchClearButton.triggered.connect(this, "searchFieldCleared()");
3116 //toggleSearchClearButton(Global.isToolbarButtonVisible("searchClear"));
3118 logger.log(logger.HIGH, "Leaving NeverNote.setupToolBar");
3120 // Update the sychronize button picture
3122 public QMenu createPopupMenu() {
3123 QMenu contextMenu = super.createPopupMenu();
3125 contextMenu.addSeparator();
3126 QAction prevAction = addContextAction("prevArrow", tr("Previous Arrow"));
3127 contextMenu.addAction(prevAction);
3128 prevAction.triggered.connect(this, "togglePrevArrowButton(Boolean)");
3130 QAction nextAction = addContextAction("nextArrow", tr("Next Arrow"));
3131 contextMenu.addAction(nextAction);
3132 nextAction.triggered.connect(this, "toggleNextArrowButton(Boolean)");
3134 QAction upAction = addContextAction("upArrow", tr("Up Arrow"));
3135 contextMenu.addAction(upAction);
3136 upAction.triggered.connect(this, "toggleUpArrowButton(Boolean)");
3138 QAction downAction = addContextAction("downArrow", tr("Down Arrow"));
3139 contextMenu.addAction(downAction);
3140 downAction.triggered.connect(this, "toggleDownArrowButton(Boolean)");
3142 QAction synchronizeAction = addContextAction("synchronize", tr("Synchronize"));
3143 contextMenu.addAction(synchronizeAction);
3144 synchronizeAction.triggered.connect(this, "toggleSynchronizeButton(Boolean)");
3146 QAction printAction = addContextAction("print", tr("Print"));
3147 contextMenu.addAction(printAction);
3148 printAction.triggered.connect(this, "togglePrintButton(Boolean)");
3150 QAction tagAction = addContextAction("tag", tr("Tag"));
3151 contextMenu.addAction(tagAction);
3152 tagAction.triggered.connect(this, "toggleTagButton(Boolean)");
3154 QAction attributeAction = addContextAction("attribute", tr("Attribute"));
3155 contextMenu.addAction(attributeAction);
3156 attributeAction.triggered.connect(this, "toggleAttributeButton(Boolean)");
3158 QAction emailAction = addContextAction("email", tr("Email"));
3159 contextMenu.addAction(emailAction);
3160 emailAction.triggered.connect(this, "toggleEmailButton(Boolean)");
3162 QAction deleteAction = addContextAction("delete", tr("Delete"));
3163 contextMenu.addAction(deleteAction);
3164 deleteAction.triggered.connect(this, "toggleDeleteButton(Boolean)");
3166 QAction newAction = addContextAction("new", tr("Add"));
3167 contextMenu.addAction(newAction);
3168 newAction.triggered.connect(this, "toggleNewButton(Boolean)");
3170 QAction allNotesAction = addContextAction("allNotes", tr("All Notes"));
3171 contextMenu.addAction(allNotesAction);
3172 allNotesAction.triggered.connect(this, "toggleAllNotesButton(Boolean)");
3174 QAction searchClearAction = addContextAction("searchClear", tr("Search Clear"));
3175 contextMenu.addAction(searchClearAction);
3176 searchClearAction.triggered.connect(this, "toggleSearchClearButton(Boolean)");
3181 private QAction addContextAction(String config, String name) {
3182 QAction newAction = new QAction(this);
3183 newAction.setText(name);
3184 newAction.setCheckable(true);
3185 newAction.setChecked(Global.isToolbarButtonVisible(config));
3188 private void togglePrevArrowButton(Boolean toggle) {
3189 prevButton.setVisible(toggle);
3190 Global.saveToolbarButtonsVisible("prevArrow", toggle);
3192 private void toggleNextArrowButton(Boolean toggle) {
3193 nextButton.setVisible(toggle);
3194 Global.saveToolbarButtonsVisible("nextArrow", toggle);
3196 private void toggleUpArrowButton(Boolean toggle) {
3197 upButton.setVisible(toggle);
3198 Global.saveToolbarButtonsVisible("upArrow", toggle);
3200 private void toggleDownArrowButton(Boolean toggle) {
3201 downButton.setVisible(toggle);
3202 Global.saveToolbarButtonsVisible("downArrow", toggle);
3204 private void toggleSynchronizeButton(Boolean toggle) {
3205 synchronizeButton.setVisible(toggle);
3206 Global.saveToolbarButtonsVisible("synchronize", toggle);
3208 private void togglePrintButton(Boolean toggle) {
3209 printButton.setVisible(toggle);
3210 Global.saveToolbarButtonsVisible("print", toggle);
3212 private void toggleTagButton(Boolean toggle) {
3213 tagButton.setVisible(toggle);
3214 Global.saveToolbarButtonsVisible("tag", toggle);
3216 private void toggleAttributeButton(Boolean toggle) {
3217 attributeButton.setVisible(toggle);
3218 Global.saveToolbarButtonsVisible("attribute", toggle);
3220 private void toggleEmailButton(Boolean toggle) {
3221 emailButton.setVisible(toggle);
3222 Global.saveToolbarButtonsVisible("email", toggle);
3224 private void toggleDeleteButton(Boolean toggle) {
3225 deleteButton.setVisible(toggle);
3226 Global.saveToolbarButtonsVisible("delete", toggle);
3228 private void toggleNewButton(Boolean toggle) {
3229 newButton.setVisible(toggle);
3230 Global.saveToolbarButtonsVisible("new", toggle);
3232 private void toggleAllNotesButton(Boolean toggle) {
3233 allNotesButton.setVisible(toggle);
3234 Global.saveToolbarButtonsVisible("allNotes", toggle);
3236 @SuppressWarnings("unused")
3237 private void toggleSearchClearButton(Boolean toggle) {
3238 searchClearButton.setVisible(toggle);
3239 Global.saveToolbarButtonsVisible("searchClear", toggle);
3246 @SuppressWarnings("unused")
3247 private void updateSyncButton() {
3249 if (syncIcons == null) {
3250 syncIcons = new ArrayList<QPixmap>();
3252 synchronizeIconAngle = 0;
3253 QPixmap pix = new QPixmap(iconPath+"synchronize.png");
3255 for (int i=0; i<=360; i++) {
3256 QPixmap rotatedPix = new QPixmap(pix.size());
3257 QPainter p = new QPainter(rotatedPix);
3258 rotatedPix.fill(toolBar.palette().color(ColorRole.Button));
3259 QSize size = pix.size();
3260 p.translate(size.width()/2, size.height()/2);
3263 p.setBackgroundMode(BGMode.OpaqueMode);
3264 p.translate(-size.width()/2, -size.height()/2);
3265 p.drawPixmap(0,0, pix);
3267 syncIcons.add(rotatedPix);
3271 synchronizeIconAngle++;
3272 if (synchronizeIconAngle > 359)
3273 synchronizeIconAngle=0;
3274 synchronizeButton.setIcon(syncIcons.get(synchronizeIconAngle));
3277 // Synchronize with Evernote
3279 private void evernoteSync() {
3280 logger.log(logger.HIGH, "Entering NeverNote.evernoteSync");
3281 if (!Global.isConnected)
3283 if (Global.isConnected)
3284 synchronizeAnimationTimer.start(5);
3285 // synchronizeAnimationTimer.start(200);
3287 logger.log(logger.HIGH, "Leaving NeverNote.evernoteSync");
3289 private void updateQuotaBar() {
3290 long limit = Global.getUploadLimit();
3291 long amount = Global.getUploadAmount();
3292 if (amount>0 && limit>0) {
3293 int percent =(int)(amount*100/limit);
3294 quotaBar.setValue(percent);
3296 quotaBar.setValue(0);
3299 @SuppressWarnings("unused")
3300 private void zoomChanged() {
3301 browserWindow.getBrowser().setZoomFactor(new Double(zoomSpinner.value())/100);
3304 //****************************************************************
3305 //****************************************************************
3306 //* System Tray functions
3307 //****************************************************************
3308 //****************************************************************
3309 private void trayToggleVisible() {
3314 if (windowMaximized)
3321 @SuppressWarnings("unused")
3322 private void trayActivated(QSystemTrayIcon.ActivationReason reason) {
3323 if (reason == QSystemTrayIcon.ActivationReason.DoubleClick) {
3324 String name = QSystemTrayIcon.MessageIcon.resolve(reason.value()).name();
3325 trayToggleVisible();
3330 //***************************************************************
3331 //***************************************************************
3332 //** These functions deal with the trash tree
3333 //***************************************************************
3334 //***************************************************************
3335 // Setup the tree containing the trash.
3336 @SuppressWarnings("unused")
3337 private void trashTreeSelection() {
3338 logger.log(logger.HIGH, "Entering NeverNote.trashTreeSelection");
3340 clearNotebookFilter();
3342 clearAttributeFilter();
3343 clearSavedSearchFilter();
3345 String tempGuid = currentNoteGuid;
3347 // currentNoteGuid = "";
3348 currentNote = new Note();
3349 selectedNoteGUIDs.clear();
3350 listManager.getSelectedNotebooks().clear();
3351 listManager.getSelectedTags().clear();
3352 listManager.setSelectedSavedSearch("");
3353 browserWindow.clear();
3355 // toggle the add buttons
3356 newButton.setEnabled(!newButton.isEnabled());
3357 menuBar.noteAdd.setEnabled(newButton.isEnabled());
3358 menuBar.noteAdd.setVisible(true);
3360 List<QTreeWidgetItem> selections = trashTree.selectedItems();
3361 if (selections.size() == 0) {
3362 currentNoteGuid = trashNoteGuid;
3363 trashNoteGuid = tempGuid;
3364 Global.showDeleted = false;
3365 menuBar.noteRestoreAction.setEnabled(false);
3366 menuBar.noteRestoreAction.setVisible(false);
3369 trashNoteGuid = tempGuid;
3370 currentNoteGuid = trashNoteGuid;
3371 menuBar.noteRestoreAction.setEnabled(true);
3372 menuBar.noteRestoreAction.setVisible(true);
3373 Global.showDeleted = true;
3375 listManager.loadNotesIndex();
3376 noteIndexUpdated(false);
3377 //// browserWindow.setEnabled(newButton.isEnabled());
3378 browserWindow.setReadOnly(!newButton.isEnabled());
3379 logger.log(logger.HIGH, "Leaving NeverNote.trashTreeSelection");
3381 // Empty the trash file
3382 @SuppressWarnings("unused")
3383 private void emptyTrash() {
3384 // browserWindow.clear();
3385 logger.log(logger.EXTREME, "Emptying Trash");
3386 listManager.emptyTrash();
3387 logger.log(logger.EXTREME, "Resetting view after trash empty");
3388 if (trashTree.selectedItems().size() > 0) {
3389 listManager.getSelectedNotebooks().clear();
3390 listManager.getSelectedTags().clear();
3391 listManager.setSelectedSavedSearch("");
3392 newButton.setEnabled(!newButton.isEnabled());
3393 menuBar.noteAdd.setEnabled(newButton.isEnabled());
3394 menuBar.noteAdd.setVisible(true);
3395 browserWindow.clear();
3398 clearNotebookFilter();
3399 clearSavedSearchFilter();
3400 clearAttributeFilter();
3402 Global.showDeleted = false;
3403 menuBar.noteRestoreAction.setEnabled(false);
3404 menuBar.noteRestoreAction.setVisible(false);
3406 listManager.loadNotesIndex();
3407 noteIndexUpdated(false);
3410 // Show/Hide trash window
3411 @SuppressWarnings("unused")
3412 private void toggleTrashWindow() {
3413 logger.log(logger.HIGH, "Entering NeverNote.toggleTrashWindow");
3414 if (trashTree.isVisible())
3418 menuBar.hideTrash.setChecked(trashTree.isVisible());
3420 Global.saveWindowVisible("trashTree", trashTree.isVisible());
3421 logger.log(logger.HIGH, "Leaving NeverNote.trashWindow");
3423 private void clearTrashFilter() {
3424 Global.showDeleted = false;
3425 newButton.setEnabled(true);
3426 menuBar.noteAdd.setEnabled(true);
3427 menuBar.noteAdd.setVisible(true);
3428 trashTree.blockSignals(true);
3429 trashTree.clearSelection();
3430 trashTree.blockSignals(false);
3435 //***************************************************************
3436 //***************************************************************
3437 //** These functions deal with connection settings
3438 //***************************************************************
3439 //***************************************************************
3440 // SyncRunner had a problem and things are disconnected
3441 @SuppressWarnings("unused")
3442 private void remoteErrorDisconnect() {
3443 menuBar.connectAction.setText(tr("Connect"));
3444 menuBar.connectAction.setToolTip(tr("Connect to Evernote"));
3445 menuBar.synchronizeAction.setEnabled(false);
3446 Global.isConnected = false;
3447 synchronizeAnimationTimer.stop();
3450 // Do a manual connect/disconnect
3451 private void remoteConnect() {
3453 logger.log(logger.HIGH, "Entering NeverNote.remoteConnect");
3455 // If we are already connected, we just disconnect
3456 if (Global.isConnected) {
3457 Global.isConnected = false;
3458 syncRunner.enDisconnect();
3459 setupConnectMenuOptions();
3464 OAuthTokenizer tokenizer = new OAuthTokenizer();
3465 AESEncrypter aes = new AESEncrypter();
3467 aes.decrypt(new FileInputStream(Global.getFileManager().getHomeDirFile("oauth.txt")));
3468 } catch (FileNotFoundException e) {
3469 // File not found, so we'll just get empty strings anyway.
3473 if (Global.getProxyValue("url").equals("")) {
3474 System.setProperty("http.proxyHost","") ;
3475 System.setProperty("http.proxyPort", "") ;
3476 System.setProperty("https.proxyHost","") ;
3477 System.setProperty("https.proxyPort", "") ;
3480 System.setProperty("http.proxyHost",Global.getProxyValue("url")) ;
3481 System.setProperty("http.proxyPort", Global.getProxyValue("port")) ;
3482 System.setProperty("https.proxyHost",Global.getProxyValue("url")) ;
3483 System.setProperty("https.proxyPort", Global.getProxyValue("port")) ;
3485 if (Global.getProxyValue("userid").equals("")) {
3486 Authenticator.setDefault(new Authenticator() {
3488 protected PasswordAuthentication getPasswordAuthentication() {
3490 PasswordAuthentication(Global.getProxyValue("userid"),Global.getProxyValue("password").toCharArray());
3496 syncRunner.userStoreUrl = Global.userStoreUrl;
3497 syncRunner.noteStoreUrl = Global.noteStoreUrl;
3498 syncRunner.noteStoreUrlBase = Global.noteStoreUrlBase;
3502 String authString = aes.getString();
3503 if (!authString.equals("")) {
3504 tokenizer.tokenize(authString);
3505 syncRunner.authToken = tokenizer.oauth_token;
3506 syncRunner.enConnect();
3509 Global.isConnected = syncRunner.isConnected;
3511 if (!Global.isConnected) {
3512 OAuthWindow window = new OAuthWindow(logger);
3514 setMessage(window.errorMessage);
3519 setMessage(window.errorMessage);
3522 tokenizer.tokenize(window.response);
3523 if (tokenizer.oauth_token.equals("")) {
3524 setMessage(tr("Invalid authorization token received."));
3527 aes.setString(window.response);
3529 aes.encrypt(new FileOutputStream(Global.getFileManager().getHomeDirFile("oauth.txt")));
3530 } catch (FileNotFoundException e) {
3531 // TODO Auto-generated catch block
3532 e.printStackTrace();
3534 syncRunner.authToken = tokenizer.oauth_token;
3535 syncRunner.enConnect();
3536 Global.isConnected = syncRunner.isConnected;
3538 // Global.username = syncRunner.username;
3540 if (!Global.isConnected)
3543 setupConnectMenuOptions();
3544 logger.log(logger.HIGH, "Leaving NeverNote.remoteConnect");
3548 private void setupConnectMenuOptions() {
3549 logger.log(logger.HIGH, "entering NeverNote.setupConnectMenuOptions");
3550 if (!Global.isConnected) {
3551 menuBar.connectAction.setText(tr("Connect"));
3552 menuBar.connectAction.setToolTip(tr("Connect to Evernote"));
3553 menuBar.synchronizeAction.setEnabled(false);
3555 menuBar.connectAction.setText(tr("Disconnect"));
3556 menuBar.connectAction.setToolTip(tr("Disconnect from Evernote"));
3557 menuBar.synchronizeAction.setEnabled(true);
3559 logger.log(logger.HIGH, "Leaving NeverNote.setupConnectionMenuOptions");
3564 //***************************************************************
3565 //***************************************************************
3566 //** These functions deal with the GUI Attribute tree
3567 //***************************************************************
3568 //***************************************************************
3569 @SuppressWarnings("unused")
3570 private void attributeTreeClicked(QTreeWidgetItem item, Integer integer) {
3572 // clearTagFilter();
3573 // clearNotebookFilter();
3575 // clearSavedSearchFilter();
3577 if (attributeTreeSelected == null || item.nativeId() != attributeTreeSelected.nativeId()) {
3578 if (item.childCount() > 0) {
3579 item.setSelected(false);
3581 Global.createdBeforeFilter.reset();
3582 Global.createdSinceFilter.reset();
3583 Global.changedBeforeFilter.reset();
3584 Global.changedSinceFilter.reset();
3585 Global.containsFilter.reset();
3586 attributeTreeSelected = item;
3587 DateAttributeFilterTable f = null;
3588 f = findDateAttributeFilterTable(item.parent());
3590 f.select(item.parent().indexOfChild(item));
3592 Global.containsFilter.select(item.parent().indexOfChild(item));
3595 listManager.loadNotesIndex();
3596 noteIndexUpdated(false);
3599 attributeTreeSelected = null;
3600 item.setSelected(false);
3601 Global.createdBeforeFilter.reset();
3602 Global.createdSinceFilter.reset();
3603 Global.changedBeforeFilter.reset();
3604 Global.changedSinceFilter.reset();
3605 Global.containsFilter.reset();
3606 listManager.loadNotesIndex();
3607 noteIndexUpdated(false);
3609 // This determines what attribute filter we need, depending upon the selection
3610 private DateAttributeFilterTable findDateAttributeFilterTable(QTreeWidgetItem w) {
3611 if (w.parent() != null && w.childCount() > 0) {
3612 QTreeWidgetItem parent = w.parent();
3613 if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Created &&
3614 w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Since)
3615 return Global.createdSinceFilter;
3616 if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Created &&
3617 w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Before)
3618 return Global.createdBeforeFilter;
3619 if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.LastModified &&
3620 w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Since)
3621 return Global.changedSinceFilter;
3622 if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.LastModified &&
3623 w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Before)
3624 return Global.changedBeforeFilter;
3629 // Show/Hide attribute search window
3630 @SuppressWarnings("unused")
3631 private void toggleAttributesWindow() {
3632 logger.log(logger.HIGH, "Entering NeverNote.toggleAttributesWindow");
3633 if (attributeTree.isVisible())
3634 attributeTree.hide();
3636 attributeTree.show();
3637 menuBar.hideAttributes.setChecked(attributeTree.isVisible());
3639 Global.saveWindowVisible("attributeTree", attributeTree.isVisible());
3640 logger.log(logger.HIGH, "Leaving NeverNote.toggleAttributeWindow");
3642 private void clearAttributeFilter() {
3643 Global.createdBeforeFilter.reset();
3644 Global.createdSinceFilter.reset();
3645 Global.changedBeforeFilter.reset();
3646 Global.changedSinceFilter.reset();
3647 Global.containsFilter.reset();
3648 attributeTreeSelected = null;
3649 attributeTree.blockSignals(true);
3650 attributeTree.clearSelection();
3651 attributeTree.blockSignals(false);
3655 //***************************************************************
3656 //***************************************************************
3657 //** These functions deal with the GUI Note index table
3658 //***************************************************************
3659 //***************************************************************
3660 // Initialize the note list table
3661 private void initializeNoteTable() {
3662 logger.log(logger.HIGH, "Entering NeverNote.initializeNoteTable");
3663 noteTableView.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection);
3664 noteTableView.selectionModel().selectionChanged.connect(this, "noteTableSelection()");
3665 logger.log(logger.HIGH, "Leaving NeverNote.initializeNoteTable");
3667 // Show/Hide trash window
3668 @SuppressWarnings("unused")
3669 private void toggleNoteListWindow() {
3670 logger.log(logger.HIGH, "Entering NeverNote.toggleNoteListWindow");
3671 if (noteTableView.isVisible())
3672 noteTableView.hide();
3674 noteTableView.show();
3675 menuBar.hideNoteList.setChecked(noteTableView.isVisible());
3677 Global.saveWindowVisible("noteList", noteTableView.isVisible());
3678 logger.log(logger.HIGH, "Leaving NeverNote.toggleNoteListWindow");
3680 // Handle the event that a user selects a note from the table
3681 @SuppressWarnings("unused")
3682 private void noteTableSelection() {
3683 logger.log(logger.HIGH, "Entering NeverNote.noteTableSelection");
3687 // If we have more than one selection, then set the merge note action to true.
3688 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
3689 if (selections.size() > 1)
3690 menuBar.noteMergeAction.setEnabled(true);
3692 menuBar.noteMergeAction.setEnabled(false);
3694 // If the ctrl key is pressed, then they are selecting multiple
3695 // entries and we don't want to change the currently viewed note.
3696 if (QApplication.keyboardModifiers().isSet(KeyboardModifier.ControlModifier) &&
3697 QApplication.mouseButtons().isSet(MouseButton.LeftButton))
3700 if (historyGuids.size() == 0) {
3701 historyGuids.add(currentNoteGuid);
3702 historyPosition = 1;
3704 noteTableView.showColumn(Global.noteTableGuidPosition);
3706 if (!Global.isColumnVisible("guid"))
3707 noteTableView.hideColumn(Global.noteTableGuidPosition);
3709 if (selections.size() > 0) {
3711 menuBar.noteDuplicateAction.setEnabled(true);
3712 menuBar.noteOnlineHistoryAction.setEnabled(true);
3713 menuBar.noteMergeAction.setEnabled(true);
3714 selectedNoteGUIDs.clear();
3715 if (selections.size() != 1 || Global.showDeleted) {
3716 menuBar.noteDuplicateAction.setEnabled(false);
3718 if (selections.size() != 1 || !Global.isConnected) {
3719 menuBar.noteOnlineHistoryAction.setEnabled(false);
3721 if (selections.size() == 1) {
3722 menuBar.noteMergeAction.setEnabled(false);
3724 for (int i=0; i<selections.size(); i++) {
3725 int row = selections.get(i).row();
3727 upButton.setEnabled(false);
3729 upButton.setEnabled(true);
3730 if (row < listManager.getNoteTableModel().rowCount()-1)
3731 downButton.setEnabled(true);
3733 downButton.setEnabled(false);
3734 index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
3735 SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
3736 currentNoteGuid = (String)ix.values().toArray()[0];
3737 selectedNoteGUIDs.add(currentNoteGuid);
3741 nextButton.setEnabled(true);
3742 prevButton.setEnabled(true);
3744 int endPosition = historyGuids.size()-1;
3745 for (int j=historyPosition; j<=endPosition; j++) {
3746 historyGuids.remove(historyGuids.size()-1);
3748 historyGuids.add(currentNoteGuid);
3749 historyPosition = historyGuids.size();
3751 if (historyPosition <= 1)
3752 prevButton.setEnabled(false);
3753 if (historyPosition == historyGuids.size())
3754 nextButton.setEnabled(false);
3756 fromHistory = false;
3757 scrollToGuid(currentNoteGuid);
3758 refreshEvernoteNote(true);
3759 logger.log(logger.HIGH, "Leaving NeverNote.noteTableSelection");
3761 // Trigger a refresh when the note db has been updated
3762 private void noteIndexUpdated(boolean reload) {
3763 logger.log(logger.HIGH, "Entering NeverNote.noteIndexUpdated");
3765 refreshEvernoteNoteList();
3766 logger.log(logger.HIGH, "Calling note table reload in NeverNote.noteIndexUpdated() - "+reload);
3767 noteTableView.load(reload);
3768 if (currentNoteGuid == null || currentNoteGuid.equals("")) {
3770 if (noteTableView.proxyModel.sortOrder() == SortOrder.AscendingOrder)
3771 pos = noteTableView.proxyModel.rowCount();
3774 if (noteTableView.proxyModel.rowCount() == 0)
3777 QModelIndex i = noteTableView.proxyModel.index(pos-1, Global.noteTableGuidPosition);
3779 currentNoteGuid = (String)i.data();
3783 if (!noteTableView.isColumnHidden(Global.noteTableGuidPosition))
3785 scrollToGuid(currentNoteGuid);
3786 logger.log(logger.HIGH, "Leaving NeverNote.noteIndexUpdated");
3788 // Called when the list of notes is updated
3789 private void refreshEvernoteNoteList() {
3790 logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNoteList");
3791 browserWindow.setDisabled(false);
3792 if (selectedNoteGUIDs == null)
3793 selectedNoteGUIDs = new ArrayList<String>();
3794 selectedNoteGUIDs.clear(); // clear out old entries
3796 String saveCurrentNoteGuid = new String();
3797 String tempNoteGuid = new String();
3799 historyGuids.clear();
3800 historyPosition = 0;
3801 prevButton.setEnabled(false);
3802 nextButton.setEnabled(false);
3804 if (currentNoteGuid == null)
3805 currentNoteGuid = new String();
3807 //determine current note guid
3808 for (Note note : listManager.getNoteIndex()) {
3809 tempNoteGuid = note.getGuid();
3810 if (currentNoteGuid.equals(tempNoteGuid)) {
3811 saveCurrentNoteGuid = tempNoteGuid;
3815 if (listManager.getNoteIndex().size() == 0) {
3816 currentNoteGuid = "";
3818 browserWindow.clear();
3819 browserWindow.setDisabled(true);
3822 if (Global.showDeleted && listManager.getNotebookIndex().size() > 0 && saveCurrentNoteGuid.equals("")) {
3823 currentNoteGuid = listManager.getNoteIndex().get(0).getGuid();
3824 saveCurrentNoteGuid = currentNoteGuid;
3825 refreshEvernoteNote(true);
3828 if (!saveCurrentNoteGuid.equals("")) {
3829 refreshEvernoteNote(false);
3831 currentNoteGuid = "";
3833 reloadTagTree(false);
3835 logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNoteList");
3837 // Called when the previous arrow button is clicked
3838 @SuppressWarnings("unused")
3839 private void previousViewedAction() {
3840 if (!prevButton.isEnabled())
3842 if (historyPosition == 0)
3845 if (historyPosition <= 0)
3847 String historyGuid = historyGuids.get(historyPosition-1);
3849 for (int i=0; i<noteTableView.model().rowCount(); i++) {
3850 QModelIndex modelIndex = noteTableView.model().index(i, Global.noteTableGuidPosition);
3851 if (modelIndex != null) {
3852 SortedMap<Integer, Object> ix = noteTableView.model().itemData(modelIndex);
3853 String tableGuid = (String)ix.values().toArray()[0];
3854 if (tableGuid.equals(historyGuid)) {
3855 noteTableView.selectRow(i);
3861 @SuppressWarnings("unused")
3862 private void nextViewedAction() {
3863 if (!nextButton.isEnabled())
3865 String historyGuid = historyGuids.get(historyPosition);
3868 for (int i=0; i<noteTableView.model().rowCount(); i++) {
3869 QModelIndex modelIndex = noteTableView.model().index(i, Global.noteTableGuidPosition);
3870 if (modelIndex != null) {
3871 SortedMap<Integer, Object> ix = noteTableView.model().itemData(modelIndex);
3872 String tableGuid = (String)ix.values().toArray()[0];
3873 if (tableGuid.equals(historyGuid)) {
3874 noteTableView.selectRow(i);
3880 // Called when the up arrow is clicked
3881 @SuppressWarnings("unused")
3882 private void upAction() {
3883 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
3884 int row = selections.get(0).row();
3886 noteTableView.selectRow(row-1);
3889 // Called when the down arrow is clicked
3890 @SuppressWarnings("unused")
3891 private void downAction() {
3892 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
3893 int row = selections.get(0).row();
3894 int max = listManager.getNoteTableModel().rowCount();
3896 noteTableView.selectRow(row+1);
3899 // Update a tag string for a specific note in the list
3900 @SuppressWarnings("unused")
3901 private void updateListTags(String guid, List<String> tags) {
3902 logger.log(logger.HIGH, "Entering NeverNote.updateListTags");
3903 StringBuffer tagBuffer = new StringBuffer();
3904 for (int i=0; i<tags.size(); i++) {
3905 tagBuffer.append(tags.get(i));
3906 if (i<tags.size()-1)
3907 tagBuffer.append(", ");
3910 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3911 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3912 if (modelIndex != null) {
3913 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3914 String tableGuid = (String)ix.values().toArray()[0];
3915 if (tableGuid.equals(guid)) {
3916 listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition,tagBuffer.toString());
3917 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
3918 noteTableView.proxyModel.invalidate();
3923 logger.log(logger.HIGH, "Leaving NeverNote.updateListTags");
3925 // Update a title for a specific note in the list
3926 @SuppressWarnings("unused")
3927 private void updateListAuthor(String guid, String author) {
3928 logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
3930 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3931 //QModelIndex modelIndex = noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
3932 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3933 if (modelIndex != null) {
3934 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3935 String tableGuid = (String)ix.values().toArray()[0];
3936 if (tableGuid.equals(guid)) {
3937 listManager.getNoteTableModel().setData(i, Global.noteTableAuthorPosition,author);
3938 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
3939 noteTableView.proxyModel.invalidate();
3945 logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
3947 private void updateListNoteNotebook(String guid, String notebook) {
3948 logger.log(logger.HIGH, "Entering NeverNote.updateListNoteNotebook");
3949 listManager.getNoteTableModel().updateNoteSyncStatus(guid, false);
3950 logger.log(logger.HIGH, "Leaving NeverNote.updateListNoteNotebook");
3952 // Update a title for a specific note in the list
3953 @SuppressWarnings("unused")
3954 private void updateListSourceUrl(String guid, String url) {
3955 logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
3957 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3958 //QModelIndex modelIndex = noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
3959 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3960 if (modelIndex != null) {
3961 // SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex);
3962 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3963 String tableGuid = (String)ix.values().toArray()[0];
3964 if (tableGuid.equals(guid)) {
3965 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
3966 listManager.getNoteTableModel().setData(i, Global.noteTableSourceUrlPosition,url);
3967 noteTableView.proxyModel.invalidate();
3972 logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
3974 @SuppressWarnings("unused")
3975 private void updateListGuid(String oldGuid, String newGuid) {
3976 logger.log(logger.HIGH, "Entering NeverNote.updateListTitle");
3978 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3979 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3980 if (modelIndex != null) {
3981 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3982 String tableGuid = (String)ix.values().toArray()[0];
3983 if (tableGuid.equals(oldGuid)) {
3984 listManager.getNoteTableModel().setData(i, Global.noteTableGuidPosition,newGuid);
3985 //listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
3990 logger.log(logger.HIGH, "Leaving NeverNote.updateListTitle");
3992 private void updateListTagName(String guid) {
3993 logger.log(logger.HIGH, "Entering NeverNote.updateTagName");
3995 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
3996 if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) {
3997 String newName = listManager.getTagNamesForNote(listManager.getNoteIndex().get(j));
3999 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4000 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4001 if (modelIndex != null) {
4002 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4003 String noteGuid = (String)ix.values().toArray()[0];
4004 if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) {
4005 listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition, newName);
4006 i=listManager.getNoteTableModel().rowCount();
4012 logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebook");
4014 private void removeListTagName(String guid) {
4015 logger.log(logger.HIGH, "Entering NeverNote.updateTagName");
4017 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
4018 if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) {
4019 for (int i=listManager.getNoteIndex().get(j).getTagGuids().size()-1; i>=0; i--) {
4020 if (listManager.getNoteIndex().get(j).getTagGuids().get(i).equals(guid))
4021 listManager.getNoteIndex().get(j).getTagGuids().remove(i);
4024 String newName = listManager.getTagNamesForNote(listManager.getNoteIndex().get(j));
4025 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4026 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4027 if (modelIndex != null) {
4028 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4029 String noteGuid = (String)ix.values().toArray()[0];
4030 if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) {
4031 listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition, newName);
4032 i=listManager.getNoteTableModel().rowCount();
4038 logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebook");
4040 private void updateListNotebookName(String oldName, String newName) {
4041 logger.log(logger.HIGH, "Entering NeverNote.updateListNotebookName");
4043 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4044 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableNotebookPosition);
4045 if (modelIndex != null) {
4046 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4047 String tableName = (String)ix.values().toArray()[0];
4048 if (tableName.equalsIgnoreCase(oldName)) {
4049 listManager.getNoteTableModel().setData(i, Global.noteTableNotebookPosition, newName);
4053 logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebookName");
4055 @SuppressWarnings("unused")
4056 private void updateListDateCreated(String guid, QDateTime date) {
4057 logger.log(logger.HIGH, "Entering NeverNote.updateListDateCreated");
4059 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4060 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4061 if (modelIndex != null) {
4062 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4063 String tableGuid = (String)ix.values().toArray()[0];
4064 if (tableGuid.equals(guid)) {
4065 listManager.getNoteTableModel().setData(i, Global.noteTableCreationPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
4066 noteTableView.proxyModel.invalidate();
4071 logger.log(logger.HIGH, "Leaving NeverNote.updateListDateCreated");
4073 @SuppressWarnings("unused")
4074 private void updateListDateSubject(String guid, QDateTime date) {
4075 logger.log(logger.HIGH, "Entering NeverNote.updateListDateSubject");
4077 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4078 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4079 if (modelIndex != null) {
4080 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4081 String tableGuid = (String)ix.values().toArray()[0];
4082 if (tableGuid.equals(guid)) {
4083 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
4084 listManager.getNoteTableModel().setData(i, Global.noteTableSubjectDatePosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
4085 noteTableView.proxyModel.invalidate();
4090 logger.log(logger.HIGH, "Leaving NeverNote.updateListDateCreated");
4092 private void updateListDateChanged(String guid, QDateTime date) {
4093 logger.log(logger.HIGH, "Entering NeverNote.updateListDateChanged");
4095 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4096 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4097 if (modelIndex != null) {
4098 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4099 String tableGuid = (String)ix.values().toArray()[0];
4100 if (tableGuid.equals(guid)) {
4101 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
4102 listManager.getNoteTableModel().setData(i, Global.noteTableChangedPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
4107 logger.log(logger.HIGH, "Leaving NeverNote.updateListDateChanged");
4109 private void updateListDateChanged() {
4110 logger.log(logger.HIGH, "Entering NeverNote.updateListDateChanged");
4111 QDateTime date = new QDateTime(QDateTime.currentDateTime());
4112 updateListDateChanged(currentNoteGuid, date);
4113 logger.log(logger.HIGH, "Leaving NeverNote.updateListDateChanged");
4116 private void scrollToCurrentGuid() {
4117 //scrollToGuid(currentNoteGuid);
4118 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
4119 if (selections.size() == 0)
4121 QModelIndex index = selections.get(0);
4122 int row = selections.get(0).row();
4123 String guid = (String)index.model().index(row, Global.noteTableGuidPosition).data();
4126 // Scroll to the current GUID in tthe list.
4127 // Scroll to a particular index item
4128 private void scrollToGuid(String guid) {
4129 if (currentNote == null || guid == null)
4131 if (currentNote.isActive() && Global.showDeleted) {
4132 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
4133 if (!listManager.getNoteIndex().get(i).isActive()) {
4134 currentNote = listManager.getNoteIndex().get(i);
4135 currentNoteGuid = currentNote.getGuid();
4136 i = listManager.getNoteIndex().size();
4140 if (!currentNote.isActive() && !Global.showDeleted) {
4141 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
4142 if (listManager.getNoteIndex().get(i).isActive()) {
4143 currentNote = listManager.getNoteIndex().get(i);
4144 currentNoteGuid = currentNote.getGuid();
4145 i = listManager.getNoteIndex().size();
4150 for (int i=0; i<noteTableView.model().rowCount(); i++) {
4151 index = noteTableView.model().index(i, Global.noteTableGuidPosition);
4152 if (currentNoteGuid.equals(index.data())) {
4153 // noteTableView.selectionModel().blockSignals(true);
4154 noteTableView.selectRow(i);
4155 // noteTableView.selectionModel().blockSignals(false);
4156 noteTableView.scrollTo(index, ScrollHint.EnsureVisible); // This should work, but it doesn't
4157 i=listManager.getNoteTableModel().rowCount();
4160 noteTableView.repaint();
4162 // Show/Hide columns
4163 private void showColumns() {
4164 noteTableView.setColumnHidden(Global.noteTableCreationPosition, !Global.isColumnVisible("dateCreated"));
4165 noteTableView.setColumnHidden(Global.noteTableChangedPosition, !Global.isColumnVisible("dateChanged"));
4166 noteTableView.setColumnHidden(Global.noteTableSubjectDatePosition, !Global.isColumnVisible("dateSubject"));
4167 noteTableView.setColumnHidden(Global.noteTableAuthorPosition, !Global.isColumnVisible("author"));
4168 noteTableView.setColumnHidden(Global.noteTableSourceUrlPosition, !Global.isColumnVisible("sourceUrl"));
4169 noteTableView.setColumnHidden(Global.noteTableTagPosition, !Global.isColumnVisible("tags"));
4170 noteTableView.setColumnHidden(Global.noteTableNotebookPosition, !Global.isColumnVisible("notebook"));
4171 noteTableView.setColumnHidden(Global.noteTableSynchronizedPosition, !Global.isColumnVisible("synchronized"));
4172 noteTableView.setColumnHidden(Global.noteTableGuidPosition, !Global.isColumnVisible("guid"));
4173 noteTableView.setColumnHidden(Global.noteTableThumbnailPosition, !Global.isColumnVisible("thumbnail"));
4174 noteTableView.setColumnHidden(Global.noteTableTitlePosition, !Global.isColumnVisible("title"));
4175 noteTableView.setColumnHidden(Global.noteTablePinnedPosition, !Global.isColumnVisible("pinned"));
4177 // Title color has changed
4178 @SuppressWarnings("unused")
4179 private void titleColorChanged(Integer color) {
4180 logger.log(logger.HIGH, "Entering NeverNote.titleColorChanged");
4183 QColor backgroundColor = new QColor();
4184 QColor foregroundColor = new QColor(QColor.black);
4185 backgroundColor.setRgb(color);
4187 if (backgroundColor.rgb() == QColor.black.rgb() || backgroundColor.rgb() == QColor.blue.rgb())
4188 foregroundColor.setRgb(QColor.white.rgb());
4190 if (selectedNoteGUIDs.size() == 0)
4191 selectedNoteGUIDs.add(currentNoteGuid);
4193 for (int j=0; j<selectedNoteGUIDs.size(); j++) {
4194 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4195 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4196 if (modelIndex != null) {
4197 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4198 String tableGuid = (String)ix.values().toArray()[0];
4199 if (tableGuid.equals(selectedNoteGUIDs.get(j))) {
4200 for (int k=0; k<Global.noteTableColumnCount; k++) {
4201 listManager.getNoteTableModel().setData(i, k, backgroundColor, Qt.ItemDataRole.BackgroundRole);
4202 listManager.getNoteTableModel().setData(i, k, foregroundColor, Qt.ItemDataRole.ForegroundRole);
4203 listManager.updateNoteTitleColor(selectedNoteGUIDs.get(j), backgroundColor.rgb());
4205 i=listManager.getNoteTableModel().rowCount();
4210 logger.log(logger.HIGH, "Leaving NeverNote.titleColorChanged");
4212 // A note has been pinned or unpinned
4213 @SuppressWarnings("unused")
4214 private void notePinned() {
4215 logger.log(logger.EXTREME, "Entering NeverNote.notePinned()");
4218 for (int j=0; j<selectedNoteGUIDs.size(); j++) {
4219 NoteMetadata meta = listManager.getNoteMetadata().get(selectedNoteGUIDs.get(j));
4220 boolean pinned = !meta.isPinned();
4221 meta.setPinned(pinned); // Toggle the pinned/unpinned
4223 // Update the list & table
4224 listManager.updateNoteMetadata(meta);
4225 noteTableView.proxyModel.addGuid(selectedNoteGUIDs.get(j), meta);
4228 logger.log(logger.EXTREME, "Leaving NeverNote.setNoteDirty()");
4230 // Wide list was chosen
4231 public void narrowListView() {
4232 saveNoteColumnPositions();
4233 saveNoteIndexWidth();
4235 int sortCol = noteTableView.proxyModel.sortColumn();
4236 int sortOrder = noteTableView.proxyModel.sortOrder().value();
4237 Global.setSortColumn(sortCol);
4238 Global.setSortOrder(sortOrder);
4240 Global.setListView(Global.View_List_Narrow);
4242 menuBar.wideListView.blockSignals(true);
4243 menuBar.narrowListView.blockSignals(true);
4245 menuBar.wideListView.setChecked(false);
4246 menuBar.narrowListView.setChecked(true);
4248 menuBar.wideListView.blockSignals(false);
4249 menuBar.narrowListView.blockSignals(false);
4251 mainLeftRightSplitter.addWidget(noteTableView);
4252 mainLeftRightSplitter.addWidget(browserWindow);
4253 restoreWindowState(false);
4254 noteTableView.repositionColumns();
4255 noteTableView.resizeColumnWidths();
4256 noteTableView.resizeRowHeights();
4258 sortCol = Global.getSortColumn();
4259 sortOrder = Global.getSortOrder();
4260 noteTableView.proxyModel.blocked = true;
4261 noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder));
4262 noteTableView.proxyModel.blocked = false;
4266 noteTableView.load(false);
4267 refreshEvernoteNote(true);
4268 scrollToCurrentGuid();
4270 public void wideListView() {
4271 int sortCol = noteTableView.proxyModel.sortColumn();
4272 int sortOrder = noteTableView.proxyModel.sortOrder().value();
4273 Global.setSortColumn(sortCol);
4274 Global.setSortOrder(sortOrder);
4277 saveNoteColumnPositions();
4278 saveNoteIndexWidth();
4279 Global.setListView(Global.View_List_Wide);
4281 menuBar.wideListView.blockSignals(true);
4282 menuBar.narrowListView.blockSignals(true);
4284 menuBar.wideListView.setChecked(true);
4285 menuBar.narrowListView.setChecked(false);
4287 menuBar.wideListView.blockSignals(false);
4288 menuBar.narrowListView.blockSignals(false);
4289 browserIndexSplitter.setVisible(true);
4290 browserIndexSplitter.addWidget(noteTableView);
4291 browserIndexSplitter.addWidget(browserWindow);
4292 restoreWindowState(false);
4293 noteTableView.repositionColumns();
4294 noteTableView.resizeColumnWidths();
4295 noteTableView.resizeRowHeights();
4297 sortCol = Global.getSortColumn();
4298 sortOrder = Global.getSortOrder();
4299 noteTableView.proxyModel.blocked = true;
4300 noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder));
4301 noteTableView.proxyModel.blocked = false;
4304 noteTableView.load(false);
4305 scrollToCurrentGuid();
4307 // Sort order for the notebook has changed
4308 public void tableSortOrderChanged(Integer column, Integer order) {
4310 // Find what notebook (if any) is selected. We ignore stacks & the "All Notebooks".
4311 List<QTreeWidgetItem> selectedNotebook = notebookTree.selectedItems();
4312 if (selectedNotebook.size() > 0 && !selectedNotebook.get(0).text(0).equalsIgnoreCase("All Notebooks") && !selectedNotebook.get(0).text(2).equalsIgnoreCase("STACK")) {
4313 QTreeWidgetItem currentSelectedNotebook = selectedNotebook.get(0);
4315 notebook = currentSelectedNotebook.text(2);
4316 conn.getNotebookTable().setSortOrder(notebook, column, order);
4320 //***************************************************************
4321 @SuppressWarnings("unused")
4322 private void evernoteLinkClick(String syncGuid, String locGuid) {
4324 if (conn.getNoteTable().guidExists(syncGuid)) {
4327 // If we didn't find it via the synchronized guid, look under the local guid
4328 // Iwe don't find it there, look to see if the GUID is posted under the local GUID, but was
4329 // later synchronized (that causes the guid to change so we need to find the new one).
4330 if (conn.getNoteTable().guidExists(locGuid))
4333 guid = conn.getNoteTable().findAlternateGuid(locGuid);
4336 openExternalEditor(guid);
4340 //If we've gotten this far, we can't find the note
4341 QMessageBox.information(this, tr("Note Not Found"), tr("Sorry, but I can't"+
4342 " seem to find that note."));
4344 //***************************************************************
4345 //***************************************************************
4346 //** External editor window functions
4347 //***************************************************************
4348 //***************************************************************
4349 private void listDoubleClick() {
4351 openExternalEditor(currentNoteGuid);
4353 private void openExternalEditor(String guid) {
4355 if (externalWindows.containsKey(guid)) {
4356 externalWindows.get(guid).raise();
4359 Note note = conn.getNoteTable().getNote(guid, true, true, false, true, true);
4360 // We have a new external editor to create
4361 QIcon appIcon = new QIcon(iconPath+"nevernote.png");
4362 ExternalBrowse newBrowser = new ExternalBrowse(conn);
4363 newBrowser.setWindowIcon(appIcon);
4364 externalWindows.put(guid, newBrowser);
4365 showEditorButtons(newBrowser.getBrowserWindow());
4366 loadNoteBrowserInformation(newBrowser.getBrowserWindow(), guid, note);
4367 setupBrowserWindowListeners(newBrowser.getBrowserWindow(), false);
4368 newBrowser.windowClosing.connect(this, "externalWindowClosing(String)");
4369 //newBrowser.getBrowserWindow().noteSignal.titleChanged.connect(this, "externalWindowTitleEdited(String, String)");
4370 newBrowser.getBrowserWindow().noteSignal.tagsChanged.connect(this, "externalWindowTagsEdited(String, List)");
4371 newBrowser.contentsChanged.connect(this, "saveNoteExternalBrowser(String, String, Boolean, BrowserWindow)");
4372 newBrowser.getBrowserWindow().blockApplication.connect(this, "blockApplication(BrowserWindow)");
4373 newBrowser.getBrowserWindow().unblockApplication.connect(this, "unblockApplication()");
4375 browserWindow.noteSignal.tagsChanged.connect(newBrowser, "updateTags(String, List)");
4376 browserWindow.noteSignal.titleChanged.connect(newBrowser, "updateTitle(String, String)");
4377 browserWindow.noteSignal.notebookChanged.connect(newBrowser, "updateNotebook(String, String)");
4381 @SuppressWarnings({ "rawtypes", "unused" })
4382 private void externalWindowTagsEdited(String guid, List values) {
4383 StringBuffer line = new StringBuffer(100);
4384 for (int i=0; i<values.size(); i++) {
4386 line.append(Global.tagDelimeter+" ");
4387 line.append(values.get(i));
4389 if (guid.equals(currentNoteGuid)) {
4390 browserWindow.setTag(line.toString());
4393 @SuppressWarnings("unused")
4394 private void externalWindowClosing(String guid) {
4395 externalWindows.remove(guid);
4400 //***************************************************************
4401 //***************************************************************
4402 //** These functions deal with Note specific things
4403 //***************************************************************
4404 //***************************************************************
4405 private void setNoteDirty() {
4406 logger.log(logger.EXTREME, "Entering NeverNote.setNoteDirty()");
4408 // Find if the note is being edited externally. If it is, update it.
4409 if (externalWindows.containsKey(currentNoteGuid)) {
4410 QTextCodec codec = QTextCodec.codecForName("UTF-8");
4411 QByteArray unicode = codec.fromUnicode(browserWindow.getContent());
4412 ExternalBrowse window = externalWindows.get(currentNoteGuid);
4413 window.getBrowserWindow().setContent(unicode);
4416 // If the note is dirty, then it is unsynchronized by default.
4420 // Set the note as dirty and check if its status is synchronized in the display table
4422 if (listManager.getNoteMetadata().containsKey(currentNoteGuid) &&
4423 listManager.getNoteMetadata().get(currentNoteGuid).isDirty()) {
4427 // If this wasn't already marked as unsynchronized, then we need to update the table
4428 listManager.getNoteTableModel().updateNoteSyncStatus(currentNoteGuid, false);
4429 // listManager.getUnsynchronizedNotes().add(currentNoteGuid);
4430 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4431 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4432 if (modelIndex != null) {
4433 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4434 String tableGuid = (String)ix.values().toArray()[0];
4435 if (tableGuid.equals(currentNoteGuid)) {
4436 listManager.getNoteTableModel().proxyModel.setData(i, Global.noteTableSynchronizedPosition, "false");
4442 logger.log(logger.EXTREME, "Leaving NeverNote.setNoteDirty()");
4444 @SuppressWarnings("unused")
4445 private void saveNoteExternalBrowser(String guid, String content, Boolean save, BrowserWindow browser) {
4446 QTextCodec codec = QTextCodec.codecForName("UTF-8");
4447 QByteArray unicode = codec.fromUnicode(content);
4448 noteCache.remove(guid);
4449 noteCache.put(guid, unicode.toString());
4450 if (guid.equals(currentNoteGuid)) {
4452 browserWindow.setContent(unicode);
4455 thumbnailRunner.addWork("GENERATE "+ guid);
4456 saveNote(guid, browser);
4460 private void saveNote() {
4462 saveNote(currentNoteGuid, browserWindow);
4463 thumbnailRunner.addWork("GENERATE "+ currentNoteGuid);
4467 private void saveNote(String guid, BrowserWindow window) {
4468 logger.log(logger.EXTREME, "Inside NeverNote.saveNote()");
4471 logger.log(logger.EXTREME, "Saving to cache");
4472 QTextCodec codec = QTextCodec.codecForLocale();
4473 // QTextDecoder decoder = codec.makeDecoder();
4474 codec = QTextCodec.codecForName("UTF-8");
4475 QByteArray unicode = codec.fromUnicode(window.getContent());
4476 noteCache.put(guid, unicode.toString());
4478 logger.log(logger.EXTREME, "updating list manager");
4479 listManager.updateNoteContent(guid, window.getContent());
4480 logger.log(logger.EXTREME, "Updating title");
4481 listManager.updateNoteTitle(guid, window.getTitle());
4482 updateListDateChanged();
4484 logger.log(logger.EXTREME, "Looking through note index for refreshed note");
4485 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
4486 if (listManager.getNoteIndex().get(i).getGuid().equals(guid)) {
4487 currentNote = listManager.getNoteIndex().get(i);
4488 i = listManager.getNoteIndex().size();
4493 // Get a note from Evernote (and put it in the browser)
4494 private void refreshEvernoteNote(boolean reload) {
4495 logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNote");
4497 if (Global.disableViewing) {
4498 browserWindow.setEnabled(false);
4503 if (Global.showDeleted || currentNoteGuid == null || currentNoteGuid.equals(""))
4505 Global.cryptCounter =0;
4507 browserWindow.setReadOnly(true);
4514 browserWindow.loadingData(true);
4516 currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true);
4517 if (currentNote == null)
4519 loadNoteBrowserInformation(browserWindow, currentNoteGuid, currentNote);
4522 private void loadNoteBrowserInformation(BrowserWindow browser, String guid, Note note) {
4523 NoteFormatter formatter = new NoteFormatter(logger, conn, tempFiles);
4524 formatter.setNote(note, Global.pdfPreview());
4525 formatter.setHighlight(listManager.getEnSearch());
4527 if (!noteCache.containsKey(guid)) {
4528 js = new QByteArray();
4529 // We need to prepend the note with <HEAD></HEAD> or encoded characters are ugly
4530 js.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
4531 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>");
4532 js.append("<style type=\"text/css\">en-hilight { background-color: rgb(255,255,0) }</style>");
4533 js.append("<style> img { height:auto; width:auto; max-height:auto; max-width:100%; }</style>");
4534 if (Global.displayRightToLeft())
4535 js.append("<style> body { direction:rtl; }</style>");
4536 js.append("<style type=\"text/css\">en-spell { text-decoration: none; border-bottom: dotted 1px #cc0000; }</style>");
4537 js.append("</head>");
4538 formatter.setNote(note, Global.pdfPreview());
4539 js.append(formatter.rebuildNoteHTML());
4540 js.append("</HTML>");
4541 js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml.dtd'>", "");
4542 js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml2.dtd'>", "");
4543 js.replace("<?xml version='1.0' encoding='UTF-8'?>", "");
4544 // if (Global.enableHTMLEntitiesFix) {
4545 // browser.getBrowser().setContent(new QByteArray(StringEscapeUtils.unescapeHtml(js.toString())));
4547 browser.setContent(js);
4548 noteCache.put(guid, js.toString());
4550 if (formatter.resourceError)
4551 resourceErrorMessage();
4552 if (formatter.formatError) {
4554 QMessageBox.information(this, tr("Error"),
4555 tr("NixNote had issues formatting this note." +
4556 " To protect your data this note is being marked as read-only."));
4559 readOnly = formatter.readOnly;
4560 inkNote = formatter.inkNote;
4562 readOnlyCache.put(guid, true);
4564 inkNoteCache.put(guid, true);
4566 logger.log(logger.HIGH, "Note content is being pulled from the cache");
4567 String cachedContent = formatter.modifyCachedTodoTags(noteCache.get(guid));
4568 js = new QByteArray(cachedContent);
4569 browser.setContent(js);
4570 if (readOnlyCache.containsKey(guid))
4572 if (inkNoteCache.containsKey(guid))
4575 if (conn.getNoteTable().isThumbnailNeeded(guid)) {
4576 thumbnailHTMLReady(guid, js, Global.calculateThumbnailZoom(js.toString()));
4578 if (readOnly || inkNote ||
4579 (note.getAttributes() != null && note.getAttributes().getContentClass() != null && note.getAttributes().getContentClass() != ""))
4580 browser.getBrowser().page().setContentEditable(false); // We don't allow editing of ink notes
4582 browser.getBrowser().page().setContentEditable(true);
4583 browser.setReadOnly(readOnly);
4584 deleteButton.setEnabled(!readOnly);
4585 tagButton.setEnabled(!readOnly);
4586 menuBar.noteDelete.setEnabled(!readOnly);
4587 menuBar.noteTags.setEnabled(!readOnly);
4588 browser.setNote(note);
4590 if (note != null && note.getNotebookGuid() != null &&
4591 conn.getNotebookTable().isLinked(note.getNotebookGuid())) {
4592 deleteButton.setEnabled(false);
4593 menuBar.notebookDeleteAction.setEnabled(false);
4595 deleteButton.setEnabled(true);
4596 menuBar.notebookDeleteAction.setEnabled(true);
4599 // Build a list of non-closed notebooks
4600 List<Notebook> nbooks = new ArrayList<Notebook>();
4601 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
4602 boolean found=false;
4603 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
4604 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
4608 nbooks.add(listManager.getNotebookIndex().get(i));
4611 browser.setTitle(note.getTitle());
4612 browser.setTag(getTagNamesForNote(note));
4613 browser.setAuthor(note.getAttributes().getAuthor());
4615 browser.setAltered(note.getUpdated());
4616 browser.setCreation(note.getCreated());
4617 if (note.getAttributes().getSubjectDate() > 0)
4618 browser.setSubjectDate(note.getAttributes().getSubjectDate());
4620 browser.setSubjectDate(note.getCreated());
4621 browser.setUrl(note.getAttributes().getSourceURL());
4623 FilterEditorTags tagFilter = new FilterEditorTags(conn, logger);
4624 List<Tag> tagList = tagFilter.getValidTags(note);
4625 browser.setAllTags(tagList);
4627 browser.setCurrentTags(note.getTagNames());
4631 browser.loadingData(false);
4632 if (thumbnailViewer.isActiveWindow())
4635 FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger);
4636 browser.setNotebookList(notebookFilter.getValidNotebooks(note, listManager.getNotebookIndex()));
4639 logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNote");
4641 // Save a generated thumbnail
4642 private void toggleNoteInformation() {
4643 logger.log(logger.HIGH, "Entering NeverNote.toggleNoteInformation");
4644 browserWindow.toggleInformation();
4645 menuBar.noteAttributes.setChecked(browserWindow.isExtended());
4646 Global.saveWindowVisible("noteInformation", browserWindow.isExtended());
4647 logger.log(logger.HIGH, "Leaving NeverNote.toggleNoteInformation");
4649 // Listener triggered when a print button is pressed
4650 @SuppressWarnings("unused")
4651 private void printNote() {
4652 logger.log(logger.HIGH, "Entering NeverNote.printNote");
4654 QPrintDialog dialog = new QPrintDialog();
4655 if (dialog.exec() == QDialog.DialogCode.Accepted.value()) {
4656 QPrinter printer = dialog.printer();
4657 browserWindow.getBrowser().print(printer);
4659 logger.log(logger.HIGH, "Leaving NeverNote.printNote");
4662 // Listener triggered when the email button is pressed
4663 @SuppressWarnings("unused")
4664 private void emailNote() {
4665 logger.log(logger.HIGH, "Entering NeverNote.emailNote");
4667 if (Desktop.isDesktopSupported()) {
4668 Desktop desktop = Desktop.getDesktop();
4670 String text2 = browserWindow.getContentsToEmail();
4671 QUrl url = new QUrl("mailto:");
4672 url.addQueryItem("subject", currentNote.getTitle());
4673 // url.addQueryItem("body", QUrl.toPercentEncoding(text2).toString());
4674 url.addQueryItem("body", text2);
4675 QDesktopServices.openUrl(url);
4679 if (desktop.isSupported(Desktop.Action.MAIL)) {
4680 URI uriMailTo = null;
4682 //String text = browserWindow.getBrowser().page().currentFrame().toPlainText();
4683 String text = browserWindow.getContentsToEmail();
4684 //text = "<b>" +text +"</b>";
4685 uriMailTo = new URI("mailto", "&SUBJECT="+currentNote.getTitle()
4686 +"&BODY=" +text, null);
4687 uriMailTo = new URI("mailto", "&SUBJECT="+currentNote.getTitle()
4688 +"&ATTACHMENT=d:/test.pdf", null);
4689 desktop.mail(uriMailTo);
4690 } catch (URISyntaxException e) {
4691 e.printStackTrace();
4692 } catch (IOException e) {
4693 e.printStackTrace();
4700 logger.log(logger.HIGH, "Leaving NeverNote.emailNote");
4702 // Reindex all notes
4703 @SuppressWarnings("unused")
4704 private void fullReindex() {
4705 logger.log(logger.HIGH, "Entering NeverNote.fullReindex");
4706 indexRunner.addWork("REINDEXALL");
4707 setMessage(tr("Database will be reindexed."));
4708 logger.log(logger.HIGH, "Leaving NeverNote.fullReindex");
4710 // Listener when a user wants to reindex a specific note
4711 @SuppressWarnings("unused")
4712 private void reindexNote() {
4713 logger.log(logger.HIGH, "Entering NeverNote.reindexNote");
4714 for (int i=0; i<selectedNoteGUIDs.size(); i++) {
4715 indexRunner.addWork("REINDEXNOTE "+selectedNoteGUIDs.get(i));
4717 if (selectedNotebookGUIDs.size() > 1)
4718 setMessage(tr("Notes will be reindexed."));
4720 setMessage(tr("Note will be reindexed."));
4721 logger.log(logger.HIGH, "Leaving NeverNote.reindexNote");
4724 @SuppressWarnings("unused")
4725 private void deleteNote() {
4726 logger.log(logger.HIGH, "Entering NeverNote.deleteNote");
4727 if (currentNote == null)
4729 if (currentNoteGuid.equals(""))
4731 String title = null;
4732 if (selectedNoteGUIDs.size() == 1)
4733 title = conn.getNoteTable().getNote(selectedNoteGUIDs.get(0),false,false,false,false,false).getTitle();
4735 // If we are deleting non-trash notes
4736 if (currentNote.isActive()) {
4737 if (Global.verifyDelete()) {
4739 if (selectedNoteGUIDs.size() > 1) {
4740 msg = new String(tr("Delete ") +selectedNoteGUIDs.size() +" notes?");
4743 msg = new String(tr("Delete note \"") +title +"\"?");
4745 msg = new String(tr("Delete note selected note?"));
4747 if (QMessageBox.question(this, tr("Confirmation"), msg,
4748 QMessageBox.StandardButton.Yes,
4749 QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) {
4753 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals(""))
4754 selectedNoteGUIDs.add(currentNoteGuid);
4755 for (int i=0; i<selectedNoteGUIDs.size(); i++) {
4756 listManager.deleteNote(selectedNoteGUIDs.get(i));
4759 // If we are deleting from the trash.
4760 if (Global.verifyDelete()) {
4762 if (selectedNoteGUIDs.size() > 1) {
4763 msg = new String(tr("Permanently delete ") +selectedNoteGUIDs.size() +" notes?");
4766 msg = new String(tr("Permanently delete note \"") +title +"\"?");
4768 msg = new String(tr("Permanently delete note selected note?"));
4770 if (QMessageBox.question(this, "Confirmation", msg,
4771 QMessageBox.StandardButton.Yes,
4772 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
4776 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals(""))
4777 selectedNoteGUIDs.add(currentNoteGuid);
4778 for (int i=selectedNoteGUIDs.size()-1; i>=0; i--) {
4779 for (int j=listManager.getNoteTableModel().rowCount()-1; j>=0; j--) {
4780 QModelIndex modelIndex = listManager.getNoteTableModel().index(j, Global.noteTableGuidPosition);
4781 if (modelIndex != null) {
4782 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4783 String tableGuid = (String)ix.values().toArray()[0];
4784 if (tableGuid.equals(selectedNoteGUIDs.get(i))) {
4785 listManager.getNoteTableModel().removeRow(j);
4790 listManager.expungeNote(selectedNoteGUIDs.get(i));
4793 currentNoteGuid = "";
4794 listManager.loadNotesIndex();
4795 noteIndexUpdated(false);
4796 refreshEvernoteNote(true);
4797 scrollToGuid(currentNoteGuid);
4798 logger.log(logger.HIGH, "Leaving NeverNote.deleteNote");
4801 @SuppressWarnings("unused")
4802 private void addNote() {
4803 logger.log(logger.HIGH, "Inside NeverNote.addNote");
4804 // browserWindow.setEnabled(true);
4805 browserWindow.setReadOnly(false);
4807 Calendar currentTime = new GregorianCalendar();
4808 StringBuffer noteString = new StringBuffer(100);
4809 noteString.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
4810 "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">\n" +
4813 if (Global.overrideDefaultFont()) {
4814 noteString.append("<font face=\"" +Global.getDefaultFont() +"\" >");
4815 noteString.append("<span style=\"font-size:" +Global.getDefaultFontSize() +"pt;\">");
4816 noteString.append("<br clear=\"none\" />\n");
4817 noteString.append("</span>\n</font>\n");
4819 noteString.append("<br clear=\"none\" />\n");
4820 noteString.append("</en-note>");
4822 Long l = new Long(currentTime.getTimeInMillis());
4823 String randint = new String(Long.toString(l));
4825 // Find a notebook. We first look for a selected notebook (the "All Notebooks" one doesn't count).
4827 // for the first non-archived notebook. Finally, if nothing else we
4828 // pick the first notebook in the list.
4829 String notebook = null;
4830 listManager.getNotebookIndex().get(0).getGuid();
4831 List<QTreeWidgetItem> selectedNotebook = notebookTree.selectedItems();
4832 if (selectedNotebook.size() > 0 && !selectedNotebook.get(0).text(0).equalsIgnoreCase("All Notebooks") && !selectedNotebook.get(0).text(2).equalsIgnoreCase("STACK")) {
4833 QTreeWidgetItem currentSelectedNotebook = selectedNotebook.get(0);
4834 notebook = currentSelectedNotebook.text(2);
4836 boolean found = false;
4837 List<Notebook> goodNotebooks = new ArrayList<Notebook>();
4838 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
4839 boolean match = false;
4840 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
4841 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid())) {
4843 j = listManager.getArchiveNotebookIndex().size();
4847 //goodNotebooks.add(listManager.getNotebookIndex().get(i).deepCopy());
4848 goodNotebooks.add((Notebook)Global.deepCopy(listManager.getNotebookIndex().get(i)));
4850 // Now we have a list of good notebooks, so we can look for the default
4852 for (int i=0; i<goodNotebooks.size(); i++) {
4853 if (goodNotebooks.get(i).isDefaultNotebook()) {
4854 notebook = goodNotebooks.get(i).getGuid();
4856 i = goodNotebooks.size();
4860 if (goodNotebooks.size() > 0 && !found)
4861 notebook = goodNotebooks.get(0).getGuid();
4864 notebook = listManager.getNotebookIndex().get(0).getGuid();
4867 Note newNote = new Note();
4868 newNote.setUpdateSequenceNum(0);
4869 newNote.setGuid(randint);
4870 newNote.setNotebookGuid(notebook);
4871 newNote.setTitle("Untitled Note");
4872 newNote.setContent(noteString.toString());
4873 newNote.setDeleted(0);
4874 newNote.setCreated(System.currentTimeMillis());
4875 newNote.setUpdated(System.currentTimeMillis());
4876 newNote.setActive(true);
4877 NoteAttributes na = new NoteAttributes();
4878 na.setLatitude(0.0);
4879 na.setLongitude(0.0);
4880 na.setAltitude(0.0);
4881 newNote.setAttributes(new NoteAttributes());
4882 newNote.setTagGuids(new ArrayList<String>());
4883 newNote.setTagNames(new ArrayList<String>());
4885 // If new notes are to be created based upon the selected tags, then we need to assign the tags
4886 if (Global.newNoteWithSelectedTags()) {
4887 List<QTreeWidgetItem> selections = tagTree.selectedItems();
4888 QTreeWidgetItem currentSelection;
4889 for (int i=0; i<selections.size(); i++) {
4890 currentSelection = selections.get(i);
4891 newNote.getTagGuids().add(currentSelection.text(2));
4892 newNote.getTagNames().add(currentSelection.text(0));
4896 conn.getNoteTable().addNote(newNote, true);
4897 NoteMetadata metadata = new NoteMetadata();
4898 metadata.setGuid(newNote.getGuid());
4899 metadata.setDirty(true);
4900 listManager.addNote(newNote, metadata);
4901 // noteTableView.insertRow(newNote, true, -1);
4903 currentNote = newNote;
4904 currentNoteGuid = currentNote.getGuid();
4905 noteTableView.clearSelection();
4906 refreshEvernoteNote(true);
4907 listManager.countNotebookResults(listManager.getNoteIndex());
4908 browserWindow.titleLabel.setFocus();
4909 browserWindow.titleLabel.selectAll();
4910 // notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
4912 // If the window is hidden, then we want to popup this in an external window &
4916 logger.log(logger.HIGH, "Leaving NeverNote.addNote");
4918 // Restore a note from the trash;
4919 @SuppressWarnings("unused")
4920 private void restoreNote() {
4922 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals(""))
4923 selectedNoteGUIDs.add(currentNoteGuid);
4924 for (int i=0; i<selectedNoteGUIDs.size(); i++) {
4925 listManager.restoreNote(selectedNoteGUIDs.get(i));
4927 currentNoteGuid = "";
4928 listManager.loadNotesIndex();
4929 noteIndexUpdated(false);
4932 // Search a note for specific txt
4933 @SuppressWarnings("unused")
4934 private void findText() {
4936 find.setFocusOnTextField();
4938 @SuppressWarnings("unused")
4939 private void doFindText() {
4940 browserWindow.getBrowser().page().findText(find.getText(), find.getFlags());
4943 @SuppressWarnings("unused")
4944 private void updateNoteTitle(String guid, String title) {
4945 listManager.setNoteSynchronized(guid, false);
4947 // We do this manually because if we've edited the note in an
4948 // external window we run into the possibility of signal recursion
4950 if (guid.equals(currentNoteGuid)) {
4951 browserWindow.titleLabel.blockSignals(true);
4952 browserWindow.titleLabel.setText(title);
4953 browserWindow.titleLabel.blockSignals(false);
4956 // Signal received that note content has changed. Normally we just need the guid to remove
4957 // it from the cache.
4958 @SuppressWarnings("unused")
4959 private void invalidateNoteCache(String guid, String content) {
4960 noteCache.remove(guid);
4961 refreshEvernoteNote(true);
4963 // Signal received that a note guid has changed
4964 @SuppressWarnings("unused")
4965 private void noteGuidChanged(String oldGuid, String newGuid) {
4966 if (noteCache.containsKey(oldGuid)) {
4967 if (!oldGuid.equals(currentNoteGuid)) {
4968 String cache = noteCache.get(oldGuid);
4969 noteCache.put(newGuid, cache);
4970 noteCache.remove(oldGuid);
4972 noteCache.remove(oldGuid);
4973 noteCache.put(newGuid, browserWindow.getContent());
4977 listManager.updateNoteGuid(oldGuid, newGuid, false);
4978 if (currentNoteGuid.equals(oldGuid)) {
4979 if (currentNote != null)
4980 currentNote.setGuid(newGuid);
4981 currentNoteGuid = newGuid;
4984 if (externalWindows.containsKey(oldGuid)) {
4985 ExternalBrowse b = externalWindows.get(oldGuid);
4986 externalWindows.remove(oldGuid);
4987 b.getBrowserWindow().getNote().setGuid(newGuid);
4988 externalWindows.put(newGuid, b);
4991 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
4992 if (listManager.getNoteIndex().get(i).getGuid().equals(newGuid)) {
4993 noteTableView.proxyModel.addGuid(newGuid, listManager.getNoteMetadata().get(newGuid));
4994 i=listManager.getNoteIndex().size();
4998 if (listManager.getNoteTableModel().metaData.containsKey(oldGuid)) {
4999 NoteMetadata meta = listManager.getNoteTableModel().metaData.get(oldGuid);
5000 listManager.getNoteTableModel().metaData.put(newGuid, meta);
5001 listManager.getNoteTableModel().metaData.remove(oldGuid);
5005 // Toggle the note editor button bar
5006 private void toggleEditorButtonBar() {
5007 if (browserWindow.buttonsVisible) {
5008 browserWindow.hideButtons();
5009 menuBar.showEditorBar.setChecked(browserWindow.buttonsVisible);
5010 // Global.saveWindowVisible("editorButtonBar", browserWindow.buttonsVisible);
5012 browserWindow.buttonsVisible = true;
5013 showEditorButtons(browserWindow);
5015 Global.saveWindowVisible("editorButtonBar", browserWindow.buttonsVisible);
5017 // Show editor buttons
5018 private void showEditorButtons(BrowserWindow browser) {
5019 browser.buttonLayout.setVisible(true);
5020 browser.undoAction.setVisible(false);
5022 browser.undoButton.setVisible(false);
5024 browser.undoAction.setVisible(Global.isEditorButtonVisible("undo"));
5025 browser.redoAction.setVisible(Global.isEditorButtonVisible("redo"));
5026 browser.cutAction.setVisible(Global.isEditorButtonVisible("cut"));
5027 browser.copyAction.setVisible(Global.isEditorButtonVisible("copy"));
5028 browser.pasteAction.setVisible(Global.isEditorButtonVisible("paste"));
5029 browser.strikethroughAction.setVisible(Global.isEditorButtonVisible("strikethrough"));
5030 browser.underlineAction.setVisible(Global.isEditorButtonVisible("underline"));
5031 browser.boldAction.setVisible(Global.isEditorButtonVisible("bold"));
5032 browser.italicAction.setVisible(Global.isEditorButtonVisible("italic"));
5033 browser.hlineAction.setVisible(Global.isEditorButtonVisible("hline"));
5034 browser.indentAction.setVisible(Global.isEditorButtonVisible("indent"));
5035 browser.outdentAction.setVisible(Global.isEditorButtonVisible("outdent"));
5036 browser.bulletListAction.setVisible(Global.isEditorButtonVisible("bulletList"));
5037 browser.numberListAction.setVisible(Global.isEditorButtonVisible("numberList"));
5038 browser.fontListAction.setVisible(Global.isEditorButtonVisible("font"));
5039 browser.fontSizeAction.setVisible(Global.isEditorButtonVisible("fontSize"));
5040 browser.fontColorAction.setVisible(Global.isEditorButtonVisible("fontColor"));
5041 browser.fontHilightAction.setVisible(Global.isEditorButtonVisible("fontHilight"));
5042 browser.leftAlignAction.setVisible(Global.isEditorButtonVisible("alignLeft"));
5043 browser.centerAlignAction.setVisible(Global.isEditorButtonVisible("alignCenter"));
5044 browser.rightAlignAction.setVisible(Global.isEditorButtonVisible("alignRight"));
5045 browser.spellCheckAction.setVisible(Global.isEditorButtonVisible("spellCheck"));
5046 browser.todoAction.setVisible(Global.isEditorButtonVisible("todo"));
5048 private void duplicateNote(String guid) {
5050 Note oldNote = conn.getNoteTable().getNote(guid, true, false,false,false,true);
5051 List<Resource> resList = conn.getNoteTable().noteResourceTable.getNoteResources(guid, true);
5052 oldNote.setContent(conn.getNoteTable().getNoteContentNoUTFConversion(guid));
5053 oldNote.setResources(resList);
5054 duplicateNote(oldNote);
5056 private void duplicateNote(Note oldNote) {
5058 // Now that we have a good notebook guid, we need to move the conflicting note
5059 // to the local notebook
5060 Calendar currentTime = new GregorianCalendar();
5061 Long l = new Long(currentTime.getTimeInMillis());
5062 String newGuid = new String(Long.toString(l));
5064 // Note newNote = oldNote.deepCopy();
5065 Note newNote = (Note)Global.deepCopy(oldNote);
5066 newNote.setUpdateSequenceNum(0);
5067 newNote.setGuid(newGuid);
5068 newNote.setDeleted(0);
5069 newNote.setActive(true);
5072 List<String> tagNames = new ArrayList<String>();
5073 List<String> tagGuids = new ArrayList<String>();;
5074 for (int i=0; i<oldNote.getTagGuidsSize(); i++) {
5075 tagNames.add(oldNote.getTagNames().get(i));
5076 tagGuids.add(oldNote.getTagGuids().get(i));
5079 // Sort note Tags to make them look nice
5080 for (int i=0; i<tagNames.size()-1; i++) {
5081 if (tagNames.get(i).compareTo(tagNames.get(i+1))<0) {
5082 String n1 = tagNames.get(i);
5083 String n2 = tagNames.get(i+1);
5084 tagNames.set(i, n2);
5085 tagNames.set(i+1, n1);
5088 newNote.setTagGuids(tagGuids);
5089 newNote.setTagNames(tagNames);
5091 // Add tag guids to note
5094 // Duplicate resources
5095 List<Resource> resList = oldNote.getResources();
5096 if (resList == null)
5097 resList = new ArrayList<Resource>();
5099 for (int i=0; i<resList.size(); i++) {
5101 while (l == prevGuid) {
5102 currentTime = new GregorianCalendar();
5103 l = new Long(currentTime.getTimeInMillis());
5106 String newResGuid = new String(Long.toString(l));
5107 resList.get(i).setNoteGuid(newGuid);
5108 resList.get(i).setGuid(newResGuid);
5109 resList.get(i).setUpdateSequenceNum(0);
5110 resList.get(i).setActive(true);
5111 conn.getNoteTable().noteResourceTable.saveNoteResource(
5112 (Resource)Global.deepCopy(resList.get(i)), true);
5114 newNote.setResources(resList);
5116 // Add note to the database
5117 conn.getNoteTable().addNote(newNote, true);
5118 NoteMetadata metaData = new NoteMetadata();
5119 NoteMetadata oldMeta = listManager.getNoteMetadata().get(oldNote.getGuid());
5120 metaData.copy(oldMeta);
5121 metaData.setGuid(newNote.getGuid());
5122 listManager.addNote(newNote, metaData);
5123 noteTableView.insertRow(newNote, metaData, true, -1);
5124 currentNoteGuid = newNote.getGuid();
5125 currentNote = newNote;
5126 refreshEvernoteNote(true);
5127 listManager.countNotebookResults(listManager.getNoteIndex());
5131 @SuppressWarnings("unused")
5132 private void allNotes() {
5133 clearAttributeFilter();
5134 clearNotebookFilter();
5135 clearSavedSearchFilter();
5138 searchField.clear();
5139 if (Global.mimicEvernoteInterface) {
5140 notebookTree.selectGuid("");
5142 notebookTreeSelection();
5143 refreshEvernoteNote(true);
5146 @SuppressWarnings("unused")
5147 private void mergeNotes() {
5148 logger.log(logger.HIGH, "Merging notes");
5151 String masterGuid = null;
5152 List<String> sources = new ArrayList<String>();
5154 for (int i=0; i<noteTableView.selectionModel().selectedRows().size(); i++) {
5155 int r = noteTableView.selectionModel().selectedRows().get(i).row();
5156 index = noteTableView.proxyModel.index(r, Global.noteTableGuidPosition);
5157 SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
5159 masterGuid = (String)ix.values().toArray()[0];
5161 sources.add((String)ix.values().toArray()[0]);
5164 logger.log(logger.EXTREME, "Master guid=" +masterGuid);
5165 logger.log(logger.EXTREME, "Children count: "+sources.size());
5166 mergeNoteContents(masterGuid, sources);
5167 currentNoteGuid = masterGuid;
5168 noteIndexUpdated(false);
5169 refreshEvernoteNote(true);
5172 private void mergeNoteContents(String targetGuid, List<String> sources) {
5173 Note target = conn.getNoteTable().getNote(targetGuid, true, false, false, false, false);
5174 String newContent = target.getContent();
5175 newContent = newContent.replace("</en-note>", "<br></br>");
5177 for (int i=0; i<sources.size(); i++) {
5178 Note source = conn.getNoteTable().getNote(sources.get(i), true, true, false, false, false);
5179 if (source.isSetTitle()) {
5180 newContent = newContent +("<table bgcolor=\"lightgrey\"><tr><td><font size=\"6\"><b>" +source.getTitle() +"</b></font></td></tr></table>");
5182 String sourceContent = source.getContent();
5183 logger.log(logger.EXTREME, "Merging contents into note");
5184 logger.log(logger.EXTREME, sourceContent);
5185 logger.log(logger.EXTREME, "End of content");
5186 int startOfNote = sourceContent.indexOf("<en-note>");
5187 sourceContent = sourceContent.substring(startOfNote+9);
5188 int endOfNote = sourceContent.indexOf("</en-note>");
5189 sourceContent = sourceContent.substring(0,endOfNote);
5190 newContent = newContent + sourceContent;
5191 logger.log(logger.EXTREME, "New note content");
5192 logger.log(logger.EXTREME, newContent);
5193 logger.log(logger.EXTREME, "End of content");
5194 for (int j=0; j<source.getResourcesSize(); j++) {
5195 logger.log(logger.EXTREME, "Reassigning resource: "+source.getResources().get(j).getGuid());
5196 Resource r = source.getResources().get(j);
5197 Resource newRes = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), true);
5199 Calendar currentTime = new GregorianCalendar();
5200 Long l = new Long(currentTime.getTimeInMillis());
5204 while (l == prevGuid) {
5205 currentTime = new GregorianCalendar();
5206 l = new Long(currentTime.getTimeInMillis());
5208 String newResGuid = new String(Long.toString(l));
5209 newRes.setNoteGuid(targetGuid);
5210 newRes.setGuid(newResGuid);
5211 newRes.setUpdateSequenceNum(0);
5212 newRes.setActive(true);
5213 conn.getNoteTable().noteResourceTable.saveNoteResource(newRes, true);
5216 logger.log(logger.EXTREME, "Updating note");
5217 conn.getNoteTable().updateNoteContent(targetGuid, newContent +"</en-note>");
5218 for (int i=0; i<sources.size(); i++) {
5219 logger.log(logger.EXTREME, "Deleting note " +sources.get(i));
5220 listManager.deleteNote(sources.get(i));
5222 logger.log(logger.EXTREME, "Exiting merge note");
5224 // A resource within a note has had a guid change
5225 @SuppressWarnings("unused")
5226 private void noteResourceGuidChanged(String noteGuid, String oldGuid, String newGuid) {
5227 if (oldGuid != null && !oldGuid.equals(newGuid))
5228 Global.resourceMap.put(oldGuid, newGuid);
5230 // View a thumbnail of the note
5231 public void thumbnailView() {
5233 String thumbnailName = Global.getFileManager().getResDirPath("thumbnail-" + currentNoteGuid + ".png");
5234 QFile thumbnail = new QFile(thumbnailName);
5235 if (!thumbnail.exists()) {
5237 QImage img = new QImage();
5238 img.loadFromData(conn.getNoteTable().getThumbnail(currentNoteGuid));
5239 thumbnailViewer.setThumbnail(img);
5241 thumbnailViewer.setThumbnail(thumbnailName);
5242 if (!thumbnailViewer.isVisible())
5243 thumbnailViewer.showFullScreen();
5245 // An error happened while saving a note. Inform the user
5246 @SuppressWarnings("unused")
5247 private void saveRunnerError(String guid, String msg) {
5249 String title = "*Unknown*";
5250 for (int i=0; i<listManager.getMasterNoteIndex().size(); i++) {
5251 if (listManager.getMasterNoteIndex().get(i).getGuid().equals(guid)) {
5252 title = listManager.getMasterNoteIndex().get(i).getTitle();
5253 i=listManager.getMasterNoteIndex().size();
5256 msg = tr("An error has happened while saving the note \"") +title+
5257 tr("\".\n\nThis is probably due to a document that is too complex for NixNote to process. "+
5258 "As a result, changes to the note may not be saved properly in the database."+
5259 "\n\nA cached copy is being preserved so you can recover any data, but data may" +
5260 "\nbe lost. Please review the note to recover any critical data before restarting.");
5262 QMessageBox.information(this, tr("Error Saving Note"), tr(msg));
5265 private void thumbnailHTMLReady(String guid, QByteArray html, Integer zoom) {
5266 logger.log(logger.HIGH, "Entering thumnailHTMLReady()");
5267 logger.log(logger.HIGH, "Thumbnail ready for " +guid);
5268 // Find an idle preview object
5269 for (int i=0; i<thumbGenerators.size(); i++) {
5270 if (thumbGenerators.get(i).mutex.tryLock()) {
5271 logger.log(logger.EXTREME, "Idle generator found - loading thumbnail for " +guid);
5272 thumbGenerators.get(i).loadContent(guid, html, zoom);
5276 if (thumbGenerators.size() >= 1) {
5277 logger.log(logger.EXTREME, "No available thumbnail generators. Aborting " +guid);
5281 logger.log(logger.EXTREME, "Creating new thumbnail generator " +guid);
5282 Thumbnailer preview = new Thumbnailer(logger, conn, listManager, thumbnailRunner);
5283 thumbGenerators.add(preview);
5285 if (preview.mutex.tryLock()) {
5286 logger.log(logger.EXTREME, "Loading thumbnail for " +guid);
5287 preview.loadContent(guid, html, zoom);
5289 logger.log(logger.HIGH, "Exiting thumnailHTMLReady()");
5294 //**********************************************************
5295 //**********************************************************
5296 //* Online user actions
5297 //**********************************************************
5298 //**********************************************************
5299 private void setupOnlineMenu() {
5300 if (!Global.isConnected) {
5301 menuBar.noteOnlineHistoryAction.setEnabled(false);
5302 menuBar.selectiveSyncAction.setEnabled(false);
5305 menuBar.noteOnlineHistoryAction.setEnabled(true);
5306 menuBar.selectiveSyncAction.setEnabled(true);
5309 @SuppressWarnings("unused")
5310 private void viewNoteHistory() {
5311 if (currentNoteGuid == null || currentNoteGuid.equals(""))
5313 if (currentNote.getUpdateSequenceNum() == 0) {
5314 setMessage(tr("Note has never been synchronized."));
5315 QMessageBox.information(this, tr("Error"), tr("This note has never been sent to Evernote, so there is no history."));
5319 setMessage(tr("Getting Note History"));
5321 Note currentOnlineNote = null;
5324 if (Global.isPremium())
5325 versions = syncRunner.localNoteStore.listNoteVersions(syncRunner.authToken, currentNoteGuid);
5327 versions = new ArrayList<NoteVersionId>();
5328 currentOnlineNote = syncRunner.localNoteStore.getNote(syncRunner.authToken, currentNoteGuid, true, true, false, false);
5329 } catch (EDAMUserException e) {
5330 setMessage("EDAMUserException: " +e.getMessage());
5332 } catch (EDAMSystemException e) {
5333 setMessage("EDAMSystemException: " +e.getMessage());
5335 } catch (EDAMNotFoundException e) {
5336 setMessage(tr("Note not found on server."));
5337 QMessageBox.information(this, tr("Error"), tr("This note could not be found on Evernote's servers."));
5339 } catch (TException e) {
5340 setMessage("EDAMTransactionException: " +e.getMessage());
5344 // If we've gotten this far, we have a good note.
5345 if (historyWindow == null) {
5346 historyWindow = new OnlineNoteHistory(logger, conn);
5347 historyWindow.historyCombo.activated.connect(this, "reloadHistoryWindow(String)");
5348 historyWindow.restoreAsNew.clicked.connect(this, "restoreHistoryNoteAsNew()");
5349 historyWindow.restore.clicked.connect(this, "restoreHistoryNote()");
5351 historyWindow.historyCombo.clear();
5353 boolean isDirty = conn.getNoteTable().isNoteDirty(currentNoteGuid);
5354 if (currentNote.getUpdateSequenceNum() != currentOnlineNote.getUpdateSequenceNum())
5356 historyWindow.setCurrent(isDirty);
5358 loadHistoryWindowContent(currentOnlineNote);
5359 historyWindow.load(versions);
5360 setMessage(tr("History retrieved"));
5362 historyWindow.exec();
5364 private Note reloadHistoryWindow(String selection) {
5366 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
5367 String dateTimeFormat = new String(fmt);
5368 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
5372 for (int i=0; i<versions.size(); i++) {
5373 StringBuilder versionDate = new StringBuilder(simple.format(versions.get(i).getSaved()));
5374 if (versionDate.toString().equals(selection))
5378 if (index > -1 || selection.indexOf("Current") > -1) {
5379 Note historyNote = null;
5382 usn = versions.get(index).getUpdateSequenceNum();
5383 historyNote = syncRunner.localNoteStore.getNoteVersion(syncRunner.authToken, currentNoteGuid, usn, true, true, true);
5385 historyNote = syncRunner.localNoteStore.getNote(syncRunner.authToken, currentNoteGuid, true,true,true,true);
5386 } catch (EDAMUserException e) {
5387 setMessage("EDAMUserException: " +e.getMessage());
5390 } catch (EDAMSystemException e) {
5391 setMessage("EDAMSystemException: " +e.getMessage());
5394 } catch (EDAMNotFoundException e) {
5395 setMessage("EDAMNotFoundException: " +e.getMessage());
5398 } catch (TException e) {
5399 setMessage("EDAMTransactionException: " +e.getMessage());
5405 if (historyNote != null)
5406 historyWindow.setContent(historyNote);
5412 private void loadHistoryWindowContent(Note note) {
5413 note.setUpdateSequenceNum(0);
5414 historyWindow.setContent(note);
5416 @SuppressWarnings("unused")
5417 private void restoreHistoryNoteAsNew() {
5418 setMessage(tr("Restoring as new note."));
5419 duplicateNote(reloadHistoryWindow(historyWindow.historyCombo.currentText()));
5420 setMessage(tr("Note has been restored as a new note."));
5422 @SuppressWarnings("unused")
5423 private void restoreHistoryNote() {
5424 setMessage(tr("Restoring note."));
5425 Note n = reloadHistoryWindow(historyWindow.historyCombo.currentText());
5426 conn.getNoteTable().expungeNote(n.getGuid(), true, false);
5429 for (int i=0; i<n.getResourcesSize(); i++) {
5430 n.getResources().get(i).setActive(true);
5431 conn.getNoteTable().noteResourceTable.saveNoteResource(n.getResources().get(i), true);
5433 NoteMetadata metadata = new NoteMetadata();
5434 metadata.setGuid(n.getGuid());
5435 listManager.addNote(n, metadata);
5436 conn.getNoteTable().addNote(n, true);
5437 refreshEvernoteNote(true);
5438 setMessage(tr("Note has been restored."));
5440 @SuppressWarnings("unused")
5441 private void setupSelectiveSync() {
5443 // Get a list of valid notebooks
5444 List<Notebook> notebooks = null;
5445 List<Tag> tags = null;
5446 List<LinkedNotebook> linkedNotebooks = null;
5448 notebooks = syncRunner.localNoteStore.listNotebooks(syncRunner.authToken);
5449 tags = syncRunner.localNoteStore.listTags(syncRunner.authToken);
5450 linkedNotebooks = syncRunner.localNoteStore.listLinkedNotebooks(syncRunner.authToken);
5451 } catch (EDAMUserException e) {
5452 setMessage("EDAMUserException: " +e.getMessage());
5454 } catch (EDAMSystemException e) {
5455 setMessage("EDAMSystemException: " +e.getMessage());
5457 } catch (TException e) {
5458 setMessage("EDAMTransactionException: " +e.getMessage());
5460 } catch (EDAMNotFoundException e) {
5461 setMessage("EDAMNotFoundException: " +e.getMessage());
5465 // Split up notebooks into synchronized & non-synchronized
5466 List<Notebook> ignoredBooks = new ArrayList<Notebook>();
5467 List<String> dbIgnoredNotebooks = conn.getSyncTable().getIgnoreRecords("NOTEBOOK");
5469 for (int i=notebooks.size()-1; i>=0; i--) {
5470 for (int j=0; j<dbIgnoredNotebooks.size(); j++) {
5471 if (notebooks.get(i).getGuid().equalsIgnoreCase(dbIgnoredNotebooks.get(j))) {
5472 ignoredBooks.add(notebooks.get(i));
5473 j=dbIgnoredNotebooks.size();
5478 // split up tags into synchronized & non-synchronized
5479 List<Tag> ignoredTags = new ArrayList<Tag>();
5480 List<String> dbIgnoredTags = conn.getSyncTable().getIgnoreRecords("TAG");
5482 for (int i=tags.size()-1; i>=0; i--) {
5483 for (int j=0; j<dbIgnoredTags.size(); j++) {
5484 if (tags.get(i).getGuid().equalsIgnoreCase(dbIgnoredTags.get(j))) {
5485 ignoredTags.add(tags.get(i));
5486 j=dbIgnoredTags.size();
5491 // split up linked notebooks into synchronized & non-synchronized
5492 List<LinkedNotebook> ignoredLinkedNotebooks = new ArrayList<LinkedNotebook>();
5493 List<String> dbIgnoredLinkedNotebooks = conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK");
5494 for (int i=linkedNotebooks.size()-1; i>=0; i--) {
5495 String notebookGuid = linkedNotebooks.get(i).getGuid();
5496 for (int j=0; j<dbIgnoredLinkedNotebooks.size(); j++) {
5497 if (notebookGuid.equalsIgnoreCase(dbIgnoredLinkedNotebooks.get(j))) {
5498 ignoredLinkedNotebooks.add(linkedNotebooks.get(i));
5499 j=dbIgnoredLinkedNotebooks.size();
5504 IgnoreSync ignore = new IgnoreSync(notebooks, ignoredBooks, tags, ignoredTags, linkedNotebooks, ignoredLinkedNotebooks);
5506 if (!ignore.okClicked())
5511 // Clear out old notebooks & add the new ones
5512 List<String> oldIgnoreNotebooks = conn.getSyncTable().getIgnoreRecords("NOTEBOOK");
5513 for (int i=0; i<oldIgnoreNotebooks.size(); i++) {
5514 conn.getSyncTable().deleteRecord("IGNORENOTEBOOK-"+oldIgnoreNotebooks.get(i));
5517 List<String> newNotebooks = new ArrayList<String>();
5518 for (int i=ignore.getIgnoredBookList().count()-1; i>=0; i--) {
5519 String text = ignore.getIgnoredBookList().takeItem(i).text();
5520 for (int j=0; j<notebooks.size(); j++) {
5521 if (notebooks.get(j).getName().equalsIgnoreCase(text)) {
5522 Notebook n = notebooks.get(j);
5523 conn.getSyncTable().addRecord("IGNORENOTEBOOK-"+n.getGuid(), n.getGuid());
5525 newNotebooks.add(n.getGuid());
5530 // Clear out old tags & add new ones
5531 List<String> oldIgnoreTags = conn.getSyncTable().getIgnoreRecords("TAG");
5532 for (int i=0; i<oldIgnoreTags.size(); i++) {
5533 conn.getSyncTable().deleteRecord("IGNORETAG-"+oldIgnoreTags.get(i));
5536 List<String> newTags = new ArrayList<String>();
5537 for (int i=ignore.getIgnoredTagList().count()-1; i>=0; i--) {
5538 String text = ignore.getIgnoredTagList().takeItem(i).text();
5539 for (int j=0; j<tags.size(); j++) {
5540 if (tags.get(j).getName().equalsIgnoreCase(text)) {
5541 Tag t = tags.get(j);
5542 conn.getSyncTable().addRecord("IGNORETAG-"+t.getGuid(), t.getGuid());
5543 newTags.add(t.getGuid());
5549 // Clear out old tags & add new ones
5550 List<String> oldIgnoreLinkedNotebooks = conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK");
5551 for (int i=0; i<oldIgnoreLinkedNotebooks.size(); i++) {
5552 conn.getSyncTable().deleteRecord("IGNORELINKEDNOTEBOOK-"+oldIgnoreLinkedNotebooks.get(i));
5555 List<String> newLinked = new ArrayList<String>();
5556 for (int i=ignore.getIgnoredLinkedNotebookList().count()-1; i>=0; i--) {
5557 String text = ignore.getIgnoredLinkedNotebookList().takeItem(i).text();
5558 for (int j=0; j<linkedNotebooks.size(); j++) {
5559 if (linkedNotebooks.get(j).getShareName().equalsIgnoreCase(text)) {
5560 LinkedNotebook t = linkedNotebooks.get(j);
5561 conn.getSyncTable().addRecord("IGNORELINKEDNOTEBOOK-"+t.getGuid(), t.getGuid());
5562 newLinked.add(t.getGuid());
5563 j=linkedNotebooks.size();
5568 conn.getNoteTable().expungeIgnoreSynchronizedNotes(newNotebooks, newTags, newLinked);
5574 //**********************************************************
5575 //**********************************************************
5576 //* XML Modifying methods
5577 //**********************************************************
5578 //**********************************************************
5579 // An error has happended fetching a resource. let the user know
5580 private void resourceErrorMessage() {
5584 QMessageBox.information(this, tr("DOUGH!!!"), tr("Well, this is embarrassing."+
5585 "\n\nSome attachments or images for this note appear to be missing from my database.\n"+
5586 "In a perfect world this wouldn't happen, but it has.\n" +
5587 "It is embarasing when a program like me, designed to save all your\n"+
5588 "precious data, has a problem finding data.\n\n" +
5589 "I guess life isn't fair, but I'll survive. Somehow...\n\n" +
5590 "In the mean time, I'm not going to let you make changes to this note.\n" +
5591 "Don't get angry. I'm doing it to prevent you from messing up\n"+
5592 "this note on the Evernote servers. Sorry."+
5593 "\n\nP.S. You might want to re-synchronize to see if it corrects this problem.\nWho knows, you might get lucky."));
5595 browserWindow.setReadOnly(true);
5602 //**********************************************************
5603 //**********************************************************
5605 //**********************************************************
5606 //**********************************************************
5607 // We should now do a sync with Evernote
5608 private void syncTimer() {
5609 logger.log(logger.EXTREME, "Entering NeverNote.syncTimer()");
5610 syncRunner.syncNeeded = true;
5611 syncRunner.disableUploads = Global.disableUploads;
5613 logger.log(logger.EXTREME, "Leaving NeverNote.syncTimer()");
5615 private void syncStart() {
5616 logger.log(logger.EXTREME, "Entering NeverNote.syncStart()");
5618 if (!syncRunning && Global.isConnected) {
5619 syncRunner.setConnected(true);
5620 syncRunner.setKeepRunning(Global.keepRunning);
5621 syncRunner.syncDeletedContent = Global.synchronizeDeletedContent();
5623 if (syncThreadsReady > 0) {
5624 thumbnailRunner.interrupt = true;
5625 saveNoteIndexWidth();
5626 saveNoteColumnPositions();
5627 if (syncRunner.addWork("SYNC")) {
5629 syncRunner.syncNeeded = true;
5634 logger.log(logger.EXTREME, "Leaving NeverNote.syncStart");
5636 @SuppressWarnings("unused")
5637 private void syncThreadComplete(Boolean refreshNeeded) {
5638 setMessage(tr("Finalizing Synchronization"));
5640 syncRunning = false;
5641 syncRunner.syncNeeded = false;
5642 synchronizeAnimationTimer.stop();
5643 synchronizeButton.setIcon(new QIcon(iconPath+"synchronize.png"));
5645 if (currentNote == null) {
5646 currentNote = conn.getNoteTable().getNote(currentNoteGuid, false, false, false, false, true);
5648 listManager.refreshNoteMetadata();
5649 noteIndexUpdated(true);
5650 noteTableView.selectionModel().blockSignals(true);
5651 scrollToGuid(currentNoteGuid);
5652 noteTableView.selectionModel().blockSignals(false);
5653 refreshEvernoteNote(false);
5654 scrollToGuid(currentNoteGuid);
5657 // Check to see if there were any shared notebook errors
5658 if (syncRunner.error && syncRunner.errorSharedNotebooks.size() > 0) {
5659 String guid = syncRunner.errorSharedNotebooks.get(0);
5660 String notebookGuid = conn.getLinkedNotebookTable().getLocalNotebookGuid(guid);
5661 String localName = listManager.getNotebookNameByGuid(notebookGuid);
5662 SharedNotebookSyncError syncDialog = new SharedNotebookSyncError(localName);
5664 if (syncDialog.okPressed()) {
5665 if (syncDialog.doNothing.isChecked()) {
5666 syncRunner.errorSharedNotebooksIgnored.put(guid, guid);
5669 if (syncDialog.deleteNotebook.isChecked()) {
5670 conn.getNoteTable().expungeNotesByNotebook(notebookGuid, true, false);
5671 conn.getNotebookTable().expungeNotebook(notebookGuid, false);
5672 conn.getLinkedNotebookTable().expungeNotebook(guid, false);
5673 conn.getLinkedNotebookTable().expungeNotebook(guid, false);
5681 // Finalize the synchronization
5682 if (!syncRunner.error)
5683 setMessage(tr("Synchronization Complete"));
5685 setMessage(tr("Synchronization completed with errors. Please check the log for details."));
5686 logger.log(logger.MEDIUM, "Sync complete.");
5688 public void saveUploadAmount(long t) {
5689 Global.saveUploadAmount(t);
5691 public void saveUserInformation(User user) {
5692 Global.saveUserInformation(user);
5694 public void saveEvernoteUpdateCount(int i) {
5695 Global.saveEvernoteUpdateCount(i);
5697 public void refreshLists() {
5698 logger.log(logger.EXTREME, "Entering NeverNote.refreshLists");
5700 listManager.refreshLists(currentNote, noteDirty, browserWindow.getContent());
5701 tagIndexUpdated(true);
5702 notebookIndexUpdated();
5703 savedSearchIndexUpdated();
5704 listManager.loadNotesIndex();
5706 noteTableView.selectionModel().blockSignals(true);
5707 noteIndexUpdated(true);
5708 noteTableView.selectionModel().blockSignals(false);
5709 logger.log(logger.EXTREME, "Leaving NeverNote.refreshLists");
5713 @SuppressWarnings("unused")
5714 private void authTimer() {
5715 Calendar cal = Calendar.getInstance();
5717 // If we are not connected let's get out of here
5718 if (!Global.isConnected)
5721 // If this is the first time through, then we need to set this
5722 // if (syncRunner.authRefreshTime == 0 || cal.getTimeInMillis() > syncRunner.authRefreshTime)
5723 // syncRunner.authRefreshTime = cal.getTimeInMillis();
5725 // long now = new Date().getTime();
5726 // if (now > Global.authRefreshTime && Global.isConnected) {
5727 syncRunner.authRefreshNeeded = true;
5731 @SuppressWarnings("unused")
5732 private void authRefreshComplete(boolean goodSync) {
5733 logger.log(logger.EXTREME, "Entering NeverNote.authRefreshComplete");
5734 Global.isConnected = syncRunner.isConnected;
5736 // authTimer.start((int)syncRunner.authTimeRemaining/4);
5737 authTimer.start(1000*60*15);
5738 logger.log(logger.LOW, "Authentication token has been renewed");
5739 // setMessage("Authentication token has been renewed.");
5741 authTimer.start(1000*60*5);
5742 logger.log(logger.LOW, "Authentication token renew has failed - retry in 5 minutes.");
5743 // setMessage("Authentication token renew has failed - retry in 5 minutes.");
5745 logger.log(logger.EXTREME, "Leaving NeverNote.authRefreshComplete");
5749 @SuppressWarnings("unused")
5750 private synchronized void indexTimer() {
5751 logger.log(logger.EXTREME, "Index timer activated. Sync running="+syncRunning);
5754 if (!indexDisabled && indexRunner.idle) {
5755 thumbnailRunner.interrupt = true;
5756 indexRunner.addWork("SCAN");
5758 logger.log(logger.EXTREME, "Leaving NixNote index timer");
5761 @SuppressWarnings("unused")
5762 private void indexStarted() {
5763 setMessage(tr("Indexing notes"));
5765 @SuppressWarnings("unused")
5766 private void indexComplete() {
5767 setMessage(tr("Index complete"));
5769 @SuppressWarnings("unused")
5770 private synchronized void toggleNoteIndexing() {
5771 logger.log(logger.HIGH, "Entering NeverNote.toggleIndexing");
5772 indexDisabled = !indexDisabled;
5774 setMessage(tr("Indexing is now enabled."));
5776 setMessage(tr("Indexing is now disabled."));
5777 menuBar.disableIndexing.setChecked(indexDisabled);
5778 logger.log(logger.HIGH, "Leaving NeverNote.toggleIndexing");
5781 @SuppressWarnings("unused")
5782 private void threadMonitorCheck() {
5787 alive = listManager.threadCheck(Global.tagCounterThreadId);
5790 if (tagDeadCount > MAX && !disableTagThreadCheck) {
5791 QMessageBox.information(this, tr("A thread has died."), tr("It appears as the tag counter thread has died. I recommend "+
5792 "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry."));
5793 disableTagThreadCheck = true;
5798 alive = listManager.threadCheck(Global.notebookCounterThreadId);
5800 notebookThreadDeadCount++;
5801 if (notebookThreadDeadCount > MAX && !disableNotebookThreadCheck) {
5802 QMessageBox.information(this, tr("A thread has died."), tr("It appears as the notebook counter thread has died. I recommend "+
5803 "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry."));
5804 disableNotebookThreadCheck=true;
5807 notebookThreadDeadCount=0;
5809 alive = listManager.threadCheck(Global.trashCounterThreadId);
5812 if (trashDeadCount > MAX && !disableTrashThreadCheck) {
5813 QMessageBox.information(this, tr("A thread has died."), ("It appears as the trash counter thread has died. I recommend "+
5814 "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry."));
5815 disableTrashThreadCheck = true;
5820 alive = listManager.threadCheck(Global.saveThreadId);
5822 saveThreadDeadCount++;
5823 if (saveThreadDeadCount > MAX && !disableSaveThreadCheck) {
5824 QMessageBox.information(this, tr("A thread has died."), tr("It appears as the note saver thread has died. I recommend "+
5825 "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry."));
5826 disableSaveThreadCheck = true;
5829 saveThreadDeadCount=0;
5831 if (!syncThread.isAlive()) {
5832 syncThreadDeadCount++;
5833 if (syncThreadDeadCount > MAX && !disableSyncThreadCheck) {
5834 QMessageBox.information(this, tr("A thread has died."), tr("It appears as the synchronization thread has died. I recommend "+
5835 "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry."));
5836 disableSyncThreadCheck = true;
5839 syncThreadDeadCount=0;
5841 if (!indexThread.isAlive()) {
5842 indexThreadDeadCount++;
5843 if (indexThreadDeadCount > MAX && !disableIndexThreadCheck) {
5844 QMessageBox.information(this, tr("A thread has died."), tr("It appears as the index thread has died. I recommend "+
5845 "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry."));
5846 disableIndexThreadCheck = true;
5849 indexThreadDeadCount=0;
5854 private void thumbnailTimer() {
5855 if (Global.enableThumbnails() && !syncRunning && indexRunner.idle) {
5856 thumbnailRunner.addWork("SCAN");
5860 //**************************************************
5861 //* Backup & Restore
5862 //**************************************************
5863 @SuppressWarnings("unused")
5864 private void databaseBackup() {
5865 QFileDialog fd = new QFileDialog(this);
5866 fd.setFileMode(FileMode.AnyFile);
5867 fd.setConfirmOverwrite(true);
5868 fd.setWindowTitle(tr("Backup Database"));
5869 fd.setFilter(tr("NixNote Export (*.nnex);;All Files (*.*)"));
5870 fd.setAcceptMode(AcceptMode.AcceptSave);
5871 if (saveLastPath == null || saveLastPath.equals(""))
5872 fd.setDirectory(System.getProperty("user.home"));
5874 fd.setDirectory(saveLastPath);
5875 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
5881 saveLastPath = fd.selectedFiles().get(0);
5882 saveLastPath = saveLastPath.substring(0,saveLastPath.lastIndexOf("/"));
5883 setMessage(tr("Backing up database"));
5885 // conn.backupDatabase(Global.getUpdateSequenceNumber(), Global.getSequenceDate());
5887 ExportData noteWriter = new ExportData(conn, true);
5888 String fileName = fd.selectedFiles().get(0);
5890 if (!fileName.endsWith(".nnex"))
5891 fileName = fileName +".nnex";
5892 noteWriter.exportData(fileName);
5893 setMessage(tr("Database backup completed."));
5898 @SuppressWarnings("unused")
5899 private void databaseRestore() {
5900 if (QMessageBox.question(this, tr("Confirmation"),
5901 tr("This is used to restore a database from backups.\n" +
5902 "It is HIGHLY recommened that this only be used to populate\n" +
5903 "an empty database. Restoring into a database that\n already has data" +
5904 " can cause problems.\n\nAre you sure you want to continue?"),
5905 QMessageBox.StandardButton.Yes,
5906 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
5911 QFileDialog fd = new QFileDialog(this);
5912 fd.setFileMode(FileMode.ExistingFile);
5913 fd.setConfirmOverwrite(true);
5914 fd.setWindowTitle(tr("Restore Database"));
5915 fd.setFilter(tr("NixNote Export (*.nnex);;All Files (*.*)"));
5916 fd.setAcceptMode(AcceptMode.AcceptOpen);
5917 if (saveLastPath == null || saveLastPath.equals(""))
5918 fd.setDirectory(System.getProperty("user.home"));
5920 fd.setDirectory(saveLastPath);
5921 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
5927 saveLastPath = fd.selectedFiles().get(0);
5928 saveLastPath = saveLastPath.substring(0,saveLastPath.lastIndexOf("/"));
5930 setMessage(tr("Restoring database"));
5931 ImportData noteReader = new ImportData(conn, true);
5932 noteReader.importData(fd.selectedFiles().get(0));
5934 if (noteReader.lastError != 0) {
5935 setMessage(noteReader.getErrorMessage());
5936 logger.log(logger.LOW, "Restore problem: " +noteReader.lastError);
5941 listManager.loadNoteTitleColors();
5943 refreshEvernoteNote(true);
5944 setMessage(tr("Database has been restored."));
5947 @SuppressWarnings("unused")
5948 private void exportNotes() {
5949 QFileDialog fd = new QFileDialog(this);
5950 fd.setFileMode(FileMode.AnyFile);
5951 fd.setConfirmOverwrite(true);
5952 fd.setWindowTitle(tr("Backup Database"));
5953 fd.setFilter(tr("NixNote Export (*.nnex);;All Files (*.*)"));
5954 fd.setAcceptMode(AcceptMode.AcceptSave);
5955 fd.setDirectory(System.getProperty("user.home"));
5956 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
5962 setMessage(tr("Exporting Notes"));
5965 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals(""))
5966 selectedNoteGUIDs.add(currentNoteGuid);
5968 ExportData noteWriter = new ExportData(conn, false, selectedNoteGUIDs);
5969 String fileName = fd.selectedFiles().get(0);
5971 if (!fileName.endsWith(".nnex"))
5972 fileName = fileName +".nnex";
5973 noteWriter.exportData(fileName);
5974 setMessage(tr("Export completed."));
5980 @SuppressWarnings("unused")
5981 private void importNotes() {
5982 QFileDialog fd = new QFileDialog(this);
5983 fd.setFileMode(FileMode.ExistingFile);
5984 fd.setConfirmOverwrite(true);
5985 fd.setWindowTitle(tr("Import Notes"));
5986 fd.setFilter(tr("NixNote Export (*.nnex);;Evernote Export (*.enex);;All Files (*.*)"));
5987 fd.setAcceptMode(AcceptMode.AcceptOpen);
5988 if (saveLastPath == null || saveLastPath.equals(""))
5989 fd.setDirectory(System.getProperty("user.home"));
5991 fd.setDirectory(saveLastPath);
5992 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
5998 setMessage(tr("Importing Notes"));
6001 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals(""))
6002 selectedNoteGUIDs.add(currentNoteGuid);
6004 String fileName = fd.selectedFiles().get(0);
6005 // saveLastPath.substring(0,fileName.lastIndexOf("/"));
6007 if (fileName.endsWith(".nnex")) {
6008 ImportData noteReader = new ImportData(conn, false);
6009 if (selectedNotebookGUIDs != null && selectedNotebookGUIDs.size() > 0)
6010 noteReader.setNotebookGuid(selectedNotebookGUIDs.get(0));
6012 noteReader.setNotebookGuid(listManager.getNotebookIndex().get(0).getGuid());
6014 noteReader.importData(fileName);
6016 if (noteReader.lastError != 0) {
6017 setMessage(noteReader.getErrorMessage());
6018 logger.log(logger.LOW, "Import problem: " +noteReader.lastError);
6023 if (fileName.endsWith(".enex")) {
6024 ImportEnex noteReader = new ImportEnex(conn, false);
6025 if (selectedNotebookGUIDs != null && selectedNotebookGUIDs.size() > 0)
6026 noteReader.setNotebookGuid(selectedNotebookGUIDs.get(0));
6028 noteReader.setNotebookGuid(listManager.getNotebookIndex().get(0).getGuid());
6031 if (QMessageBox.question(this, tr("Confirmation"),
6032 tr("Create new tags from import?"),
6033 QMessageBox.StandardButton.Yes,
6034 QMessageBox.StandardButton.No) == StandardButton.Yes.value()) {
6035 noteReader.createNewTags = true;
6037 noteReader.createNewTags = false;
6039 noteReader.importData(fileName);
6041 if (noteReader.lastError != 0) {
6042 setMessage(noteReader.getErrorMessage());
6043 logger.log(logger.LOW, "Import problem: " +noteReader.lastError);
6050 listManager.loadNoteTitleColors();
6052 refreshEvernoteNote(false);
6053 setMessage(tr("Notes have been imported."));
6056 setMessage(tr("Import completed."));
6063 //**************************************************
6064 //* Duplicate a note
6065 //**************************************************
6066 @SuppressWarnings("unused")
6067 private void duplicateNote() {
6069 duplicateNote(currentNoteGuid);
6072 //**************************************************
6073 //* Action from when a user clicks Copy As URL
6074 //**************************************************
6075 @SuppressWarnings("unused")
6076 private void copyAsUrlClicked() {
6077 QClipboard clipboard = QApplication.clipboard();
6078 QMimeData mime = new QMimeData();
6080 mime.setText(currentNoteGuid);
6081 List<QUrl> urls = new ArrayList<QUrl>();
6083 // Start building the URL
6084 User user = Global.getUserInformation();
6086 // Check that we have everything we need
6087 if ((user.getShardId().equals("") || user.getId() == 0) && !Global.bypassSynchronizationWarning()) {
6088 SynchronizationRequiredWarning warning = new SynchronizationRequiredWarning(this);
6090 if (!warning.neverSynchronize())
6093 Global.setBypassSynchronizationWarning(true);
6094 user.setShardId("s0");
6100 // Start building a list of URLs based upon the selected notes
6101 noteTableView.showColumn(Global.noteTableGuidPosition);
6103 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
6104 if (!Global.isColumnVisible("guid"))
6105 noteTableView.hideColumn(Global.noteTableGuidPosition);
6107 // Check that the note is either synchronized, or in a local notebook
6108 for (int i=0; i<selections.size(); i++) {
6110 int row = selections.get(i).row();
6111 index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
6112 SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
6113 String selectedGuid = (String)ix.values().toArray()[0];
6115 Note n = conn.getNoteTable().getNote(selectedGuid, false, false, false, false, false);
6116 if (n.getUpdateSequenceNum() == 0 && !conn.getNotebookTable().isNotebookLocal(n.getNotebookGuid())) {
6117 QMessageBox.critical(this, tr("Please Synchronize") ,tr("Please either synchronize or move any " +
6118 "new notes to a local notebook."));
6123 // Start building the URLs
6124 for (int i=0; i<selections.size(); i++) {
6126 int row = selections.get(i).row();
6127 index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
6128 SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
6129 String selectedGuid = (String)ix.values().toArray()[0];
6130 mime.setText(selectedGuid);
6134 Note selectedNote = conn.getNoteTable().getNote(selectedGuid, false, false, false, false, false);
6135 if (selectedNote.getUpdateSequenceNum() > 0) {
6139 gid = "00000000-0000-0000-0000-000000000000";
6142 url = new String("evernote://///view/") + new String(user.getId() + "/" +user.getShardId() +"/"
6144 urls.add(new QUrl(url));
6147 clipboard.setMimeData(mime);
6151 //**************************************************
6153 //**************************************************
6154 public void setupFolderImports() {
6155 List<WatchFolderRecord> records = conn.getWatchFolderTable().getAll();
6157 if (importKeepWatcher == null)
6158 importKeepWatcher = new QFileSystemWatcher();
6159 if (importDeleteWatcher == null) {
6160 importDeleteWatcher = new QFileSystemWatcher();
6161 for (int i=0; i<records.size(); i++) {
6162 if (!records.get(i).keep)
6163 folderImportDelete(records.get(i).folder);
6169 // importKeepWatcher.addPath(records.get(i).folder.replace('\\', '/'));
6170 for (int i=0; i<records.size(); i++) {
6171 logger.log(logger.LOW, "Adding file monitor: " +records.get(i).folder);
6172 if (records.get(i).keep)
6173 importKeepWatcher.addPath(records.get(i).folder);
6175 importDeleteWatcher.addPath(records.get(i).folder);
6178 logger.log(logger.EXTREME, "List of directories being watched (kept)...");
6179 List<String> monitorDelete = importKeepWatcher.directories();
6180 for (int i=0; i<monitorDelete.size(); i++) {
6181 logger.log(logger.EXTREME, monitorDelete.get(i));
6183 logger.log(logger.EXTREME, "<end of list>");
6184 logger.log(logger.EXTREME, "List of directories being watched (delete)...");
6185 monitorDelete = importDeleteWatcher.directories();
6186 for (int i=0; i<monitorDelete.size(); i++) {
6187 logger.log(logger.EXTREME, monitorDelete.get(i));
6189 logger.log(logger.EXTREME, "<end of list>");
6191 importKeepWatcher.directoryChanged.connect(this, "folderImportKeep(String)");
6192 importDeleteWatcher.directoryChanged.connect(this, "folderImportDelete(String)");
6194 // Look at the files already there so we don't import them again if a new file is created
6195 if (importedFiles == null) {
6196 importedFiles = new ArrayList<String>();
6197 for (int j=0; j<records.size(); j++) {
6198 QDir dir = new QDir(records.get(j).folder);
6199 List<QFileInfo> list = dir.entryInfoList();
6200 for (int k=0; k<list.size(); k++) {
6201 if (list.get(k).isFile())
6202 importedFiles.add(list.get(k).absoluteFilePath());
6208 // Menu folderImport action triggered
6209 public void folderImport() {
6210 List<WatchFolderRecord> recs = conn.getWatchFolderTable().getAll();
6211 WatchFolder dialog = new WatchFolder(recs, listManager.getNotebookIndex());
6213 if (!dialog.okClicked())
6216 // We have some sort of update.
6217 if (importKeepWatcher.directories().size() > 0)
6218 importKeepWatcher.removePaths(importKeepWatcher.directories());
6219 if (importDeleteWatcher.directories().size() > 0)
6220 importDeleteWatcher.removePaths(importDeleteWatcher.directories());
6222 conn.getWatchFolderTable().expungeAll();
6223 // Start building from the table
6224 for (int i=0; i<dialog.table.rowCount(); i++) {
6225 QTableWidgetItem item = dialog.table.item(i, 0);
6226 String dir = item.text();
6227 item = dialog.table.item(i, 1);
6228 String notebook = item.text();
6229 item = dialog.table.item(i, 2);
6231 if (item.text().equalsIgnoreCase("Keep"))
6236 String guid = conn.getNotebookTable().findNotebookByName(notebook);
6237 conn.getWatchFolderTable().addWatchFolder(dir, guid, keep, 0);
6239 setupFolderImports();
6243 public void folderImportKeep(String dirName) throws NoSuchAlgorithmException {
6244 logger.log(logger.LOW, "Inside folderImportKeep");
6245 String whichOS = System.getProperty("os.name");
6246 if (whichOS.contains("Windows"))
6247 dirName = dirName.replace('/','\\');
6249 FileImporter importer = new FileImporter(logger, conn);
6251 QDir dir = new QDir(dirName);
6252 List<QFileInfo> list = dir.entryInfoList();
6253 String notebook = conn.getWatchFolderTable().getNotebook(dirName);
6255 for (int i=0; i<list.size(); i++){
6256 logger.log(logger.LOW, "File found: " +list.get(i).fileName());
6257 boolean redundant = false;
6258 // Check if we've already imported this one or if it existed before
6259 for (int j=0; j<importedFiles.size(); j++) {
6260 logger.log(logger.LOW, "redundant file list: " +list.get(i).absoluteFilePath());
6261 if (importedFiles.get(j).equals(list.get(i).absoluteFilePath()))
6265 logger.log(logger.LOW, "Checking if redundant: " +redundant);
6267 importer.setFileInfo(list.get(i));
6268 importer.setFileName(list.get(i).absoluteFilePath());
6271 logger.log(logger.LOW, "File importing is a file: " +list.get(i).isFile());
6272 logger.log(logger.LOW, "File importing is a valid: " +importer.isValidType());
6273 if (list.get(i).isFile() && importer.isValidType()) {
6275 if (!importer.importFile()) {
6276 // If we can't get to the file, it is probably locked. We'll try again later.
6277 logger.log(logger.LOW, "Unable to save externally edited file. Saving for later.");
6278 importFilesKeep.add(list.get(i).absoluteFilePath());
6281 Note newNote = importer.getNote();
6282 newNote.setNotebookGuid(notebook);
6283 newNote.setTitle(dir.at(i));
6284 NoteMetadata metadata = new NoteMetadata();
6285 metadata.setDirty(true);
6286 metadata.setGuid(newNote.getGuid());
6287 listManager.addNote(newNote, metadata);
6288 conn.getNoteTable().addNote(newNote, true);
6289 noteTableView.insertRow(newNote, metadata, true, -1);
6290 listManager.updateNoteContent(newNote.getGuid(), importer.getNoteContent());
6291 listManager.countNotebookResults(listManager.getNoteIndex());
6292 importedFiles.add(list.get(i).absoluteFilePath());
6301 public void folderImportDelete(String dirName) {
6302 logger.log(logger.LOW, "Inside folderImportDelete");
6303 String whichOS = System.getProperty("os.name");
6304 if (whichOS.contains("Windows"))
6305 dirName = dirName.replace('/','\\');
6307 FileImporter importer = new FileImporter(logger, conn);
6308 QDir dir = new QDir(dirName);
6309 List<QFileInfo> list = dir.entryInfoList();
6310 String notebook = conn.getWatchFolderTable().getNotebook(dirName);
6312 for (int i=0; i<list.size(); i++){
6313 logger.log(logger.LOW, "File found: " +list.get(i).fileName());
6314 importer.setFileInfo(list.get(i));
6315 importer.setFileName(list.get(i).absoluteFilePath());
6317 logger.log(logger.LOW, "File importing is a file: " +list.get(i).isFile());
6318 logger.log(logger.LOW, "File importing is a valid: " +importer.isValidType());
6319 if (list.get(i).isFile() && importer.isValidType()) {
6321 if (!importer.importFile()) {
6322 // If we can't get to the file, it is probably locked. We'll try again later.
6323 logger.log(logger.LOW, "Unable to save externally edited file. Saving for later.");
6324 importFilesKeep.add(list.get(i).absoluteFilePath());
6327 Note newNote = importer.getNote();
6328 newNote.setNotebookGuid(notebook);
6329 newNote.setTitle(dir.at(i));
6330 NoteMetadata metadata = new NoteMetadata();
6331 metadata.setDirty(true);
6332 metadata.setGuid(newNote.getGuid());
6333 listManager.addNote(newNote, metadata);
6334 conn.getNoteTable().addNote(newNote, true);
6335 noteTableView.insertRow(newNote, metadata, true, -1);
6336 listManager.updateNoteContent(newNote.getGuid(), importer.getNoteContent());
6337 listManager.countNotebookResults(listManager.getNoteIndex());
6338 dir.remove(dir.at(i));
6345 //**************************************************
6347 //**************************************************
6348 private void externalFileEdited(String fileName) throws NoSuchAlgorithmException {
6349 logger.log(logger.HIGH, "Entering exernalFileEdited");
6351 // Strip URL prefix and base dir path
6352 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
6353 String name = fileName.replace(dPath, "");
6354 int pos = name.lastIndexOf('.');
6357 guid = guid.substring(0,pos);
6359 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
6361 guid = name.substring(0, pos);
6364 QFile file = new QFile(fileName);
6365 if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly))) {
6366 // If we can't get to the file, it is probably locked. We'll try again later.
6367 logger.log(logger.LOW, "Unable to save externally edited file. Saving for later.");
6368 externalFiles.add(fileName);
6371 QByteArray binData = file.readAll();
6373 if (binData.size() == 0) {
6374 // If we can't get to the file, it is probably locked. We'll try again later.
6375 logger.log(logger.LOW, "Unable to save externally edited file. Saving for later.");
6376 externalFiles.add(fileName);
6380 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
6382 r = conn.getNoteTable().noteResourceTable.getNoteResource(Global.resourceMap.get(guid), true);
6383 if (r == null || r.getData() == null || r.getData().getBody() == null)
6385 String oldHash = Global.byteArrayToHexString(r.getData().getBodyHash());
6386 MessageDigest md = MessageDigest.getInstance("MD5");
6387 md.update(binData.toByteArray());
6388 byte[] hash = md.digest();
6389 String newHash = Global.byteArrayToHexString(hash);
6390 if (r.getNoteGuid().equalsIgnoreCase(currentNoteGuid)) {
6391 updateResourceContentHash(browserWindow, r.getGuid(), oldHash, newHash);
6393 if (externalWindows.containsKey(r.getNoteGuid())) {
6394 updateResourceContentHash(externalWindows.get(r.getNoteGuid()).getBrowserWindow(),
6395 r.getGuid(), oldHash, newHash);
6397 conn.getNoteTable().updateResourceContentHash(r.getNoteGuid(), oldHash, newHash);
6398 Data data = r.getData();
6399 data.setBody(binData.toByteArray());
6400 data.setBodyHash(hash);
6401 logger.log(logger.LOW, "externalFileEdited: " +data.getSize() +" bytes");
6403 conn.getNoteTable().noteResourceTable.updateNoteResource(r,true);
6405 if (r.getNoteGuid().equals(currentNoteGuid)) {
6406 QWebSettings.setMaximumPagesInCache(0);
6407 QWebSettings.setObjectCacheCapacities(0, 0, 0);
6408 refreshEvernoteNote(true);
6409 browserWindow.getBrowser().triggerPageAction(WebAction.Reload);
6412 if (externalWindows.containsKey(r.getNoteGuid())) {
6413 QWebSettings.setMaximumPagesInCache(0);
6414 QWebSettings.setObjectCacheCapacities(0, 0, 0);
6415 externalWindows.get(r.getNoteGuid()).getBrowserWindow().getBrowser().triggerPageAction(WebAction.Reload);
6419 logger.log(logger.HIGH, "Exiting externalFielEdited");
6421 // This is a timer event that tries to save any external files that were edited. This
6422 // is only needed if we couldn't save a file earlier.
6423 public void externalFileEditedSaver() {
6424 for (int i=externalFiles.size()-1; i>=0; i--) {
6426 logger.log(logger.MEDIUM, "Trying to save " +externalFiles.get(i));
6427 externalFileEdited(externalFiles.get(i));
6428 externalFiles.remove(i);
6429 } catch (NoSuchAlgorithmException e) {e.printStackTrace();}
6431 for (int i=0; i<importFilesKeep.size(); i++) {
6433 logger.log(logger.MEDIUM, "Trying to save " +importFilesKeep.get(i));
6434 folderImportKeep(importFilesKeep.get(i));
6435 importFilesKeep.remove(i);
6436 } catch (NoSuchAlgorithmException e) {e.printStackTrace();}
6438 for (int i=0; i<importFilesDelete.size(); i++) {
6439 logger.log(logger.MEDIUM, "Trying to save " +importFilesDelete.get(i));
6440 folderImportDelete(importFilesDelete.get(i));
6441 importFilesDelete.remove(i);
6448 // If an attachment on the current note was edited, we need to update the current notes's hash
6449 // Update a note content's hash. This happens if a resource is edited outside of NN
6450 public void updateResourceContentHash(BrowserWindow browser, String guid, String oldHash, String newHash) {
6451 int position = browserWindow.getContent().indexOf("en-tag=\"en-media\" guid=\""+guid+"\" type=");
6453 for (;position>-1;) {
6454 endPos = browser.getContent().indexOf(">", position+1);
6455 String oldSegment = browser.getContent().substring(position,endPos);
6456 int hashPos = oldSegment.indexOf("hash=\"");
6457 int hashEnd = oldSegment.indexOf("\"", hashPos+7);
6458 String hash = oldSegment.substring(hashPos+6, hashEnd);
6459 if (hash.equalsIgnoreCase(oldHash)) {
6460 String newSegment = oldSegment.replace(oldHash, newHash);
6461 String content = browser.getContent().substring(0,position) +
6463 browser.getContent().substring(endPos);
6464 browser.setContent(new QByteArray(content));;
6467 position = browser.getContent().indexOf("en-tag=\"en-media\" guid=\""+guid+"\" type=", position+1);
6472 //*************************************************
6473 //* Minimize to tray
6474 //*************************************************
6476 public void changeEvent(QEvent e) {
6477 if (e.type() == QEvent.Type.WindowStateChange) {
6478 if (QSystemTrayIcon.isSystemTrayAvailable()) {
6479 if (isMinimized() && (Global.showTrayIcon() || Global.showTrayIcon())) {
6481 QTimer.singleShot(10, this, "hide()");
6485 windowMaximized = true;
6487 windowMaximized = false;
6492 //*************************************************
6493 //* Check database userid & passwords
6494 //*************************************************
6495 private static boolean databaseCheck(String url,String userid, String userPassword, String cypherPassword) {
6496 Connection connection;
6499 Class.forName("org.h2.Driver");
6500 } catch (ClassNotFoundException e1) {
6501 e1.printStackTrace();
6506 String passwordString = null;
6507 if (cypherPassword==null || cypherPassword.trim().equals(""))
6508 passwordString = userPassword;
6510 passwordString = cypherPassword+" "+userPassword;
6511 connection = DriverManager.getConnection(url,userid,passwordString);
6512 } catch (SQLException e) {
6517 } catch (SQLException e) {
6518 e.printStackTrace();
6523 //*************************************************
6524 //* View / Hide source HTML for a note
6525 //*************************************************
6526 public void viewSource() {
6527 browserWindow.showSource(menuBar.viewSource.isChecked());
6529 //*************************************************
6530 // Block the program. This is used for things
6531 // like async web calls.
6532 //*************************************************
6533 @SuppressWarnings("unused")
6534 private void blockApplication(BrowserWindow b) {
6535 // Block all signals
6539 blockTimer = new QTimer();
6540 blockTimer.setSingleShot(true);
6541 blockTimer.setInterval(15000);
6542 blockTimer.timeout.connect(this, "unblockApplication()");
6547 @SuppressWarnings("unused")
6548 private void unblockApplication() {
6550 if (blockingWindow != null && new GregorianCalendar().getTimeInMillis() > blockingWindow.unblockTime && blockingWindow.unblockTime != -1) {
6551 QMessageBox.critical(null, tr("No Response from CodeCogs") ,tr("Unable to contact CodeCogs for LaTeX formula."));
6552 blockingWindow.unblockTime = -1;
6553 blockingWindow.awaitingHttpResponse = false;
6555 blockingWindow = null;
6556 blockSignals(false);