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 if (currentNoteGuid.equals(""))
696 currentNote = new Note();
697 historyGuids = new ArrayList<String>();
701 if (!currentNoteGuid.trim().equals("")) {
702 currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true);
705 noteIndexUpdated(true);
707 menuBar.showEditorBar.setChecked(Global.isWindowVisible("editorButtonBar"));
708 if (menuBar.showEditorBar.isChecked())
709 showEditorButtons(browserWindow);
710 tagIndexUpdated(true);
711 savedSearchIndexUpdated();
712 notebookIndexUpdated();
714 setupSyncSignalListeners();
715 setupBrowserSignalListeners();
716 setupIndexListeners();
719 tagTree.tagSignal.listChanged.connect(this, "tagIndexUpdated()");
720 tagTree.showAllTags(true);
722 QIcon appIcon = new QIcon(iconPath+"nevernote.png");
723 if (QSystemTrayIcon.isSystemTrayAvailable()) {
724 setWindowIcon(appIcon);
725 trayIcon.setIcon(appIcon);
726 if (Global.showTrayIcon() || Global.minimizeOnClose())
732 scrollToGuid(currentNoteGuid);
733 if (Global.automaticLogin()) {
735 if (Global.isConnected)
738 setupFolderImports();
741 restoreWindowState(true);
743 if (Global.mimicEvernoteInterface) {
744 notebookTree.selectGuid("");
747 threadMonitorTimer = new QTimer();
748 threadMonitorTimer.timeout.connect(this, "threadMonitorCheck()");
749 threadMonitorTimer.start(1000*10); // Check for threads every 10 seconds;
751 historyGuids.add(currentNoteGuid);
754 menuBar.blockSignals(true);
755 menuBar.narrowListView.blockSignals(true);
756 menuBar.wideListView.blockSignals(true);
757 if (Global.getListView() == Global.View_List_Narrow) {
758 menuBar.narrowListView.setChecked(true);
761 menuBar.wideListView.setChecked(true);
763 menuBar.blockSignals(false);
764 menuBar.narrowListView.blockSignals(false);
765 menuBar.wideListView.blockSignals(false);
767 if (Global.getListView() == Global.View_List_Wide) {
768 browserIndexSplitter.addWidget(noteTableView);
769 browserIndexSplitter.addWidget(browserWindow);
771 mainLeftRightSplitter.addWidget(noteTableView);
772 mainLeftRightSplitter.addWidget(browserWindow);
775 messageTimer = new QTimer();
776 messageTimer.timeout.connect(this, "clearMessage()");
777 messageTimer.setInterval(1000*15);
780 int sortCol = Global.getSortColumn();
781 int sortOrder = Global.getSortOrder();
782 noteTableView.proxyModel.blocked = true;
783 // We sort the table twice to fix a bug. For some reaosn the table won't sort properly if it is in narrow
784 // list view and sorted descending on the date created. By sorting it twice it forces the proper sort. Ugly.
785 if (sortCol == 0 && sortOrder == 1 && Global.getListView() == Global.View_List_Narrow)
786 noteTableView.sortByColumn(sortCol, SortOrder.resolve(0));
787 noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder));
788 noteTableView.proxyModel.blocked = false;
789 noteTableView.proxyModel.sortChanged.connect(this, "tableSortOrderChanged(Integer,Integer)");
791 // Set the startup notebook
792 String defaultNotebook = Global.getStartupNotebook();
793 if (!defaultNotebook.equals("AllNotebooks") && !defaultNotebook.equals("")) {
794 for (int k=0; k<listManager.getNotebookIndex().size(); k++) {
795 if (listManager.getNotebookIndex().get(k).isDefaultNotebook()) {
796 notebookTree.clearSelection();
797 notebookTree.selectGuid(listManager.getNotebookIndex().get(k).getGuid());
798 notebookTree.selectionSignal.emit();
806 if (Global.checkVersionUpgrade())
811 public void debugDirty() {
812 List<Note> dirty = conn.getNoteTable().getDirty();
813 logger.log(logger.LOW, "------ Dirty Notes List Begin ------");
814 for (int i=0; i<dirty.size(); i++) {
815 logger.log(logger.LOW, "GUID: " +dirty.get(i).getGuid() + " Title:" + dirty.get(i).getTitle());
817 logger.log(logger.LOW, "------ Dirty Notes List End ------");
821 public static void main(String[] args) {
822 log.setLevel(Level.FATAL);
823 QApplication.initialize(args);
824 QPixmap pixmap = new QPixmap("classpath:cx/fbn/nevernote/icons/splash_logo.png");
825 QSplashScreen splash = new QSplashScreen(pixmap);
828 DatabaseConnection dbConn;
831 initializeGlobalSettings(args);
833 showSplash = Global.isWindowVisible("SplashScreen");
837 dbConn = setupDatabaseConnection();
839 // Must be last stage of setup - only safe once DB is open hence we know we are the only instance running
840 Global.getFileManager().purgeResDirectory(true);
842 } catch (InitializationException e) {
845 QMessageBox.critical(null, "Startup error", "Aborting: " + e.getMessage());
850 String proxyUrl = Global.getProxyValue("url");
851 String proxyPort = Global.getProxyValue("port");
852 String proxyUserid = Global.getProxyValue("userid");
853 String proxyPassword = Global.getProxyValue("password");
854 boolean proxySet = false;
855 QNetworkProxy proxy = new QNetworkProxy();
856 proxy.setType(ProxyType.HttpProxy);
857 if (!proxyUrl.trim().equals("")) {
858 System.out.println("Proxy URL found: " +proxyUrl);
860 proxy.setHostName(proxyUrl);
862 if (!proxyPort.trim().equals("")) {
863 System.out.println("Proxy Port found: " +proxyPort);
865 proxy.setPort(Integer.parseInt(proxyPort));
867 if (!proxyUserid.trim().equals("")) {
868 System.out.println("Proxy Userid found: " +proxyUserid);
870 proxy.setUser(proxyUserid);
872 if (!proxyPassword.trim().equals("")) {
873 System.out.println("Proxy URL found: " +proxyPassword);
875 proxy.setPassword(proxyPassword);
878 QNetworkProxy.setApplicationProxy(proxy);
882 NeverNote application = new NeverNote(dbConn);
883 if (Global.syncOnly) {
884 System.out.println("Performing synchronization only.");
885 application.remoteConnect();
886 if (Global.isConnected) {
887 application.syncRunner.syncNeeded = true;
888 application.syncRunner.addWork("SYNC");
889 application.syncRunner.addWork("STOP");
890 while(!application.syncRunner.isIdle());
891 application.closeNeverNote();
896 application.setAttribute(WidgetAttribute.WA_DeleteOnClose, true);
897 if (Global.startMinimized())
898 application.showMinimized();
900 if (Global.wasWindowMaximized())
901 application.showMaximized();
907 splash.finish(application);
909 System.out.println("Goodbye.");
914 * Open the internal database, or create if not present
916 * @throws InitializationException when opening the database fails, e.g. because another process has it locked
918 private static DatabaseConnection setupDatabaseConnection() throws InitializationException {
919 ApplicationLogger logger = new ApplicationLogger("nevernote-database.log");
921 File f = Global.getFileManager().getDbDirFile(Global.databaseName + ".h2.db");
922 File fr = Global.getFileManager().getDbDirFile(Global.resourceDatabaseName + ".h2.db");
923 File fi = Global.getFileManager().getDbDirFile(Global.resourceDatabaseName + ".h2.db");
925 Global.setDatabaseUrl("");
927 Global.setResourceDatabaseUrl("");
929 Global.setIndexDatabaseUrl("");
931 if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") > -1) {
932 boolean goodCheck = false;
934 DatabaseLoginDialog dialog = new DatabaseLoginDialog();
936 if (!dialog.okPressed())
938 Global.cipherPassword = dialog.getPassword();
939 goodCheck = databaseCheck(Global.getDatabaseUrl(), Global.getDatabaseUserid(),
940 Global.getDatabaseUserPassword(), Global.cipherPassword);
943 DatabaseConnection dbConn = new DatabaseConnection(logger,Global.getDatabaseUrl(),
944 Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(),
945 Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword, 0);
949 // Encrypt the database upon shutdown
950 private void encryptOnShutdown() {
951 String dbPath= Global.getFileManager().getDbDirPath("");
954 Statement st = conn.getConnection().createStatement();
955 st.execute("shutdown");
956 st = conn.getResourceConnection().createStatement();
957 st.execute("shutdown");
958 st = conn.getIndexConnection().createStatement();
959 st.execute("shutdown");
960 if (QMessageBox.question(this, tr("Are you sure"),
961 tr("Are you sure you wish to encrypt the database?"),
962 QMessageBox.StandardButton.Yes,
963 QMessageBox.StandardButton.No) == StandardButton.Yes.value()) {
964 ChangeFileEncryption.execute(dbPath, "NeverNote", encryptCipher, null, Global.cipherPassword.toCharArray(), true);
965 ChangeFileEncryption.execute(dbPath, "Resources", encryptCipher, null, Global.cipherPassword.toCharArray(), true);
966 ChangeFileEncryption.execute(dbPath, "Index", encryptCipher, null, Global.cipherPassword.toCharArray(), true);
967 Global.setDatabaseUrl(Global.getDatabaseUrl() + ";CIPHER="+encryptCipher);
968 Global.setResourceDatabaseUrl(Global.getResourceDatabaseUrl() + ";CIPHER="+encryptCipher);
969 Global.setIndexDatabaseUrl(Global.getIndexDatabaseUrl() + ";CIPHER="+encryptCipher);
971 QMessageBox.information(this, tr("Encryption Complete"), tr("Encryption is complete"));
973 } catch (SQLException e) {
978 // Decrypt the database upon shutdown
979 private void decryptOnShutdown() {
980 String dbPath= Global.getFileManager().getDbDirPath("");
981 String dbName = "NeverNote";
983 Statement st = conn.getConnection().createStatement();
984 st.execute("shutdown");
985 if (Global.getDatabaseUrl().toUpperCase().indexOf(";CIPHER=AES") > -1)
986 encryptCipher = "AES";
988 encryptCipher = "XTEA";
989 if (QMessageBox.question(this, tr("Confirmation"), tr("Are you sure",
990 "Are you sure you wish to decrypt the database?"),
991 QMessageBox.StandardButton.Yes,
992 QMessageBox.StandardButton.No) == StandardButton.Yes.value()) {
994 ChangeFileEncryption.execute(dbPath, dbName, encryptCipher, Global.cipherPassword.toCharArray(), null, true);
995 Global.setDatabaseUrl("");
996 Global.setResourceDatabaseUrl("");
997 Global.setIndexDatabaseUrl("");
998 QMessageBox.information(this, tr("Decryption Complete"), tr("Decryption is complete"));
1000 } catch (SQLException e) {
1001 e.printStackTrace();
1005 * Encrypt/Decrypt the local database
1007 public void doDatabaseEncrypt() {
1008 // The database is not currently encrypted
1009 if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") == -1) {
1010 if (QMessageBox.question(this, tr("Confirmation"), tr("Encrypting the database is used" +
1011 "to enhance security and is performed\nupon shutdown, but please be aware that if"+
1012 " you lose the password your\nis lost forever.\n\nIt is highly recommended you " +
1013 "perform a backup and/or fully synchronize\n prior to executing this funtction.\n\n" +
1014 "Do you wish to proceed?"),
1015 QMessageBox.StandardButton.Yes,
1016 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1019 DBEncryptDialog dialog = new DBEncryptDialog();
1021 if (dialog.okPressed()) {
1022 Global.cipherPassword = dialog.getPassword();
1023 encryptOnShutdown = true;
1024 encryptCipher = dialog.getEncryptionMethod();
1027 DBEncryptDialog dialog = new DBEncryptDialog();
1028 dialog.setWindowTitle(tr("Database Decryption"));
1029 dialog.hideEncryption();
1031 if (dialog.okPressed()) {
1032 if (!dialog.getPassword().equals(Global.cipherPassword)) {
1033 QMessageBox.critical(null, tr("Incorrect Password"), tr("Incorrect Password"));
1036 decryptOnShutdown = true;
1043 private static void initializeGlobalSettings(String[] args) throws InitializationException {
1044 StartupConfig startupConfig = new StartupConfig();
1046 for (String arg : args) {
1047 String lower = arg.toLowerCase();
1048 if (lower.startsWith("--name="))
1049 startupConfig.setName(arg.substring(arg.indexOf('=') + 1));
1050 if (lower.startsWith("--home="))
1051 startupConfig.setHomeDirPath(arg.substring(arg.indexOf('=') + 1));
1052 if (lower.startsWith("--disable-viewing"))
1053 startupConfig.setDisableViewing(true);
1054 if (lower.startsWith("--sync-only=true"))
1055 startupConfig.setSyncOnly(true);
1057 Global.setup(startupConfig);
1063 public void closeEvent(QCloseEvent event) {
1064 if (Global.minimizeOnClose() && !closeAction) {
1069 logger.log(logger.HIGH, "Entering NeverNote.closeEvent");
1072 if (currentNote!= null & browserWindow!=null) {
1073 if (currentNote.getTitle() != null && browserWindow != null
1074 && !currentNote.getTitle().equals(browserWindow.getTitle()))
1075 conn.getNoteTable().updateNoteTitle(currentNote.getGuid(), browserWindow.getTitle());
1078 setMessage(tr("Beginning shutdown."));
1080 // Close down external windows
1081 Collection<ExternalBrowse> windows = externalWindows.values();
1082 Iterator<ExternalBrowse> iterator = windows.iterator();
1083 while (iterator.hasNext()) {
1084 ExternalBrowse browser = iterator.next();
1085 browser.windowClosing.disconnect();
1090 externalFileEditedSaver();
1091 if (Global.isConnected && Global.synchronizeOnClose()) {
1092 setMessage(tr("Performing synchronization before closing."));
1093 syncRunner.syncNeeded = true;
1094 syncRunner.addWork("SYNC");
1096 syncRunner.keepRunning = false;
1098 syncRunner.addWork("STOP");
1099 setMessage("Closing Program.");
1100 threadMonitorTimer.stop();
1102 thumbnailRunner.addWork("STOP");
1103 indexRunner.addWork("STOP");
1108 if (tempFiles != null)
1111 browserWindow.noteSignal.tagsChanged.disconnect();
1112 browserWindow.noteSignal.titleChanged.disconnect();
1113 browserWindow.noteSignal.noteChanged.disconnect();
1114 browserWindow.noteSignal.notebookChanged.disconnect();
1115 browserWindow.noteSignal.createdDateChanged.disconnect();
1116 browserWindow.noteSignal.alteredDateChanged.disconnect();
1117 syncRunner.searchSignal.listChanged.disconnect();
1118 syncRunner.tagSignal.listChanged.disconnect();
1119 syncRunner.notebookSignal.listChanged.disconnect();
1120 syncRunner.noteIndexSignal.listChanged.disconnect();
1123 Global.saveWindowVisible("toolBar", toolBar.isVisible());
1124 saveNoteColumnPositions();
1125 saveNoteIndexWidth();
1127 int width = notebookTree.columnWidth(0);
1128 Global.setColumnWidth("notebookTreeName", width);
1129 width = tagTree.columnWidth(0);
1130 Global.setColumnWidth("tagTreeName", width);
1132 Global.saveWindowMaximized(isMaximized());
1133 Global.saveCurrentNoteGuid(currentNoteGuid);
1135 int sortCol = noteTableView.proxyModel.sortColumn();
1136 int sortOrder = noteTableView.proxyModel.sortOrder().value();
1137 Global.setSortColumn(sortCol);
1138 Global.setSortOrder(sortOrder);
1142 Global.keepRunning = false;
1144 logger.log(logger.MEDIUM, "Waiting for indexThread to stop");
1145 if (indexRunner.thread().isAlive())
1146 indexRunner.thread().join(50);
1147 if (!indexRunner.thread().isAlive())
1148 logger.log(logger.MEDIUM, "Index thread has stopped");
1150 logger.log(logger.MEDIUM, "Index thread still running - interrupting");
1151 indexRunner.thread().interrupt();
1153 } catch (InterruptedException e1) {
1154 e1.printStackTrace();
1157 if (!syncRunner.thread().isAlive()) {
1158 logger.log(logger.MEDIUM, "Waiting for syncThread to stop");
1159 if (syncRunner.thread().isAlive()) {
1160 System.out.println(tr("Synchronizing. Please be patient."));
1161 for(;syncRunner.thread().isAlive();) {
1164 } catch (InterruptedException e) {
1165 e.printStackTrace();
1169 logger.log(logger.MEDIUM, "Sync thread has stopped");
1172 if (encryptOnShutdown) {
1173 encryptOnShutdown();
1175 if (decryptOnShutdown) {
1176 decryptOnShutdown();
1179 Global.getFileManager().purgeResDirectory(false);
1180 } catch (InitializationException e) {
1181 System.out.println(tr("Empty res directory purge failed"));
1182 e.printStackTrace();
1184 logger.log(logger.HIGH, "Leaving NeverNote.closeEvent");
1188 private void closeNeverNote() {
1192 public void setMessage(String s) {
1194 logger.log(logger.HIGH, "Entering NeverNote.setMessage");
1196 System.out.println("*** ERROR *** " +s);
1198 if (statusBar != null) {
1201 logger.log(logger.HIGH, "Message: " +s);
1202 statusBar.showMessage(s);
1203 if (emitLog != null)
1206 if (messageTimer != null) {
1207 messageTimer.stop();
1208 messageTimer.setSingleShot(true);
1209 messageTimer.start();
1214 logger.log(logger.HIGH, "Leaving NeverNote.setMessage");
1217 private void clearMessage() {
1218 statusBar.clearMessage();
1222 private void waitCursor(boolean wait) {
1224 if (QApplication.overrideCursor() == null)
1225 QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.WaitCursor));
1228 if (QApplication.overrideCursor() != null)
1229 QApplication.restoreOverrideCursor();
1231 QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.ArrowCursor));
1233 listManager.refreshCounters();
1236 private void setupIndexListeners() {
1237 // indexRunner.noteSignal.noteIndexed.connect(this, "indexThreadComplete(String)");
1238 // indexRunner.resourceSignal.resourceIndexed.connect(this, "indexThreadComplete(String)");
1239 indexRunner.signal.indexStarted.connect(this, "indexStarted()");
1240 indexRunner.signal.indexFinished.connect(this, "indexComplete()");
1242 private void setupSyncSignalListeners() {
1243 syncRunner.tagSignal.listChanged.connect(this, "tagIndexUpdated()");
1244 syncRunner.searchSignal.listChanged.connect(this, "savedSearchIndexUpdated()");
1245 syncRunner.notebookSignal.listChanged.connect(this, "notebookIndexUpdated()");
1246 syncRunner.noteIndexSignal.listChanged.connect(this, "noteIndexUpdated(boolean)");
1247 syncRunner.noteSignal.quotaChanged.connect(this, "updateQuotaBar()");
1249 syncRunner.syncSignal.saveUploadAmount.connect(this,"saveUploadAmount(long)");
1250 syncRunner.syncSignal.saveUserInformation.connect(this,"saveUserInformation(User)");
1251 syncRunner.syncSignal.saveEvernoteUpdateCount.connect(this,"saveEvernoteUpdateCount(int)");
1253 syncRunner.noteSignal.guidChanged.connect(this, "noteGuidChanged(String, String)");
1254 syncRunner.noteSignal.noteChanged.connect(this, "invalidateNoteCache(String, String)");
1255 syncRunner.resourceSignal.resourceGuidChanged.connect(this, "noteResourceGuidChanged(String,String,String)");
1256 syncRunner.noteSignal.noteDownloaded.connect(listManager, "noteDownloaded(Note)");
1257 syncRunner.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
1259 syncRunner.syncSignal.refreshLists.connect(this, "refreshLists()");
1262 private void setupBrowserSignalListeners() {
1263 setupBrowserWindowListeners(browserWindow, true);
1266 private void setupBrowserWindowListeners(BrowserWindow browser, boolean master) {
1267 browser.fileWatcher.fileChanged.connect(this, "externalFileEdited(String)");
1268 browser.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)");
1269 browser.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)");
1270 if (master) browser.noteSignal.noteChanged.connect(this, "setNoteDirty()");
1271 browser.noteSignal.titleChanged.connect(listManager, "updateNoteTitle(String, String)");
1272 browser.noteSignal.titleChanged.connect(this, "updateNoteTitle(String, String)");
1273 browser.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
1274 browser.noteSignal.createdDateChanged.connect(listManager, "updateNoteCreatedDate(String, QDateTime)");
1275 browser.noteSignal.alteredDateChanged.connect(listManager, "updateNoteAlteredDate(String, QDateTime)");
1276 browser.noteSignal.subjectDateChanged.connect(listManager, "updateNoteSubjectDate(String, QDateTime)");
1277 browser.noteSignal.authorChanged.connect(listManager, "updateNoteAuthor(String, String)");
1278 browser.noteSignal.geoChanged.connect(listManager, "updateNoteGeoTag(String, Double,Double,Double)");
1279 browser.noteSignal.geoChanged.connect(this, "setNoteDirty()");
1280 browser.noteSignal.sourceUrlChanged.connect(listManager, "updateNoteSourceUrl(String, String)");
1281 browser.blockApplication.connect(this, "blockApplication(BrowserWindow)");
1282 browser.unblockApplication.connect(this, "unblockApplication()");
1283 if (master) browser.focusLost.connect(this, "saveNote()");
1284 browser.resourceSignal.contentChanged.connect(this, "externalFileEdited(String)");
1285 browser.evernoteLinkClicked.connect(this, "evernoteLinkClick(String, String)");
1288 //**************************************************
1290 //**************************************************
1291 private void setupShortcut(QShortcut action, String text) {
1292 if (!Global.shortcutKeys.containsAction(text))
1294 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
1297 //***************************************************************
1298 //***************************************************************
1299 //* Settings and look & feel
1300 //***************************************************************
1301 //***************************************************************
1302 @SuppressWarnings("unused")
1303 private void settings() {
1304 logger.log(logger.HIGH, "Entering NeverNote.settings");
1305 saveNoteColumnPositions();
1306 saveNoteIndexWidth();
1308 ConfigDialog settings = new ConfigDialog(this);
1309 String dateFormat = Global.getDateFormat();
1310 String timeFormat = Global.getTimeFormat();
1312 indexTime = 1000*Global.getIndexThreadSleepInterval();
1313 indexTimer.start(indexTime); // reset indexing timer
1316 indexRunner.indexAttachmentsLocally = Global.indexAttachmentsLocally();
1317 indexRunner.indexNoteBody = Global.indexNoteBody();
1318 indexRunner.indexNoteTitle = Global.indexNoteTitle();
1319 indexRunner.specialIndexCharacters = Global.getSpecialIndexCharacters();
1320 indexRunner.indexImageRecognition = Global.indexImageRecognition();
1321 if (Global.showTrayIcon() || Global.minimizeOnClose())
1326 if (menuBar.showEditorBar.isChecked())
1327 showEditorButtons(browserWindow);
1329 // Reset the save timer
1330 if (Global.getAutoSaveInterval() > 0)
1331 saveTimer.setInterval(1000*60*Global.getAutoSaveInterval());
1336 // Set special reloads
1337 if (settings.getDebugPage().reloadSharedNotebooksClicked()) {
1338 conn.executeSql("Delete from LinkedNotebook");
1339 conn.executeSql("delete from SharedNotebook");
1340 conn.executeSql("Delete from Notebook where linked=true");
1341 conn.executeSql("Insert into Sync (key, value) values ('FullLinkedNotebookSync', 'true')");
1342 conn.executeSql("Insert into Sync (key, value) values ('FullSharedNotebookSync', 'true')");
1347 readOnlyCache.clear();
1348 inkNoteCache.clear();
1349 noteIndexUpdated(true);
1351 logger.log(logger.HIGH, "Leaving NeverNote.settings");
1353 // Restore things to the way they were
1354 private void restoreWindowState(boolean mainWindow) {
1355 // We need to name things or this doesn't work.
1356 setObjectName("NeverNote");
1357 restoreState(Global.restoreState(objectName()));
1358 mainLeftRightSplitter.setObjectName("mainLeftRightSplitter");
1359 browserIndexSplitter.setObjectName("browserIndexSplitter");
1360 leftSplitter1.setObjectName("leftSplitter1");
1362 // Restore the actual positions.
1364 restoreGeometry(Global.restoreGeometry(objectName()));
1365 mainLeftRightSplitter.restoreState(Global.restoreState(mainLeftRightSplitter.objectName()));
1366 browserIndexSplitter.restoreState(Global.restoreState(browserIndexSplitter.objectName()));
1367 leftSplitter1.restoreState(Global.restoreState(leftSplitter1.objectName()));
1370 // Save window positions for the next start
1371 private void saveWindowState() {
1372 Global.saveGeometry(objectName(), saveGeometry());
1373 Global.saveState(mainLeftRightSplitter.objectName(), mainLeftRightSplitter.saveState());
1374 Global.saveState(browserIndexSplitter.objectName(), browserIndexSplitter.saveState());
1375 Global.saveState(leftSplitter1.objectName(), leftSplitter1.saveState());
1376 Global.saveState(objectName(), saveState());
1378 // Load the style sheet
1379 private void loadStyleSheet() {
1380 String styleSheetName = "default.qss";
1381 if (Global.getStyle().equalsIgnoreCase("cleanlooks"))
1382 styleSheetName = "default-cleanlooks.qss";
1383 String fileName = Global.getFileManager().getQssDirPathUser("default.qss");
1384 QFile file = new QFile(fileName);
1386 // If a user default.qss doesn't exist, we use the one shipped with NeverNote
1387 if (!file.exists()) {
1388 fileName = Global.getFileManager().getQssDirPath(styleSheetName);
1389 file = new QFile(fileName);
1391 file.open(OpenModeFlag.ReadOnly);
1392 String styleSheet = file.readAll().toString();
1394 setStyleSheet(styleSheet);
1396 // Save column positions for the next time
1397 private void saveNoteColumnPositions() {
1398 int position = noteTableView.header.visualIndex(Global.noteTableCreationPosition);
1399 Global.setColumnPosition("noteTableCreationPosition", position);
1400 position = noteTableView.header.visualIndex(Global.noteTableTagPosition);
1401 Global.setColumnPosition("noteTableTagPosition", position);
1402 position = noteTableView.header.visualIndex(Global.noteTableNotebookPosition);
1403 Global.setColumnPosition("noteTableNotebookPosition", position);
1404 position = noteTableView.header.visualIndex(Global.noteTableChangedPosition);
1405 Global.setColumnPosition("noteTableChangedPosition", position);
1406 position = noteTableView.header.visualIndex(Global.noteTableAuthorPosition);
1407 Global.setColumnPosition("noteTableAuthorPosition", position);
1408 position = noteTableView.header.visualIndex(Global.noteTableSourceUrlPosition);
1409 Global.setColumnPosition("noteTableSourceUrlPosition", position);
1410 position = noteTableView.header.visualIndex(Global.noteTableSubjectDatePosition);
1411 Global.setColumnPosition("noteTableSubjectDatePosition", position);
1412 position = noteTableView.header.visualIndex(Global.noteTableTitlePosition);
1413 Global.setColumnPosition("noteTableTitlePosition", position);
1414 position = noteTableView.header.visualIndex(Global.noteTableSynchronizedPosition);
1415 Global.setColumnPosition("noteTableSynchronizedPosition", position);
1416 position = noteTableView.header.visualIndex(Global.noteTableGuidPosition);
1417 Global.setColumnPosition("noteTableGuidPosition", position);
1418 position = noteTableView.header.visualIndex(Global.noteTableThumbnailPosition);
1419 Global.setColumnPosition("noteTableThumbnailPosition", position);
1420 position = noteTableView.header.visualIndex(Global.noteTablePinnedPosition);
1421 Global.setColumnPosition("noteTablePinnedPosition", position);
1424 // Save column widths for the next time
1425 private void saveNoteIndexWidth() {
1427 width = noteTableView.getColumnWidth(Global.noteTableCreationPosition);
1428 Global.setColumnWidth("noteTableCreationPosition", width);
1429 width = noteTableView.getColumnWidth(Global.noteTableChangedPosition);
1430 Global.setColumnWidth("noteTableChangedPosition", width);
1431 width = noteTableView.getColumnWidth(Global.noteTableGuidPosition);
1432 Global.setColumnWidth("noteTableGuidPosition", width);
1433 width = noteTableView.getColumnWidth(Global.noteTableNotebookPosition);
1434 Global.setColumnWidth("noteTableNotebookPosition", width);
1435 width = noteTableView.getColumnWidth(Global.noteTableTagPosition);
1436 Global.setColumnWidth("noteTableTagPosition", width);
1437 width = noteTableView.getColumnWidth(Global.noteTableTitlePosition);
1438 Global.setColumnWidth("noteTableTitlePosition", width);
1439 width = noteTableView.getColumnWidth(Global.noteTableSourceUrlPosition);
1440 Global.setColumnWidth("noteTableSourceUrlPosition", width);
1441 width = noteTableView.getColumnWidth(Global.noteTableAuthorPosition);
1442 Global.setColumnWidth("noteTableAuthorPosition", width);
1443 width = noteTableView.getColumnWidth(Global.noteTableSubjectDatePosition);
1444 Global.setColumnWidth("noteTableSubjectDatePosition", width);
1445 width = noteTableView.getColumnWidth(Global.noteTableSynchronizedPosition);
1446 Global.setColumnWidth("noteTableSynchronizedPosition", width);
1447 width = noteTableView.getColumnWidth(Global.noteTableThumbnailPosition);
1448 Global.setColumnWidth("noteTableThumbnailPosition", width);
1449 width = noteTableView.getColumnWidth(Global.noteTableGuidPosition);
1450 Global.setColumnWidth("noteTableGuidPosition", width);
1451 width = noteTableView.getColumnWidth(Global.noteTablePinnedPosition);
1452 Global.setColumnWidth("noteTablePinnedPosition", width);
1455 @SuppressWarnings("unused")
1456 private void toggleSearchWindow() {
1457 logger.log(logger.HIGH, "Entering NeverNote.toggleSearchWindow");
1458 searchLayout.toggleSearchField();
1459 menuBar.hideSearch.setChecked(searchField.isVisible());
1460 Global.saveWindowVisible("searchField", searchField.isVisible());
1461 logger.log(logger.HIGH, "Leaving NeverNote.toggleSearchWindow");
1463 @SuppressWarnings("unused")
1464 private void toggleQuotaWindow() {
1465 logger.log(logger.HIGH, "Entering NeverNote.toggleQuotaWindow");
1466 searchLayout.toggleQuotaBar();
1467 menuBar.hideQuota.setChecked(quotaBar.isVisible());
1468 Global.saveWindowVisible("quota", quotaBar.isVisible());
1469 logger.log(logger.HIGH, "Leaving NeverNote.toggleQuotaWindow");
1471 @SuppressWarnings("unused")
1472 private void toggleZoomWindow() {
1473 logger.log(logger.HIGH, "Entering NeverNote.toggleZoomWindow");
1474 searchLayout.toggleZoom();
1475 menuBar.hideZoom.setChecked(zoomSpinner.isVisible());
1476 Global.saveWindowVisible("zoom", zoomSpinner.isVisible());
1477 logger.log(logger.HIGH, "Leaving NeverNote.toggleZoomWindow");
1482 //***************************************************************
1483 //***************************************************************
1484 //** These functions deal with Notebook menu items
1485 //***************************************************************
1486 //***************************************************************
1487 // Setup the tree containing the user's notebooks.
1488 private void initializeNotebookTree() {
1489 logger.log(logger.HIGH, "Entering NeverNote.initializeNotebookTree");
1490 // notebookTree.itemClicked.connect(this, "notebookTreeSelection()");
1491 notebookTree.selectionSignal.connect(this, "notebookTreeSelection()");
1492 listManager.notebookSignal.refreshNotebookTreeCounts.connect(notebookTree, "updateCounts(List, List)");
1493 logger.log(logger.HIGH, "Leaving NeverNote.initializeNotebookTree");
1495 // Listener when a notebook is selected
1496 private void notebookTreeSelection() {
1497 logger.log(logger.HIGH, "Entering NeverNote.notebookTreeSelection");
1498 noteTableView.proxyModel.blocked = true;
1501 clearAttributeFilter();
1502 clearSavedSearchFilter();
1503 if (Global.mimicEvernoteInterface) {
1505 //searchField.clear();
1506 searchField.clearEditText();
1508 menuBar.noteRestoreAction.setVisible(false);
1509 menuBar.notebookEditAction.setEnabled(true);
1510 menuBar.notebookDeleteAction.setEnabled(true);
1511 menuBar.notebookPublishAction.setEnabled(true);
1512 menuBar.notebookShareAction.setEnabled(true);
1513 menuBar.notebookIconAction.setEnabled(true);
1514 menuBar.notebookStackAction.setEnabled(true);
1515 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1516 selectedNotebookGUIDs.clear();
1518 String stackName = "";
1519 if (selections.size() > 0) {
1520 guid = (selections.get(0).text(2));
1521 stackName = selections.get(0).text(0);
1523 if (!Global.mimicEvernoteInterface) {
1524 // If no notebooks are selected, we make it look like the "all notebooks" one was selected
1525 if (selections.size()==0) {
1526 selectedNotebookGUIDs.clear();
1527 for (int i=0; i < listManager.getNotebookIndex().size(); i++) {
1528 selectedNotebookGUIDs.add(listManager.getNotebookIndex().get(i).getGuid());
1530 menuBar.notebookEditAction.setEnabled(false);
1531 menuBar.notebookDeleteAction.setEnabled(false);
1532 menuBar.notebookStackAction.setEnabled(false);
1533 menuBar.notebookIconAction.setEnabled(false);
1536 if (!guid.equals("") && !guid.equals("STACK")) {
1537 selectedNotebookGUIDs.add(guid);
1538 menuBar.notebookIconAction.setEnabled(true);
1540 menuBar.notebookIconAction.setEnabled(true);
1541 for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1542 Notebook book = listManager.getNotebookIndex().get(j);
1543 if (book.getStack() != null && book.getStack().equalsIgnoreCase(stackName))
1544 selectedNotebookGUIDs.add(book.getGuid());
1547 listManager.setSelectedNotebooks(selectedNotebookGUIDs);
1548 listManager.loadNotesIndex();
1549 noteIndexUpdated(false);
1550 refreshEvernoteNote(true);
1551 listManager.refreshCounters = true;
1552 listManager.refreshCounters();
1553 if (selectedNotebookGUIDs.size() == 1) {
1554 int col = conn.getNotebookTable().getSortColumn(selectedNotebookGUIDs.get(0));
1555 int order = conn.getNotebookTable().getSortOrder(selectedNotebookGUIDs.get(0));
1557 noteTableView.proxyModel.blocked = true;
1559 noteTableView.sortByColumn(col, Qt.SortOrder.DescendingOrder);
1561 noteTableView.sortByColumn(col, Qt.SortOrder.AscendingOrder);
1564 noteTableView.proxyModel.blocked = false;
1565 logger.log(logger.HIGH, "Leaving NeverNote.notebookTreeSelection");
1568 private void clearNotebookFilter() {
1569 notebookTree.blockSignals(true);
1570 notebookTree.clearSelection();
1571 menuBar.noteRestoreAction.setVisible(false);
1572 menuBar.notebookEditAction.setEnabled(false);
1573 menuBar.notebookDeleteAction.setEnabled(false);
1574 selectedNotebookGUIDs.clear();
1575 listManager.setSelectedNotebooks(selectedNotebookGUIDs);
1576 notebookTree.blockSignals(false);
1578 // Triggered when the notebook DB has been updated
1579 private void notebookIndexUpdated() {
1580 logger.log(logger.HIGH, "Entering NeverNote.notebookIndexUpdated");
1582 // Get the possible icons
1583 HashMap<String, QIcon> icons = conn.getNotebookTable().getAllIcons();
1584 notebookTree.setIcons(icons);
1586 if (selectedNotebookGUIDs == null)
1587 selectedNotebookGUIDs = new ArrayList<String>();
1588 List<Notebook> books = conn.getNotebookTable().getAll();
1589 for (int i=books.size()-1; i>=0; i--) {
1590 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1591 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(books.get(i).getGuid())) {
1593 j=listManager.getArchiveNotebookIndex().size();
1599 listManager.countNotebookResults(listManager.getNoteIndex());
1600 notebookTree.blockSignals(true);
1601 notebookTree.load(books, listManager.getLocalNotebooks());
1602 for (int i=selectedNotebookGUIDs.size()-1; i>=0; i--) {
1603 boolean found = notebookTree.selectGuid(selectedNotebookGUIDs.get(i));
1605 selectedNotebookGUIDs.remove(i);
1607 listManager.refreshCounters = true;
1608 listManager.refreshCounters();
1609 notebookTree.blockSignals(false);
1611 logger.log(logger.HIGH, "Leaving NeverNote.notebookIndexUpdated");
1613 // Show/Hide note information
1614 @SuppressWarnings("unused")
1615 private void toggleNotebookWindow() {
1616 logger.log(logger.HIGH, "Entering NeverNote.toggleNotebookWindow");
1617 searchLayout.toggleNotebook();
1618 menuBar.hideNotebooks.setChecked(notebookTree.isVisible());
1619 Global.saveWindowVisible("notebookTree", notebookTree.isVisible());
1620 logger.log(logger.HIGH, "Leaving NeverNote.toggleNotebookWindow");
1622 // Add a new notebook
1623 @SuppressWarnings("unused")
1624 private void addNotebook() {
1625 logger.log(logger.HIGH, "Inside NeverNote.addNotebook");
1626 NotebookEdit edit = new NotebookEdit();
1627 edit.setNotebooks(listManager.getNotebookIndex());
1630 if (!edit.okPressed())
1633 Calendar currentTime = new GregorianCalendar();
1634 Long l = new Long(currentTime.getTimeInMillis());
1635 String randint = new String(Long.toString(l));
1637 Notebook newBook = new Notebook();
1638 newBook.setUpdateSequenceNum(0);
1639 newBook.setGuid(randint);
1640 newBook.setName(edit.getNotebook());
1641 newBook.setServiceCreated(new Date().getTime());
1642 newBook.setServiceUpdated(new Date().getTime());
1643 newBook.setDefaultNotebook(false);
1644 newBook.setPublished(false);
1646 listManager.getNotebookIndex().add(newBook);
1648 listManager.getLocalNotebooks().add(newBook.getGuid());
1649 conn.getNotebookTable().addNotebook(newBook, true, edit.isLocal());
1650 notebookIndexUpdated();
1651 listManager.countNotebookResults(listManager.getNoteIndex());
1652 // notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
1653 logger.log(logger.HIGH, "Leaving NeverNote.addNotebook");
1655 // Edit an existing notebook
1656 @SuppressWarnings("unused")
1657 private void stackNotebook() {
1658 logger.log(logger.HIGH, "Entering NeverNote.stackNotebook");
1659 StackNotebook edit = new StackNotebook();
1661 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1662 QTreeWidgetItem currentSelection;
1663 for (int i=0; i<selections.size(); i++) {
1664 currentSelection = selections.get(0);
1665 String guid = currentSelection.text(2);
1666 if (guid.equalsIgnoreCase("")) {
1667 QMessageBox.critical(this, tr("Unable To Stack") ,tr("You can't stack the \"All Notebooks\" item."));
1670 if (guid.equalsIgnoreCase("STACK")) {
1671 QMessageBox.critical(this, tr("Unable To Stack") ,tr("You can't stack a stack."));
1676 edit.setStackNames(conn.getNotebookTable().getAllStackNames());
1681 if (!edit.okPressed())
1684 String stack = edit.getStackName();
1686 for (int i=0; i<selections.size(); i++) {
1687 currentSelection = selections.get(i);
1688 String guid = currentSelection.text(2);
1689 listManager.updateNotebookStack(guid, stack);
1691 notebookIndexUpdated();
1692 logger.log(logger.HIGH, "Leaving NeverNote.stackNotebook");
1694 // Edit an existing notebook
1695 @SuppressWarnings("unused")
1696 private void editNotebook() {
1697 logger.log(logger.HIGH, "Entering NeverNote.editNotebook");
1698 NotebookEdit edit = new NotebookEdit();
1700 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1701 QTreeWidgetItem currentSelection;
1702 currentSelection = selections.get(0);
1703 edit.setNotebook(currentSelection.text(0));
1705 String guid = currentSelection.text(2);
1706 if (!guid.equalsIgnoreCase("STACK")) {
1707 edit.setTitle(tr("Edit Notebook"));
1708 edit.setNotebooks(listManager.getNotebookIndex());
1709 edit.setLocalCheckboxEnabled(false);
1710 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1711 if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
1712 edit.setDefaultNotebook(listManager.getNotebookIndex().get(i).isDefaultNotebook());
1713 i=listManager.getNotebookIndex().size();
1717 edit.setTitle(tr("Edit Stack"));
1718 edit.setStacks(conn.getNotebookTable().getAllStackNames());
1719 edit.hideLocalCheckbox();
1720 edit.hideDefaultCheckbox();
1725 if (!edit.okPressed())
1729 if (guid.equalsIgnoreCase("STACK")) {
1730 conn.getNotebookTable().renameStacks(currentSelection.text(0), edit.getNotebook());
1731 for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1732 if (listManager.getNotebookIndex().get(j).getStack() != null &&
1733 listManager.getNotebookIndex().get(j).getStack().equalsIgnoreCase(currentSelection.text(0)))
1734 listManager.getNotebookIndex().get(j).setStack(edit.getNotebook());
1736 conn.getNotebookTable().renameStacks(currentSelection.text(0), edit.getNotebook());
1737 currentSelection.setText(0, edit.getNotebook());
1741 updateListNotebookName(currentSelection.text(0), edit.getNotebook());
1742 currentSelection.setText(0, edit.getNotebook());
1744 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1745 if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
1746 listManager.getNotebookIndex().get(i).setName(edit.getNotebook());
1747 if (!listManager.getNotebookIndex().get(i).isDefaultNotebook() && edit.isDefaultNotebook()) {
1748 for (int j=0; j<listManager.getNotebookIndex().size(); j++)
1749 listManager.getNotebookIndex().get(j).setDefaultNotebook(false);
1750 listManager.getNotebookIndex().get(i).setDefaultNotebook(true);
1751 conn.getNotebookTable().setDefaultNotebook(listManager.getNotebookIndex().get(i).getGuid());
1753 conn.getNotebookTable().updateNotebook(listManager.getNotebookIndex().get(i), true);
1754 if (conn.getNotebookTable().isLinked(listManager.getNotebookIndex().get(i).getGuid())) {
1755 LinkedNotebook linkedNotebook = conn.getLinkedNotebookTable().getByNotebookGuid(listManager.getNotebookIndex().get(i).getGuid());
1756 linkedNotebook.setShareName(edit.getNotebook());
1757 conn.getLinkedNotebookTable().updateNotebook(linkedNotebook, true);
1759 i=listManager.getNotebookIndex().size();
1763 // Build a list of non-closed notebooks
1764 List<Notebook> nbooks = new ArrayList<Notebook>();
1765 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1766 boolean found=false;
1767 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1768 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
1772 nbooks.add(listManager.getNotebookIndex().get(i));
1776 FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger);
1777 List<Notebook> filteredBooks = notebookFilter.getValidNotebooks(currentNote, listManager.getNotebookIndex());
1778 browserWindow.setNotebookList(filteredBooks);
1779 Iterator<String> set = externalWindows.keySet().iterator();
1780 while(set.hasNext())
1781 externalWindows.get(set.next()).getBrowserWindow().setNotebookList(filteredBooks);
1782 logger.log(logger.HIGH, "Leaving NeverNote.editNotebook");
1784 // Publish a notebook
1785 @SuppressWarnings("unused")
1786 private void publishNotebook() {
1787 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1788 QTreeWidgetItem currentSelection;
1789 currentSelection = selections.get(0);
1790 String guid = currentSelection.text(2);
1792 if (guid.equalsIgnoreCase("STACK") || guid.equalsIgnoreCase(""))
1797 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1798 if (guid.equals(listManager.getNotebookIndex().get(i).getGuid())) {
1799 n = listManager.getNotebookIndex().get(i);
1801 i = listManager.getNotebookIndex().size();
1807 PublishNotebook publish = new PublishNotebook(Global.username, Global.getServer(), n);
1810 if (!publish.okClicked())
1813 Publishing p = publish.getPublishing();
1814 boolean isPublished = !publish.isStopPressed();
1815 conn.getNotebookTable().setPublishing(n.getGuid(), isPublished, p);
1816 n.setPublished(isPublished);
1818 listManager.getNotebookIndex().set(position, n);
1819 notebookIndexUpdated();
1821 // Publish a notebook
1822 @SuppressWarnings("unused")
1823 private void shareNotebook() {
1824 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1825 QTreeWidgetItem currentSelection;
1826 currentSelection = selections.get(0);
1827 String guid = currentSelection.text(2);
1829 if (guid.equalsIgnoreCase("STACK") || guid.equalsIgnoreCase(""))
1833 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1834 if (guid.equals(listManager.getNotebookIndex().get(i).getGuid())) {
1835 n = listManager.getNotebookIndex().get(i);
1836 i = listManager.getNotebookIndex().size();
1840 String authToken = null;
1841 if (syncRunner.isConnected)
1842 authToken = syncRunner.authToken;
1843 ShareNotebook share = new ShareNotebook(n.getName(), conn, n, syncRunner);
1848 // Delete an existing notebook
1849 @SuppressWarnings("unused")
1850 private void deleteNotebook() {
1851 logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
1852 boolean stacksFound = false;
1853 boolean notebooksFound = false;
1854 boolean assigned = false;
1855 // Check if any notes have this notebook
1856 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1857 for (int i=0; i<selections.size(); i++) {
1858 QTreeWidgetItem currentSelection;
1859 currentSelection = selections.get(i);
1860 String guid = currentSelection.text(2);
1861 if (!guid.equalsIgnoreCase("STACK")) {
1862 notebooksFound = true;
1863 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
1864 String noteGuid = listManager.getNoteIndex().get(j).getNotebookGuid();
1865 if (noteGuid.equals(guid)) {
1867 j=listManager.getNoteIndex().size();
1868 i=selections.size();
1876 QMessageBox.information(this, tr("Unable to Delete"), tr("Some of the selected notebook(s) contain notes.\n"+
1877 "Please delete the notes or move them to another notebook before deleting any notebooks."));
1881 if (conn.getNotebookTable().getAll().size() == 1) {
1882 QMessageBox.information(this, tr("Unable to Delete"), tr("You must have at least one notebook."));
1886 // If all notebooks are clear, verify the delete
1887 String msg1 = new String(tr("Delete selected notebooks?"));
1888 String msg2 = new String(tr("Remove selected stacks (notebooks will not be deleted)?"));
1889 String msg3 = new String(tr("Delete selected notebooks & remove stacks? Notebooks under the stacks are" +
1890 " not deleted unless selected?"));
1892 if (stacksFound && notebooksFound)
1894 if (!stacksFound && notebooksFound)
1896 if (stacksFound && !notebooksFound)
1898 if (QMessageBox.question(this, tr("Confirmation"), msg,
1899 QMessageBox.StandardButton.Yes,
1900 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1904 // If confirmed, delete the notebook
1905 for (int i=selections.size()-1; i>=0; i--) {
1906 QTreeWidgetItem currentSelection;
1907 currentSelection = selections.get(i);
1908 String guid = currentSelection.text(2);
1909 if (currentSelection.text(2).equalsIgnoreCase("STACK")) {
1910 conn.getNotebookTable().renameStacks(currentSelection.text(0), "");
1911 listManager.renameStack(currentSelection.text(0), "");
1913 conn.getNotebookTable().expungeNotebook(guid, true);
1914 listManager.deleteNotebook(guid);
1918 notebookIndexUpdated();
1919 // notebookTreeSelection();
1920 // notebookTree.load(listManager.getNotebookIndex(), listManager.getLocalNotebooks());
1921 // listManager.countNotebookResults(listManager.getNoteIndex());
1922 logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
1924 // A note's notebook has been updated
1925 @SuppressWarnings("unused")
1926 private void updateNoteNotebook(String guid, String notebookGuid) {
1928 // Update the list manager
1929 listManager.updateNoteNotebook(guid, notebookGuid);
1930 listManager.countNotebookResults(listManager.getNoteIndex());
1931 // notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
1933 // Find the name of the notebook
1934 String notebookName = null;
1935 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1936 if (listManager.getNotebookIndex().get(i).getGuid().equals(notebookGuid)) {
1937 notebookName = listManager.getNotebookIndex().get(i).getName();
1942 // If we found the name, update the browser window
1943 if (notebookName != null) {
1944 updateListNoteNotebook(guid, notebookName);
1945 if (guid.equals(currentNoteGuid)) {
1946 int pos = browserWindow.notebookBox.findText(notebookName);
1948 browserWindow.notebookBox.setCurrentIndex(pos);
1952 // If we're dealing with the current note, then we need to be sure and update the notebook there
1953 if (guid.equals(currentNoteGuid)) {
1954 if (currentNote != null) {
1955 currentNote.setNotebookGuid(notebookGuid);
1959 // Open/close notebooks
1960 @SuppressWarnings("unused")
1961 private void closeNotebooks() {
1962 NotebookArchive na = new NotebookArchive(listManager.getNotebookIndex(), listManager.getArchiveNotebookIndex());
1964 if (!na.okClicked())
1968 listManager.getArchiveNotebookIndex().clear();
1970 for (int i=na.getClosedBookList().count()-1; i>=0; i--) {
1971 String text = na.getClosedBookList().takeItem(i).text();
1972 for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1973 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
1974 Notebook n = listManager.getNotebookIndex().get(j);
1975 conn.getNotebookTable().setArchived(n.getGuid(),true);
1976 listManager.getArchiveNotebookIndex().add(n);
1977 j=listManager.getNotebookIndex().size();
1982 for (int i=na.getOpenBookList().count()-1; i>=0; i--) {
1983 String text = na.getOpenBookList().takeItem(i).text();
1984 for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1985 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
1986 Notebook n = listManager.getNotebookIndex().get(j);
1987 conn.getNotebookTable().setArchived(n.getGuid(),false);
1988 j=listManager.getNotebookIndex().size();
1992 notebookTreeSelection();
1993 listManager.loadNotesIndex();
1994 notebookIndexUpdated();
1995 noteIndexUpdated(false);
1996 reloadTagTree(true);
1997 // noteIndexUpdated(false);
1999 // Build a list of non-closed notebooks
2000 List<Notebook> nbooks = new ArrayList<Notebook>();
2001 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
2002 boolean found=false;
2003 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
2004 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
2008 nbooks.add(listManager.getNotebookIndex().get(i));
2011 FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger);
2012 List<Notebook> filteredBooks = notebookFilter.getValidNotebooks(currentNote, listManager.getNotebookIndex());
2013 browserWindow.setNotebookList(filteredBooks);
2015 // Update any external windows
2016 Iterator<String> set = externalWindows.keySet().iterator();
2017 while(set.hasNext())
2018 externalWindows.get(set.next()).getBrowserWindow().setNotebookList(filteredBooks);
2022 // Change the notebook's icon
2023 @SuppressWarnings("unused")
2024 private void setNotebookIcon() {
2025 boolean stackSelected = false;
2026 boolean allNotebookSelected = false;
2028 QTreeWidgetItem currentSelection;
2029 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
2030 if (selections.size() == 0)
2033 currentSelection = selections.get(0);
2034 String guid = currentSelection.text(2);
2035 if (guid.equalsIgnoreCase(""))
2036 allNotebookSelected = true;
2037 if (guid.equalsIgnoreCase("STACK"))
2038 stackSelected = true;
2040 QIcon currentIcon = currentSelection.icon(0);
2044 if (!stackSelected && !allNotebookSelected) {
2045 icon = conn.getNotebookTable().getIcon(guid);
2047 dialog = new SetIcon(currentIcon, saveLastPath);
2048 dialog.setUseDefaultIcon(true);
2050 dialog = new SetIcon(icon, saveLastPath);
2051 dialog.setUseDefaultIcon(false);
2054 if (stackSelected) {
2055 icon = conn.getSystemIconTable().getIcon(currentSelection.text(0), "STACK");
2057 icon = conn.getSystemIconTable().getIcon(currentSelection.text(0), "ALLNOTEBOOK");
2060 dialog = new SetIcon(currentIcon, saveLastPath);
2061 dialog.setUseDefaultIcon(true);
2063 dialog = new SetIcon(icon, saveLastPath);
2064 dialog.setUseDefaultIcon(false);
2068 if (dialog.okPressed()) {
2069 saveLastPath = dialog.getPath();
2071 QIcon newIcon = dialog.getIcon();
2072 if (stackSelected) {
2073 conn.getSystemIconTable().setIcon(currentSelection.text(0), "STACK", newIcon, dialog.getFileType());
2074 if (newIcon == null) {
2075 newIcon = new QIcon(iconPath+"books2.png");
2077 currentSelection.setIcon(0,newIcon);
2080 if (allNotebookSelected) {
2081 conn.getSystemIconTable().setIcon(currentSelection.text(0), "ALLNOTEBOOK", newIcon, dialog.getFileType());
2082 if (newIcon == null) {
2083 newIcon = new QIcon(iconPath+"notebook-green.png");
2085 currentSelection.setIcon(0,newIcon);
2088 conn.getNotebookTable().setIcon(guid, newIcon, dialog.getFileType());
2089 if (newIcon == null) {
2090 boolean isPublished = false;;
2091 boolean found = false;
2092 for (int i=0; i<listManager.getNotebookIndex().size() && !found; i++) {
2093 if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
2094 isPublished = listManager.getNotebookIndex().get(i).isPublished();
2098 newIcon = notebookTree.findDefaultIcon(guid, currentSelection.text(1), listManager.getLocalNotebooks(), isPublished);
2100 currentSelection.setIcon(0, newIcon);
2106 //***************************************************************
2107 //***************************************************************
2108 //** These functions deal with Tag menu items
2109 //***************************************************************
2110 //***************************************************************
2111 // Add a new notebook
2112 @SuppressWarnings("unused")
2113 private void addTag() {
2114 logger.log(logger.HIGH, "Inside NeverNote.addTag");
2115 TagEdit edit = new TagEdit();
2116 edit.setTagList(listManager.getTagIndex());
2118 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2119 QTreeWidgetItem currentSelection = null;
2120 if (selections.size() > 0) {
2121 currentSelection = selections.get(0);
2122 edit.setParentTag(currentSelection.text(0));
2127 if (!edit.okPressed())
2130 Calendar currentTime = new GregorianCalendar();
2131 Long l = new Long(currentTime.getTimeInMillis());
2132 String randint = new String(Long.toString(l));
2134 Tag newTag = new Tag();
2135 newTag.setUpdateSequenceNum(0);
2136 newTag.setGuid(randint);
2137 newTag.setName(edit.getTag());
2138 if (edit.getParentTag().isChecked()) {
2139 newTag.setParentGuid(currentSelection.text(2));
2140 newTag.setParentGuidIsSet(true);
2141 currentSelection.setExpanded(true);
2143 conn.getTagTable().addTag(newTag, true);
2144 listManager.getTagIndex().add(newTag);
2145 reloadTagTree(true);
2147 logger.log(logger.HIGH, "Leaving NeverNote.addTag");
2149 @SuppressWarnings("unused")
2150 private void reloadTagTree() {
2151 reloadTagTree(false);
2153 private void reloadTagTree(boolean reload) {
2154 logger.log(logger.HIGH, "Entering NeverNote.reloadTagTree");
2155 tagIndexUpdated(reload);
2156 boolean filter = false;
2158 listManager.countTagResults(listManager.getNoteIndex());
2159 if (notebookTree.selectedItems().size() > 0
2160 && !notebookTree.selectedItems().get(0).text(0).equalsIgnoreCase("All Notebooks"))
2162 if (tagTree.selectedItems().size() > 0)
2164 tagTree.showAllTags(!filter);
2165 tagIndexUpdated(false);
2166 logger.log(logger.HIGH, "Leaving NeverNote.reloadTagTree");
2168 // Edit an existing tag
2169 @SuppressWarnings("unused")
2170 private void editTag() {
2171 logger.log(logger.HIGH, "Entering NeverNote.editTag");
2172 TagEdit edit = new TagEdit();
2173 edit.setTitle("Edit Tag");
2174 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2175 QTreeWidgetItem currentSelection;
2176 currentSelection = selections.get(0);
2177 edit.setTag(currentSelection.text(0));
2178 edit.setTagList(listManager.getTagIndex());
2181 if (!edit.okPressed())
2184 String guid = currentSelection.text(2);
2185 currentSelection.setText(0,edit.getTag());
2187 for (int i=0; i<listManager.getTagIndex().size(); i++) {
2188 if (listManager.getTagIndex().get(i).getGuid().equals(guid)) {
2189 listManager.getTagIndex().get(i).setName(edit.getTag());
2190 conn.getTagTable().updateTag(listManager.getTagIndex().get(i), true);
2191 updateListTagName(guid);
2192 if (currentNote != null && currentNote.getTagGuids().contains(guid))
2193 browserWindow.setTag(getTagNamesForNote(currentNote));
2194 logger.log(logger.HIGH, "Leaving NeverNote.editTag");
2198 listManager.reloadNoteTagNames(guid, edit.getTag());
2199 noteIndexUpdated(true);
2200 refreshEvernoteNote(true);
2201 browserWindow.setTag(getTagNamesForNote(currentNote));
2202 logger.log(logger.HIGH, "Leaving NeverNote.editTag...");
2204 // Delete an existing tag
2205 @SuppressWarnings("unused")
2206 private void deleteTag() {
2207 logger.log(logger.HIGH, "Entering NeverNote.deleteTag");
2209 if (QMessageBox.question(this, tr("Confirmation"), tr("Delete the selected tags?"),
2210 QMessageBox.StandardButton.Yes,
2211 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
2215 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2216 for (int i=selections.size()-1; i>=0; i--) {
2217 QTreeWidgetItem currentSelection;
2218 currentSelection = selections.get(i);
2219 removeTagItem(currentSelection.text(2));
2221 tagIndexUpdated(true);
2223 listManager.countTagResults(listManager.getNoteIndex());
2224 // tagTree.updateCounts(listManager.getTagCounter());
2225 logger.log(logger.HIGH, "Leaving NeverNote.deleteTag");
2227 // Remove a tag tree item. Go recursively down & remove the children too
2228 private void removeTagItem(String guid) {
2229 for (int j=listManager.getTagIndex().size()-1; j>=0; j--) {
2230 String parent = listManager.getTagIndex().get(j).getParentGuid();
2231 if (parent != null && parent.equals(guid)) {
2232 //Remove this tag's children
2233 removeTagItem(listManager.getTagIndex().get(j).getGuid());
2236 //Now, remove this tag
2237 removeListTagName(guid);
2238 conn.getTagTable().expungeTag(guid, true);
2239 for (int a=0; a<listManager.getTagIndex().size(); a++) {
2240 if (listManager.getTagIndex().get(a).getGuid().equals(guid)) {
2241 listManager.getTagIndex().remove(a);
2246 // Setup the tree containing the user's tags
2247 private void initializeTagTree() {
2248 logger.log(logger.HIGH, "Entering NeverNote.initializeTagTree");
2249 // tagTree.itemSelectionChanged.connect(this, "tagTreeSelection()");
2250 // tagTree.itemClicked.connect(this, "tagTreeSelection()");
2251 tagTree.selectionSignal.connect(this, "tagTreeSelection()");
2252 listManager.tagSignal.refreshTagTreeCounts.connect(tagTree, "updateCounts(List)");
2253 logger.log(logger.HIGH, "Leaving NeverNote.initializeTagTree");
2255 // Listener when a tag is selected
2256 private void tagTreeSelection() {
2257 logger.log(logger.HIGH, "Entering NeverNote.tagTreeSelection");
2260 clearAttributeFilter();
2261 clearSavedSearchFilter();
2263 menuBar.noteRestoreAction.setVisible(false);
2265 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2266 QTreeWidgetItem currentSelection;
2267 selectedTagGUIDs.clear();
2268 for (int i=0; i<selections.size(); i++) {
2269 currentSelection = selections.get(i);
2270 selectedTagGUIDs.add(currentSelection.text(2));
2272 if (selections.size() > 0) {
2273 menuBar.tagEditAction.setEnabled(true);
2274 menuBar.tagDeleteAction.setEnabled(true);
2275 menuBar.tagIconAction.setEnabled(true);
2278 menuBar.tagEditAction.setEnabled(false);
2279 menuBar.tagDeleteAction.setEnabled(false);
2280 menuBar.tagIconAction.setEnabled(true);
2282 if (selections.size() > 1)
2283 menuBar.tagMergeAction.setEnabled(true);
2285 menuBar.tagMergeAction.setEnabled(false);
2286 listManager.setSelectedTags(selectedTagGUIDs);
2287 listManager.loadNotesIndex();
2288 noteIndexUpdated(false);
2289 refreshEvernoteNote(true);
2290 listManager.refreshCounters = true;
2291 listManager.refreshCounters();
2292 logger.log(logger.HIGH, "Leaving NeverNote.tagTreeSelection");
2294 // trigger the tag index to be refreshed
2295 @SuppressWarnings("unused")
2296 private void tagIndexUpdated() {
2297 tagIndexUpdated(true);
2299 private void tagIndexUpdated(boolean reload) {
2300 logger.log(logger.HIGH, "Entering NeverNote.tagIndexUpdated");
2301 if (selectedTagGUIDs == null)
2302 selectedTagGUIDs = new ArrayList<String>();
2304 listManager.reloadTagIndex();
2306 tagTree.blockSignals(true);
2308 tagTree.setIcons(conn.getTagTable().getAllIcons());
2309 tagTree.load(listManager.getTagIndex());
2312 for (int i=selectedTagGUIDs.size()-1; i>=0; i--) {
2313 boolean found = tagTree.selectGuid(selectedTagGUIDs.get(i));
2315 selectedTagGUIDs.remove(i);
2317 tagTree.blockSignals(false);
2319 browserWindow.setTag(getTagNamesForNote(currentNote));
2320 logger.log(logger.HIGH, "Leaving NeverNote.tagIndexUpdated");
2322 // Show/Hide note information
2323 @SuppressWarnings("unused")
2324 private void toggleTagWindow() {
2325 logger.log(logger.HIGH, "Entering NeverNote.toggleTagWindow");
2326 if (tagTree.isVisible())
2330 menuBar.hideTags.setChecked(tagTree.isVisible());
2331 Global.saveWindowVisible("tagTree", tagTree.isVisible());
2332 logger.log(logger.HIGH, "Leaving NeverNote.toggleTagWindow");
2334 // A note's tags have been updated
2335 @SuppressWarnings("unused")
2336 private void updateNoteTags(String guid, List<String> tags) {
2337 // Save any new tags. We'll need them later.
2338 List<String> newTags = new ArrayList<String>();
2339 for (int i=0; i<tags.size(); i++) {
2340 if (conn.getTagTable().findTagByName(tags.get(i))==null)
2341 newTags.add(tags.get(i));
2344 listManager.saveNoteTags(guid, tags, true);
2345 listManager.countTagResults(listManager.getNoteIndex());
2346 StringBuffer names = new StringBuffer("");
2347 for (int i=0; i<tags.size(); i++) {
2348 names = names.append(tags.get(i));
2349 if (i<tags.size()-1) {
2350 names.append(Global.tagDelimeter + " ");
2353 browserWindow.setTag(names.toString());
2356 // Now, we need to add any new tags to the tag tree
2357 for (int i=0; i<newTags.size(); i++)
2358 tagTree.insertTag(newTags.get(i), conn.getTagTable().findTagByName(newTags.get(i)));
2360 // Get a string containing all tag names for a note
2361 private String getTagNamesForNote(Note n) {
2362 logger.log(logger.HIGH, "Entering NeverNote.getTagNamesForNote");
2363 if (n==null || n.getGuid() == null || n.getGuid().equals(""))
2365 StringBuffer buffer = new StringBuffer(100);
2366 Vector<String> v = new Vector<String>();
2367 List<String> guids = n.getTagGuids();
2372 for (int i=0; i<guids.size(); i++) {
2373 v.add(listManager.getTagNameByGuid(guids.get(i)));
2375 Comparator<String> comparator = Collections.reverseOrder();
2376 Collections.sort(v,comparator);
2377 Collections.reverse(v);
2379 for (int i = 0; i<v.size(); i++) {
2381 buffer.append(", ");
2382 buffer.append(v.get(i));
2385 logger.log(logger.HIGH, "Leaving NeverNote.getTagNamesForNote");
2386 return buffer.toString();
2388 // Tags were added via dropping notes from the note list
2389 @SuppressWarnings("unused")
2390 private void tagsAdded(String noteGuid, String tagGuid) {
2391 String tagName = null;
2392 for (int i=0; i<listManager.getTagIndex().size(); i++) {
2393 if (listManager.getTagIndex().get(i).getGuid().equals(tagGuid)) {
2394 tagName = listManager.getTagIndex().get(i).getName();
2395 i=listManager.getTagIndex().size();
2398 if (tagName == null)
2401 for (int i=0; i<listManager.getMasterNoteIndex().size(); i++) {
2402 if (listManager.getMasterNoteIndex().get(i).getGuid().equals(noteGuid)) {
2403 List<String> tagNames = new ArrayList<String>();
2404 tagNames.add(new String(tagName));
2405 Note n = listManager.getMasterNoteIndex().get(i);
2406 for (int j=0; j<n.getTagNames().size(); j++) {
2407 tagNames.add(new String(n.getTagNames().get(j)));
2409 listManager.getNoteTableModel().updateNoteTags(noteGuid, n.getTagGuids(), tagNames);
2410 if (n.getGuid().equals(currentNoteGuid)) {
2411 Collections.sort(tagNames);
2412 String display = "";
2413 for (int j=0; j<tagNames.size(); j++) {
2414 display = display+tagNames.get(j);
2415 if (j+2<tagNames.size())
2416 display = display+Global.tagDelimeter+" ";
2418 browserWindow.setTag(display);
2420 i=listManager.getMasterNoteIndex().size();
2425 listManager.getNoteTableModel().updateNoteSyncStatus(noteGuid, false);
2427 private void clearTagFilter() {
2428 tagTree.blockSignals(true);
2429 tagTree.clearSelection();
2430 menuBar.noteRestoreAction.setVisible(false);
2431 menuBar.tagEditAction.setEnabled(false);
2432 menuBar.tagMergeAction.setEnabled(false);
2433 menuBar.tagDeleteAction.setEnabled(false);
2434 menuBar.tagIconAction.setEnabled(false);
2435 selectedTagGUIDs.clear();
2436 listManager.setSelectedTags(selectedTagGUIDs);
2437 tagTree.blockSignals(false);
2439 // Change the icon for a tag
2440 @SuppressWarnings("unused")
2441 private void setTagIcon() {
2442 QTreeWidgetItem currentSelection;
2443 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2444 if (selections.size() == 0)
2447 currentSelection = selections.get(0);
2448 String guid = currentSelection.text(2);
2450 QIcon currentIcon = currentSelection.icon(0);
2451 QIcon icon = conn.getTagTable().getIcon(guid);
2454 dialog = new SetIcon(currentIcon, saveLastPath);
2455 dialog.setUseDefaultIcon(true);
2457 dialog = new SetIcon(icon, saveLastPath);
2458 dialog.setUseDefaultIcon(false);
2461 if (dialog.okPressed()) {
2462 saveLastPath = dialog.getPath();
2463 QIcon newIcon = dialog.getIcon();
2464 conn.getTagTable().setIcon(guid, newIcon, dialog.getFileType());
2465 if (newIcon == null)
2466 newIcon = new QIcon(iconPath+"tag.png");
2467 currentSelection.setIcon(0, newIcon);
2472 @SuppressWarnings("unused")
2473 private void mergeTags() {
2474 List<Tag> tags = new ArrayList<Tag>();
2475 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2476 for (int i=0; i<selections.size(); i++) {
2477 Tag record = new Tag();
2478 record.setGuid(selections.get(i).text(2));
2479 record.setName(selections.get(i).text(0));
2483 TagMerge mergeDialog = new TagMerge(tags);
2485 if (!mergeDialog.okClicked())
2487 String newGuid = mergeDialog.getNewTagGuid();
2489 for (int i=0; i<tags.size(); i++) {
2490 if (!tags.get(i).getGuid().equals(newGuid)) {
2491 List<String> noteGuids = conn.getNoteTable().noteTagsTable.getTagNotes(tags.get(i).getGuid());
2492 for (int j=0; j<noteGuids.size(); j++) {
2493 String noteGuid = noteGuids.get(j);
2494 conn.getNoteTable().noteTagsTable.deleteNoteTag(noteGuid);
2495 if (!conn.getNoteTable().noteTagsTable.checkNoteNoteTags(noteGuid, newGuid))
2496 conn.getNoteTable().noteTagsTable.saveNoteTag(noteGuid, newGuid, true);
2500 listManager.reloadIndexes();
2503 //***************************************************************
2504 //***************************************************************
2505 //** These functions deal with Saved Search menu items
2506 //***************************************************************
2507 //***************************************************************
2508 // Add a new notebook
2509 @SuppressWarnings("unused")
2510 private void addSavedSearch() {
2511 logger.log(logger.HIGH, "Inside NeverNote.addSavedSearch");
2512 SavedSearchEdit edit = new SavedSearchEdit();
2513 edit.setSearchList(listManager.getSavedSearchIndex());
2516 if (!edit.okPressed())
2519 Calendar currentTime = new GregorianCalendar();
2520 Long l = new Long(currentTime.getTimeInMillis());
2521 String randint = new String(Long.toString(l));
2523 SavedSearch search = new SavedSearch();
2524 search.setUpdateSequenceNum(0);
2525 search.setGuid(randint);
2526 search.setName(edit.getName());
2527 search.setQuery(edit.getQuery());
2528 search.setFormat(QueryFormat.USER);
2529 listManager.getSavedSearchIndex().add(search);
2530 conn.getSavedSearchTable().addSavedSearch(search, true);
2531 savedSearchIndexUpdated();
2532 logger.log(logger.HIGH, "Leaving NeverNote.addSavedSearch");
2534 // Edit an existing tag
2535 @SuppressWarnings("unused")
2536 private void editSavedSearch() {
2537 logger.log(logger.HIGH, "Entering NeverNote.editSavedSearch");
2538 SavedSearchEdit edit = new SavedSearchEdit();
2539 edit.setTitle(tr("Edit Search"));
2540 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2541 QTreeWidgetItem currentSelection;
2542 currentSelection = selections.get(0);
2543 String guid = currentSelection.text(1);
2544 SavedSearch s = conn.getSavedSearchTable().getSavedSearch(guid);
2545 edit.setName(currentSelection.text(0));
2546 edit.setQuery(s.getQuery());
2547 edit.setSearchList(listManager.getSavedSearchIndex());
2550 if (!edit.okPressed())
2553 List<SavedSearch> list = listManager.getSavedSearchIndex();
2554 SavedSearch search = null;
2555 boolean found = false;
2556 for (int i=0; i<list.size(); i++) {
2557 search = list.get(i);
2558 if (search.getGuid().equals(guid)) {
2565 search.setName(edit.getName());
2566 search.setQuery(edit.getQuery());
2567 conn.getSavedSearchTable().updateSavedSearch(search, true);
2568 savedSearchIndexUpdated();
2569 logger.log(logger.HIGH, "Leaving NeverNote.editSavedSearch");
2571 // Delete an existing tag
2572 @SuppressWarnings("unused")
2573 private void deleteSavedSearch() {
2574 logger.log(logger.HIGH, "Entering NeverNote.deleteSavedSearch");
2576 if (QMessageBox.question(this, tr("Confirmation"), tr("Delete the selected search?"),
2577 QMessageBox.StandardButton.Yes,
2578 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
2582 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2583 for (int i=selections.size()-1; i>=0; i--) {
2584 QTreeWidgetItem currentSelection;
2585 currentSelection = selections.get(i);
2586 for (int j=0; j<listManager.getSavedSearchIndex().size(); j++) {
2587 if (listManager.getSavedSearchIndex().get(j).getGuid().equals(currentSelection.text(1))) {
2588 conn.getSavedSearchTable().expungeSavedSearch(listManager.getSavedSearchIndex().get(j).getGuid(), true);
2589 listManager.getSavedSearchIndex().remove(j);
2590 j=listManager.getSavedSearchIndex().size()+1;
2593 selections.remove(i);
2595 savedSearchIndexUpdated();
2596 logger.log(logger.HIGH, "Leaving NeverNote.deleteSavedSearch");
2598 // Setup the tree containing the user's tags
2599 private void initializeSavedSearchTree() {
2600 logger.log(logger.HIGH, "Entering NeverNote.initializeSavedSearchTree");
2601 savedSearchTree.itemSelectionChanged.connect(this, "savedSearchTreeSelection()");
2602 logger.log(logger.HIGH, "Leaving NeverNote.initializeSavedSearchTree");
2604 // Listener when a tag is selected
2605 @SuppressWarnings("unused")
2606 private void savedSearchTreeSelection() {
2607 logger.log(logger.HIGH, "Entering NeverNote.savedSearchTreeSelection");
2609 clearNotebookFilter();
2612 clearAttributeFilter();
2614 String currentGuid = selectedSavedSearchGUID;
2615 menuBar.savedSearchEditAction.setEnabled(true);
2616 menuBar.savedSearchDeleteAction.setEnabled(true);
2617 menuBar.savedSearchIconAction.setEnabled(true);
2618 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2619 QTreeWidgetItem currentSelection;
2620 selectedSavedSearchGUID = "";
2621 for (int i=0; i<selections.size(); i++) {
2622 currentSelection = selections.get(i);
2623 if (currentSelection.text(1).equals(currentGuid)) {
2624 currentSelection.setSelected(false);
2626 selectedSavedSearchGUID = currentSelection.text(1);
2628 // i = selections.size() +1;
2631 // There is the potential for no notebooks to be selected if this
2632 // happens then we make it look like all notebooks were selecetd.
2633 // If that happens, just select the "all notebooks"
2634 if (selections.size()==0) {
2635 clearSavedSearchFilter();
2637 listManager.setSelectedSavedSearch(selectedSavedSearchGUID);
2639 logger.log(logger.HIGH, "Leaving NeverNote.savedSearchTreeSelection");
2641 private void clearSavedSearchFilter() {
2642 menuBar.savedSearchEditAction.setEnabled(false);
2643 menuBar.savedSearchDeleteAction.setEnabled(false);
2644 menuBar.savedSearchIconAction.setEnabled(false);
2645 savedSearchTree.blockSignals(true);
2646 savedSearchTree.clearSelection();
2647 savedSearchTree.blockSignals(false);
2648 selectedSavedSearchGUID = "";
2649 searchField.setEditText("");
2650 searchPerformed = false;
2651 listManager.setSelectedSavedSearch(selectedSavedSearchGUID);
2653 // trigger the tag index to be refreshed
2654 private void savedSearchIndexUpdated() {
2655 if (selectedSavedSearchGUID == null)
2656 selectedSavedSearchGUID = new String();
2657 savedSearchTree.blockSignals(true);
2658 savedSearchTree.setIcons(conn.getSavedSearchTable().getAllIcons());
2659 savedSearchTree.load(listManager.getSavedSearchIndex());
2660 savedSearchTree.selectGuid(selectedSavedSearchGUID);
2661 savedSearchTree.blockSignals(false);
2663 // trigger when the saved search selection changes
2664 @SuppressWarnings("unused")
2665 private void updateSavedSearchSelection() {
2666 logger.log(logger.HIGH, "Entering NeverNote.updateSavedSearchSelection()");
2668 menuBar.savedSearchEditAction.setEnabled(true);
2669 menuBar.savedSearchDeleteAction.setEnabled(true);
2670 menuBar.savedSearchIconAction.setEnabled(true);
2671 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2673 if (selections.size() > 0) {
2674 menuBar.savedSearchEditAction.setEnabled(true);
2675 menuBar.savedSearchDeleteAction.setEnabled(true);
2676 menuBar.savedSearchIconAction.setEnabled(true);
2677 selectedSavedSearchGUID = selections.get(0).text(1);
2678 SavedSearch s = conn.getSavedSearchTable().getSavedSearch(selectedSavedSearchGUID);
2679 searchField.setEditText(s.getQuery());
2681 menuBar.savedSearchEditAction.setEnabled(false);
2682 menuBar.savedSearchDeleteAction.setEnabled(false);
2683 menuBar.savedSearchIconAction.setEnabled(false);
2684 selectedSavedSearchGUID = "";
2685 searchField.setEditText("");
2687 searchFieldChanged();
2689 logger.log(logger.HIGH, "Leaving NeverNote.updateSavedSearchSelection()");
2693 // Show/Hide note information
2694 @SuppressWarnings("unused")
2695 private void toggleSavedSearchWindow() {
2696 logger.log(logger.HIGH, "Entering NeverNote.toggleSavedSearchWindow");
2697 if (savedSearchTree.isVisible())
2698 savedSearchTree.hide();
2700 savedSearchTree.show();
2701 menuBar.hideSavedSearches.setChecked(savedSearchTree.isVisible());
2703 Global.saveWindowVisible("savedSearchTree", savedSearchTree.isVisible());
2704 logger.log(logger.HIGH, "Leaving NeverNote.toggleSavedSearchWindow");
2706 // Change the icon for a saved search
2707 @SuppressWarnings("unused")
2708 private void setSavedSearchIcon() {
2709 QTreeWidgetItem currentSelection;
2710 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2711 if (selections.size() == 0)
2714 currentSelection = selections.get(0);
2715 String guid = currentSelection.text(1);
2717 QIcon currentIcon = currentSelection.icon(0);
2718 QIcon icon = conn.getSavedSearchTable().getIcon(guid);
2721 dialog = new SetIcon(currentIcon, saveLastPath);
2722 dialog.setUseDefaultIcon(true);
2724 dialog = new SetIcon(icon, saveLastPath);
2725 dialog.setUseDefaultIcon(false);
2728 if (dialog.okPressed()) {
2729 saveLastPath = dialog.getPath();
2730 QIcon newIcon = dialog.getIcon();
2731 conn.getSavedSearchTable().setIcon(guid, newIcon, dialog.getFileType());
2732 if (newIcon == null)
2733 newIcon = new QIcon(iconPath+"search.png");
2734 currentSelection.setIcon(0, newIcon);
2742 //***************************************************************
2743 //***************************************************************
2744 //** These functions deal with Help menu & tool menu items
2745 //***************************************************************
2746 //***************************************************************
2747 // Show database status
2748 @SuppressWarnings("unused")
2749 private void databaseStatus() {
2751 indexRunner.interrupt = true;
2752 int dirty = conn.getNoteTable().getDirtyCount();
2753 int unindexed = conn.getNoteTable().getUnindexedCount();
2754 DatabaseStatus status = new DatabaseStatus();
2755 status.setUnsynchronized(dirty);
2756 status.setUnindexed(unindexed);
2757 status.setNoteCount(conn.getNoteTable().getNoteCount());
2758 status.setNotebookCount(listManager.getNotebookIndex().size());
2759 status.setUnindexedResourceCount(conn.getNoteTable().noteResourceTable.getUnindexedCount());
2760 status.setSavedSearchCount(listManager.getSavedSearchIndex().size());
2761 status.setTagCount(listManager.getTagIndex().size());
2762 status.setResourceCount(conn.getNoteTable().noteResourceTable.getResourceCount());
2763 status.setWordCount(conn.getWordsTable().getWordCount());
2767 // Compact the database
2768 @SuppressWarnings("unused")
2769 private void compactDatabase() {
2770 logger.log(logger.HIGH, "Entering NeverNote.compactDatabase");
2771 if (QMessageBox.question(this, tr("Confirmation"), tr("This will free unused space in the database, "+
2772 "but please be aware that depending upon the size of your database this can be time consuming " +
2773 "and NixNote will be unresponsive until it is complete. Do you wish to continue?"),
2774 QMessageBox.StandardButton.Yes,
2775 QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) {
2778 setMessage("Compacting database.");
2780 listManager.compactDatabase();
2782 setMessage("Database compact is complete.");
2783 logger.log(logger.HIGH, "Leaving NeverNote.compactDatabase");
2785 @SuppressWarnings("unused")
2786 private void accountInformation() {
2787 logger.log(logger.HIGH, "Entering NeverNote.accountInformation");
2788 AccountDialog dialog = new AccountDialog();
2790 logger.log(logger.HIGH, "Leaving NeverNote.accountInformation");
2792 @SuppressWarnings("unused")
2793 private void releaseNotes() {
2794 logger.log(logger.HIGH, "Entering NeverNote.releaseNotes");
2795 QDialog dialog = new QDialog(this);
2796 QHBoxLayout layout = new QHBoxLayout();
2797 QTextEdit textBox = new QTextEdit();
2798 layout.addWidget(textBox);
2799 textBox.setReadOnly(true);
2800 QFile file = new QFile(Global.getFileManager().getProgramDirPath("release.txt"));
2801 if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly,
2802 QIODevice.OpenModeFlag.Text)))
2804 textBox.setText(file.readAll().toString());
2806 dialog.setWindowTitle(tr("Release Notes"));
2807 dialog.setLayout(layout);
2809 logger.log(logger.HIGH, "Leaving NeverNote.releaseNotes");
2811 // Called when user picks Log from the help menu
2812 @SuppressWarnings("unused")
2813 private void logger() {
2814 logger.log(logger.HIGH, "Entering NeverNote.logger");
2815 LogFileDialog dialog = new LogFileDialog(emitLog);
2817 logger.log(logger.HIGH, "Leaving NeverNote.logger");
2819 // Menu option "help/about" was selected
2820 @SuppressWarnings("unused")
2821 private void about() {
2822 logger.log(logger.HIGH, "Entering NeverNote.about");
2823 QMessageBox.about(this,
2824 tr("About NixNote"),
2825 tr("<h4><center><b>NixNote</b></center></h4><hr><center>Version ")
2829 +"Open Source Evernote Client.<br><br>"
2830 +"Licensed under GPL v2. <br><hr><br>"
2831 +"</center>Evernote is copyright 2001-2012 by Evernote Corporation<br>"
2832 +"Jambi and QT are the licensed trademark of Nokia Corporation<br>"
2833 +"PDFRenderer is licened under the LGPL<br>"
2834 +"JTidy is copyrighted under the World Wide Web Consortium<br>"
2835 +"Apache Common Utilities licensed under the Apache License Version 2.0<br>"
2836 +"Jazzy is licened under the LGPL<br>"
2837 +"Java is a registered trademark of Oracle Corporation.<br><hr>"
2838 +"Special thanks to:<br>BitRock InstallBuilder for the Windows installer"
2839 +"<br>CodeCogs (www.codecogs.com) for the LaTeX image rendering."));
2840 logger.log(logger.HIGH, "Leaving NeverNote.about");
2842 // Hide the entire left hand side
2843 @SuppressWarnings("unused")
2844 private void toggleLeftSide() {
2847 hidden = !menuBar.hideLeftSide.isChecked();
2848 menuBar.hideLeftSide.setChecked(!hidden);
2851 leftSplitter1.setHidden(true);
2853 leftSplitter1.setHidden(false);
2855 Global.saveWindowVisible("leftPanel", hidden);
2858 public void checkForUpdates() {
2859 // Send off thread to check for a new version
2860 versionChecker = new QNetworkAccessManager(this);
2861 versionChecker.finished.connect(this, "upgradeFileRead(QNetworkReply)");
2862 QNetworkRequest request = new QNetworkRequest();
2863 request.setUrl(new QUrl(Global.getUpdatesAvailableUrl()));
2864 versionChecker.get(request);
2866 @SuppressWarnings("unused")
2867 private void upgradeFileRead(QNetworkReply reply) {
2868 if (!reply.isReadable())
2871 String winVersion = Global.version;
2872 String osxVersion = Global.version;
2873 String linuxVersion = Global.version;
2874 String linux64Version = Global.version;
2875 String version = Global.version;
2877 // Determine the versions available
2878 QByteArray data = reply.readLine();
2879 while (data != null && !reply.atEnd()) {
2880 String line = data.toString();
2882 if (line.contains(":"))
2883 lineVersion = line.substring(line.indexOf(":")+1).replace(" ", "").replace("\n", "");
2886 if (line.toLowerCase().contains("windows"))
2887 winVersion = lineVersion;
2888 else if (line.toLowerCase().contains("os-x"))
2889 osxVersion = lineVersion;
2890 else if (line.toLowerCase().contains("linux amd64"))
2891 linux64Version = lineVersion;
2892 else if (line.toLowerCase().contains("linux i386"))
2893 linuxVersion = lineVersion;
2894 else if (line.toLowerCase().contains("default"))
2895 version = lineVersion;
2897 // Read the next line
2898 data = reply.readLine();
2901 // Now we need to determine what system we are on.
2902 if (System.getProperty("os.name").toLowerCase().contains("windows"))
2903 version = winVersion;
2904 if (System.getProperty("os.name").toLowerCase().contains("mac os"))
2905 version = osxVersion;
2906 if (System.getProperty("os.name").toLowerCase().contains("Linux")) {
2907 if (System.getProperty("os.arch").contains("amd64") ||
2908 System.getProperty("os.arch").contains("x86_64"))
2909 version = linux64Version;
2911 version = linuxVersion;
2915 for (String validVersion : Global.validVersions) {
2916 if (version.equals(validVersion))
2920 UpgradeAvailableDialog dialog = new UpgradeAvailableDialog();
2922 if (dialog.remindMe())
2923 Global.setCheckVersionUpgrade(true);
2925 Global.setCheckVersionUpgrade(false);
2929 //***************************************************************
2930 //***************************************************************
2931 //** These functions deal with the Toolbar
2932 //***************************************************************
2933 //***************************************************************
2934 @SuppressWarnings("unused")
2935 private void focusSearch() {
2936 searchField.setFocus();
2939 // Text in the search bar has been cleared
2940 private void searchFieldCleared() {
2943 // This is done because we want to force a reload of
2944 // images. Some images we may want to highlight the text.
2945 readOnlyCache.clear();
2946 inkNoteCache.clear();
2948 QWebSettings.setMaximumPagesInCache(0);
2949 QWebSettings.setObjectCacheCapacities(0, 0, 0);
2951 searchField.setEditText("");
2952 saveNoteColumnPositions();
2953 saveNoteIndexWidth();
2954 noteIndexUpdated(true);
2955 if (currentNote == null && listManager.getNoteIndex().size() > 0) {
2956 currentNote = listManager.getNoteIndex().get(0);
2957 currentNoteGuid = currentNote.getGuid();
2959 refreshEvernoteNote(true);
2960 if (currentNote != null)
2961 loadNoteBrowserInformation(browserWindow, currentNoteGuid, currentNote);
2963 // text in the search bar changed. We only use this to tell if it was cleared,
2964 // otherwise we trigger off searchFieldChanged.
2965 @SuppressWarnings("unused")
2966 private void searchFieldTextChanged(String text) {
2967 QWebSettings.setMaximumPagesInCache(0);
2968 QWebSettings.setObjectCacheCapacities(0, 0, 0);
2970 if (text.trim().equals("")) {
2971 searchFieldCleared();
2972 if (searchPerformed) {
2974 // This is done because we want to force a reload of
2975 // images. Some images we may want to highlight the text.
2977 readOnlyCache.clear();
2978 inkNoteCache.clear();
2980 listManager.setEnSearch("");
2981 listManager.loadNotesIndex();
2982 refreshEvernoteNote(true);
2983 noteIndexUpdated(false);
2984 refreshEvernoteNote(true);
2986 searchPerformed = false;
2989 // Text in the toolbar has changed
2990 private void searchFieldChanged() {
2991 logger.log(logger.HIGH, "Entering NeverNote.searchFieldChanged");
2993 readOnlyCache.clear();
2994 inkNoteCache.clear();
2995 saveNoteColumnPositions();
2996 saveNoteIndexWidth();
2997 String text = searchField.currentText();
2998 listManager.setEnSearch(text.trim());
2999 listManager.loadNotesIndex();
3000 noteIndexUpdated(false);
3002 refreshEvernoteNote(true);
3003 searchPerformed = true;
3005 logger.log(logger.HIGH, "Leaving NeverNote.searchFieldChanged");
3008 // Build the window tool bar
3009 private void setupToolBar() {
3010 logger.log(logger.HIGH, "Entering NeverNote.setupToolBar");
3011 toolBar = addToolBar(tr("Tool Bar"));
3012 toolBar.setObjectName("toolBar");
3013 menuBar.setupToolBarVisible();
3014 if (!Global.isWindowVisible("toolBar"))
3015 toolBar.setVisible(false);
3017 toolBar.setVisible(true);
3019 // toolBar.addWidget(menuBar);
3020 // menuBar.setSizePolicy(Policy.Minimum, Policy.Minimum);
3021 // toolBar.addSeparator();
3022 prevButton = toolBar.addAction(tr("Previous"));
3023 QIcon prevIcon = new QIcon(iconPath+"back.png");
3024 prevButton.setIcon(prevIcon);
3025 prevButton.triggered.connect(this, "previousViewedAction()");
3026 togglePrevArrowButton(Global.isToolbarButtonVisible("prevArrow"));
3028 nextButton = toolBar.addAction(tr("Next"));
3029 QIcon nextIcon = new QIcon(iconPath+"forward.png");
3030 nextButton.setIcon(nextIcon);
3031 nextButton.triggered.connect(this, "nextViewedAction()");
3032 toggleNextArrowButton(Global.isToolbarButtonVisible("nextArrow"));
3034 upButton = toolBar.addAction(tr("Up"));
3035 QIcon upIcon = new QIcon(iconPath+"up.png");
3036 upButton.setIcon(upIcon);
3037 upButton.triggered.connect(this, "upAction()");
3038 toggleUpArrowButton(Global.isToolbarButtonVisible("upArrow"));
3041 downButton = toolBar.addAction(tr("Down"));
3042 QIcon downIcon = new QIcon(iconPath+"down.png");
3043 downButton.setIcon(downIcon);
3044 downButton.triggered.connect(this, "downAction()");
3045 toggleDownArrowButton(Global.isToolbarButtonVisible("downArrow"));
3047 synchronizeButton = toolBar.addAction(tr("Synchronize"));
3048 synchronizeButton.setIcon(new QIcon(iconPath+"synchronize.png"));
3049 synchronizeIconAngle = 0;
3050 synchronizeButton.triggered.connect(this, "evernoteSync()");
3051 toggleSynchronizeButton(Global.isToolbarButtonVisible("synchronize"));
3053 printButton = toolBar.addAction(tr("Print"));
3054 QIcon printIcon = new QIcon(iconPath+"print.png");
3055 printButton.setIcon(printIcon);
3056 printButton.triggered.connect(this, "printNote()");
3057 togglePrintButton(Global.isToolbarButtonVisible("print"));
3059 tagButton = toolBar.addAction(tr("Tag"));
3060 QIcon tagIcon = new QIcon(iconPath+"tag.png");
3061 tagButton.setIcon(tagIcon);
3062 tagButton.triggered.connect(browserWindow, "modifyTags()");
3063 toggleTagButton(Global.isToolbarButtonVisible("tag"));
3065 attributeButton = toolBar.addAction(tr("Attributes"));
3066 QIcon attributeIcon = new QIcon(iconPath+"attribute.png");
3067 attributeButton.setIcon(attributeIcon);
3068 attributeButton.triggered.connect(this, "toggleNoteInformation()");
3069 toggleAttributeButton(Global.isToolbarButtonVisible("attribute"));
3071 emailButton = toolBar.addAction(tr("Email"));
3072 QIcon emailIcon = new QIcon(iconPath+"email.png");
3073 emailButton.setIcon(emailIcon);
3074 emailButton.triggered.connect(this, "emailNote()");
3075 toggleEmailButton(Global.isToolbarButtonVisible("email"));
3077 deleteButton = toolBar.addAction(tr("Delete"));
3078 QIcon deleteIcon = new QIcon(iconPath+"delete.png");
3079 deleteButton.setIcon(deleteIcon);
3080 deleteButton.triggered.connect(this, "deleteNote()");
3081 toggleDeleteButton(Global.isToolbarButtonVisible("delete"));
3083 newButton = toolBar.addAction(tr("New"));
3084 QIcon newIcon = new QIcon(iconPath+"new.png");
3085 newButton.triggered.connect(this, "addNote()");
3086 newButton.setIcon(newIcon);
3087 toggleNewButton(Global.isToolbarButtonVisible("new"));
3089 allNotesButton = toolBar.addAction(tr("All Notes"));
3090 QIcon allIcon = new QIcon(iconPath+"books.png");
3091 allNotesButton.triggered.connect(this, "allNotes()");
3092 allNotesButton.setIcon(allIcon);
3093 toggleAllNotesButton(Global.isToolbarButtonVisible("allNotes"));
3095 //toolBar.addSeparator();
3096 //toolBar.addWidget(new QLabel(tr("Quota:")));
3097 //toolBar.addWidget(quotaBar);
3098 //quotaBar.setSizePolicy(Policy.Minimum, Policy.Minimum);
3100 //toolBar.addSeparator();
3102 //toolBar.addWidget(new QLabel(tr("Zoom")));
3103 //toolBar.addWidget(zoomSpinner);
3105 //toolBar.addWidget(new QLabel(" "));
3106 //toolBar.addSeparator();
3107 //toolBar.addWidget(new QLabel(tr(" Search:")));
3108 //toolBar.addWidget(searchField);
3109 QSizePolicy sizePolicy = new QSizePolicy();
3110 sizePolicy.setHorizontalPolicy(Policy.MinimumExpanding);
3111 QLabel spacer = new QLabel("");
3112 spacer.setSizePolicy(sizePolicy);
3113 toolBar.addWidget(spacer);
3114 //searchField.setInsertPolicy(InsertPolicy.InsertAtTop);
3116 //searchClearButton = toolBar.addAction("Search Clear");
3117 //QIcon searchClearIcon = new QIcon(iconPath+"searchclear.png");
3118 //searchClearButton.setIcon(searchClearIcon);
3119 //searchClearButton.triggered.connect(this, "searchFieldCleared()");
3120 //toggleSearchClearButton(Global.isToolbarButtonVisible("searchClear"));
3122 logger.log(logger.HIGH, "Leaving NeverNote.setupToolBar");
3124 // Update the sychronize button picture
3126 public QMenu createPopupMenu() {
3127 QMenu contextMenu = super.createPopupMenu();
3129 contextMenu.addSeparator();
3130 QAction prevAction = addContextAction("prevArrow", tr("Previous Arrow"));
3131 contextMenu.addAction(prevAction);
3132 prevAction.triggered.connect(this, "togglePrevArrowButton(Boolean)");
3134 QAction nextAction = addContextAction("nextArrow", tr("Next Arrow"));
3135 contextMenu.addAction(nextAction);
3136 nextAction.triggered.connect(this, "toggleNextArrowButton(Boolean)");
3138 QAction upAction = addContextAction("upArrow", tr("Up Arrow"));
3139 contextMenu.addAction(upAction);
3140 upAction.triggered.connect(this, "toggleUpArrowButton(Boolean)");
3142 QAction downAction = addContextAction("downArrow", tr("Down Arrow"));
3143 contextMenu.addAction(downAction);
3144 downAction.triggered.connect(this, "toggleDownArrowButton(Boolean)");
3146 QAction synchronizeAction = addContextAction("synchronize", tr("Synchronize"));
3147 contextMenu.addAction(synchronizeAction);
3148 synchronizeAction.triggered.connect(this, "toggleSynchronizeButton(Boolean)");
3150 QAction printAction = addContextAction("print", tr("Print"));
3151 contextMenu.addAction(printAction);
3152 printAction.triggered.connect(this, "togglePrintButton(Boolean)");
3154 QAction tagAction = addContextAction("tag", tr("Tag"));
3155 contextMenu.addAction(tagAction);
3156 tagAction.triggered.connect(this, "toggleTagButton(Boolean)");
3158 QAction attributeAction = addContextAction("attribute", tr("Attribute"));
3159 contextMenu.addAction(attributeAction);
3160 attributeAction.triggered.connect(this, "toggleAttributeButton(Boolean)");
3162 QAction emailAction = addContextAction("email", tr("Email"));
3163 contextMenu.addAction(emailAction);
3164 emailAction.triggered.connect(this, "toggleEmailButton(Boolean)");
3166 QAction deleteAction = addContextAction("delete", tr("Delete"));
3167 contextMenu.addAction(deleteAction);
3168 deleteAction.triggered.connect(this, "toggleDeleteButton(Boolean)");
3170 QAction newAction = addContextAction("new", tr("Add"));
3171 contextMenu.addAction(newAction);
3172 newAction.triggered.connect(this, "toggleNewButton(Boolean)");
3174 QAction allNotesAction = addContextAction("allNotes", tr("All Notes"));
3175 contextMenu.addAction(allNotesAction);
3176 allNotesAction.triggered.connect(this, "toggleAllNotesButton(Boolean)");
3178 QAction searchClearAction = addContextAction("searchClear", tr("Search Clear"));
3179 contextMenu.addAction(searchClearAction);
3180 searchClearAction.triggered.connect(this, "toggleSearchClearButton(Boolean)");
3185 private QAction addContextAction(String config, String name) {
3186 QAction newAction = new QAction(this);
3187 newAction.setText(name);
3188 newAction.setCheckable(true);
3189 newAction.setChecked(Global.isToolbarButtonVisible(config));
3192 private void togglePrevArrowButton(Boolean toggle) {
3193 prevButton.setVisible(toggle);
3194 Global.saveToolbarButtonsVisible("prevArrow", toggle);
3196 private void toggleNextArrowButton(Boolean toggle) {
3197 nextButton.setVisible(toggle);
3198 Global.saveToolbarButtonsVisible("nextArrow", toggle);
3200 private void toggleUpArrowButton(Boolean toggle) {
3201 upButton.setVisible(toggle);
3202 Global.saveToolbarButtonsVisible("upArrow", toggle);
3204 private void toggleDownArrowButton(Boolean toggle) {
3205 downButton.setVisible(toggle);
3206 Global.saveToolbarButtonsVisible("downArrow", toggle);
3208 private void toggleSynchronizeButton(Boolean toggle) {
3209 synchronizeButton.setVisible(toggle);
3210 Global.saveToolbarButtonsVisible("synchronize", toggle);
3212 private void togglePrintButton(Boolean toggle) {
3213 printButton.setVisible(toggle);
3214 Global.saveToolbarButtonsVisible("print", toggle);
3216 private void toggleTagButton(Boolean toggle) {
3217 tagButton.setVisible(toggle);
3218 Global.saveToolbarButtonsVisible("tag", toggle);
3220 private void toggleAttributeButton(Boolean toggle) {
3221 attributeButton.setVisible(toggle);
3222 Global.saveToolbarButtonsVisible("attribute", toggle);
3224 private void toggleEmailButton(Boolean toggle) {
3225 emailButton.setVisible(toggle);
3226 Global.saveToolbarButtonsVisible("email", toggle);
3228 private void toggleDeleteButton(Boolean toggle) {
3229 deleteButton.setVisible(toggle);
3230 Global.saveToolbarButtonsVisible("delete", toggle);
3232 private void toggleNewButton(Boolean toggle) {
3233 newButton.setVisible(toggle);
3234 Global.saveToolbarButtonsVisible("new", toggle);
3236 private void toggleAllNotesButton(Boolean toggle) {
3237 allNotesButton.setVisible(toggle);
3238 Global.saveToolbarButtonsVisible("allNotes", toggle);
3240 @SuppressWarnings("unused")
3241 private void toggleSearchClearButton(Boolean toggle) {
3242 searchClearButton.setVisible(toggle);
3243 Global.saveToolbarButtonsVisible("searchClear", toggle);
3250 @SuppressWarnings("unused")
3251 private void updateSyncButton() {
3253 if (syncIcons == null) {
3254 syncIcons = new ArrayList<QPixmap>();
3256 synchronizeIconAngle = 0;
3257 QPixmap pix = new QPixmap(iconPath+"synchronize.png");
3259 for (int i=0; i<=360; i++) {
3260 QPixmap rotatedPix = new QPixmap(pix.size());
3261 QPainter p = new QPainter(rotatedPix);
3262 rotatedPix.fill(toolBar.palette().color(ColorRole.Button));
3263 QSize size = pix.size();
3264 p.translate(size.width()/2, size.height()/2);
3267 p.setBackgroundMode(BGMode.OpaqueMode);
3268 p.translate(-size.width()/2, -size.height()/2);
3269 p.drawPixmap(0,0, pix);
3271 syncIcons.add(rotatedPix);
3275 synchronizeIconAngle++;
3276 if (synchronizeIconAngle > 359)
3277 synchronizeIconAngle=0;
3278 synchronizeButton.setIcon(syncIcons.get(synchronizeIconAngle));
3281 // Synchronize with Evernote
3283 private void evernoteSync() {
3284 logger.log(logger.HIGH, "Entering NeverNote.evernoteSync");
3285 if (!Global.isConnected)
3287 if (Global.isConnected)
3288 synchronizeAnimationTimer.start(5);
3289 // synchronizeAnimationTimer.start(200);
3291 logger.log(logger.HIGH, "Leaving NeverNote.evernoteSync");
3293 private void updateQuotaBar() {
3294 long limit = Global.getUploadLimit();
3295 long amount = Global.getUploadAmount();
3296 if (amount>0 && limit>0) {
3297 int percent =(int)(amount*100/limit);
3298 quotaBar.setValue(percent);
3300 quotaBar.setValue(0);
3303 @SuppressWarnings("unused")
3304 private void zoomChanged() {
3305 browserWindow.getBrowser().setZoomFactor(new Double(zoomSpinner.value())/100);
3308 //****************************************************************
3309 //****************************************************************
3310 //* System Tray functions
3311 //****************************************************************
3312 //****************************************************************
3313 private void trayToggleVisible() {
3318 if (windowMaximized)
3325 @SuppressWarnings("unused")
3326 private void trayActivated(QSystemTrayIcon.ActivationReason reason) {
3327 if (reason == QSystemTrayIcon.ActivationReason.DoubleClick) {
3328 String name = QSystemTrayIcon.MessageIcon.resolve(reason.value()).name();
3329 trayToggleVisible();
3334 //***************************************************************
3335 //***************************************************************
3336 //** These functions deal with the trash tree
3337 //***************************************************************
3338 //***************************************************************
3339 // Setup the tree containing the trash.
3340 @SuppressWarnings("unused")
3341 private void trashTreeSelection() {
3342 logger.log(logger.HIGH, "Entering NeverNote.trashTreeSelection");
3344 clearNotebookFilter();
3346 clearAttributeFilter();
3347 clearSavedSearchFilter();
3349 String tempGuid = currentNoteGuid;
3351 // currentNoteGuid = "";
3352 currentNote = new Note();
3353 selectedNoteGUIDs.clear();
3354 listManager.getSelectedNotebooks().clear();
3355 listManager.getSelectedTags().clear();
3356 listManager.setSelectedSavedSearch("");
3357 browserWindow.clear();
3359 // toggle the add buttons
3360 newButton.setEnabled(!newButton.isEnabled());
3361 menuBar.noteAdd.setEnabled(newButton.isEnabled());
3362 menuBar.noteAdd.setVisible(true);
3364 List<QTreeWidgetItem> selections = trashTree.selectedItems();
3365 if (selections.size() == 0) {
3366 currentNoteGuid = trashNoteGuid;
3367 trashNoteGuid = tempGuid;
3368 Global.showDeleted = false;
3369 menuBar.noteRestoreAction.setEnabled(false);
3370 menuBar.noteRestoreAction.setVisible(false);
3373 trashNoteGuid = tempGuid;
3374 currentNoteGuid = trashNoteGuid;
3375 menuBar.noteRestoreAction.setEnabled(true);
3376 menuBar.noteRestoreAction.setVisible(true);
3377 Global.showDeleted = true;
3379 listManager.loadNotesIndex();
3380 noteIndexUpdated(false);
3381 //// browserWindow.setEnabled(newButton.isEnabled());
3382 browserWindow.setReadOnly(!newButton.isEnabled());
3383 logger.log(logger.HIGH, "Leaving NeverNote.trashTreeSelection");
3385 // Empty the trash file
3386 @SuppressWarnings("unused")
3387 private void emptyTrash() {
3388 // browserWindow.clear();
3389 logger.log(logger.EXTREME, "Emptying Trash");
3390 listManager.emptyTrash();
3391 logger.log(logger.EXTREME, "Resetting view after trash empty");
3392 if (trashTree.selectedItems().size() > 0) {
3393 listManager.getSelectedNotebooks().clear();
3394 listManager.getSelectedTags().clear();
3395 listManager.setSelectedSavedSearch("");
3396 newButton.setEnabled(!newButton.isEnabled());
3397 menuBar.noteAdd.setEnabled(newButton.isEnabled());
3398 menuBar.noteAdd.setVisible(true);
3399 browserWindow.clear();
3402 clearNotebookFilter();
3403 clearSavedSearchFilter();
3404 clearAttributeFilter();
3406 Global.showDeleted = false;
3407 menuBar.noteRestoreAction.setEnabled(false);
3408 menuBar.noteRestoreAction.setVisible(false);
3410 listManager.loadNotesIndex();
3411 noteIndexUpdated(false);
3414 // Show/Hide trash window
3415 @SuppressWarnings("unused")
3416 private void toggleTrashWindow() {
3417 logger.log(logger.HIGH, "Entering NeverNote.toggleTrashWindow");
3418 if (trashTree.isVisible())
3422 menuBar.hideTrash.setChecked(trashTree.isVisible());
3424 Global.saveWindowVisible("trashTree", trashTree.isVisible());
3425 logger.log(logger.HIGH, "Leaving NeverNote.trashWindow");
3427 private void clearTrashFilter() {
3428 Global.showDeleted = false;
3429 newButton.setEnabled(true);
3430 menuBar.noteAdd.setEnabled(true);
3431 menuBar.noteAdd.setVisible(true);
3432 trashTree.blockSignals(true);
3433 trashTree.clearSelection();
3434 trashTree.blockSignals(false);
3439 //***************************************************************
3440 //***************************************************************
3441 //** These functions deal with connection settings
3442 //***************************************************************
3443 //***************************************************************
3444 // SyncRunner had a problem and things are disconnected
3445 @SuppressWarnings("unused")
3446 private void remoteErrorDisconnect() {
3447 menuBar.connectAction.setText(tr("Connect"));
3448 menuBar.connectAction.setToolTip(tr("Connect to Evernote"));
3449 menuBar.synchronizeAction.setEnabled(false);
3450 Global.isConnected = false;
3451 synchronizeAnimationTimer.stop();
3454 // Do a manual connect/disconnect
3455 private void remoteConnect() {
3457 logger.log(logger.HIGH, "Entering NeverNote.remoteConnect");
3459 // If we are already connected, we just disconnect
3460 if (Global.isConnected) {
3461 Global.isConnected = false;
3462 syncRunner.enDisconnect();
3463 setupConnectMenuOptions();
3468 OAuthTokenizer tokenizer = new OAuthTokenizer();
3469 AESEncrypter aes = new AESEncrypter();
3471 aes.decrypt(new FileInputStream(Global.getFileManager().getHomeDirFile("oauth.txt")));
3472 } catch (FileNotFoundException e) {
3473 // File not found, so we'll just get empty strings anyway.
3477 if (Global.getProxyValue("url").equals("")) {
3478 System.setProperty("http.proxyHost","") ;
3479 System.setProperty("http.proxyPort", "") ;
3480 System.setProperty("https.proxyHost","") ;
3481 System.setProperty("https.proxyPort", "") ;
3484 System.setProperty("http.proxyHost",Global.getProxyValue("url")) ;
3485 System.setProperty("http.proxyPort", Global.getProxyValue("port")) ;
3486 System.setProperty("https.proxyHost",Global.getProxyValue("url")) ;
3487 System.setProperty("https.proxyPort", Global.getProxyValue("port")) ;
3489 if (Global.getProxyValue("userid").equals("")) {
3490 Authenticator.setDefault(new Authenticator() {
3492 protected PasswordAuthentication getPasswordAuthentication() {
3494 PasswordAuthentication(Global.getProxyValue("userid"),Global.getProxyValue("password").toCharArray());
3500 syncRunner.userStoreUrl = Global.userStoreUrl;
3501 syncRunner.noteStoreUrl = Global.noteStoreUrl;
3502 syncRunner.noteStoreUrlBase = Global.noteStoreUrlBase;
3506 String authString = aes.getString();
3507 if (!authString.equals("")) {
3508 tokenizer.tokenize(authString);
3509 syncRunner.authToken = tokenizer.oauth_token;
3510 syncRunner.enConnect();
3513 Global.isConnected = syncRunner.isConnected;
3515 if (!Global.isConnected) {
3516 OAuthWindow window = new OAuthWindow(logger);
3518 setMessage(window.errorMessage);
3523 setMessage(window.errorMessage);
3526 tokenizer.tokenize(window.response);
3527 if (tokenizer.oauth_token.equals("")) {
3528 setMessage(tr("Invalid authorization token received."));
3531 aes.setString(window.response);
3533 aes.encrypt(new FileOutputStream(Global.getFileManager().getHomeDirFile("oauth.txt")));
3534 } catch (FileNotFoundException e) {
3535 // TODO Auto-generated catch block
3536 e.printStackTrace();
3538 syncRunner.authToken = tokenizer.oauth_token;
3539 syncRunner.enConnect();
3540 Global.isConnected = syncRunner.isConnected;
3542 // Global.username = syncRunner.username;
3544 if (!Global.isConnected)
3547 setupConnectMenuOptions();
3548 logger.log(logger.HIGH, "Leaving NeverNote.remoteConnect");
3552 private void setupConnectMenuOptions() {
3553 logger.log(logger.HIGH, "entering NeverNote.setupConnectMenuOptions");
3554 if (!Global.isConnected) {
3555 menuBar.connectAction.setText(tr("Connect"));
3556 menuBar.connectAction.setToolTip(tr("Connect to Evernote"));
3557 menuBar.synchronizeAction.setEnabled(false);
3559 menuBar.connectAction.setText(tr("Disconnect"));
3560 menuBar.connectAction.setToolTip(tr("Disconnect from Evernote"));
3561 menuBar.synchronizeAction.setEnabled(true);
3563 logger.log(logger.HIGH, "Leaving NeverNote.setupConnectionMenuOptions");
3568 //***************************************************************
3569 //***************************************************************
3570 //** These functions deal with the GUI Attribute tree
3571 //***************************************************************
3572 //***************************************************************
3573 @SuppressWarnings("unused")
3574 private void attributeTreeClicked(QTreeWidgetItem item, Integer integer) {
3576 // clearTagFilter();
3577 // clearNotebookFilter();
3579 // clearSavedSearchFilter();
3581 if (attributeTreeSelected == null || item.nativeId() != attributeTreeSelected.nativeId()) {
3582 if (item.childCount() > 0) {
3583 item.setSelected(false);
3585 Global.createdBeforeFilter.reset();
3586 Global.createdSinceFilter.reset();
3587 Global.changedBeforeFilter.reset();
3588 Global.changedSinceFilter.reset();
3589 Global.containsFilter.reset();
3590 attributeTreeSelected = item;
3591 DateAttributeFilterTable f = null;
3592 f = findDateAttributeFilterTable(item.parent());
3594 f.select(item.parent().indexOfChild(item));
3596 Global.containsFilter.select(item.parent().indexOfChild(item));
3599 listManager.loadNotesIndex();
3600 noteIndexUpdated(false);
3603 attributeTreeSelected = null;
3604 item.setSelected(false);
3605 Global.createdBeforeFilter.reset();
3606 Global.createdSinceFilter.reset();
3607 Global.changedBeforeFilter.reset();
3608 Global.changedSinceFilter.reset();
3609 Global.containsFilter.reset();
3610 listManager.loadNotesIndex();
3611 noteIndexUpdated(false);
3613 // This determines what attribute filter we need, depending upon the selection
3614 private DateAttributeFilterTable findDateAttributeFilterTable(QTreeWidgetItem w) {
3615 if (w.parent() != null && w.childCount() > 0) {
3616 QTreeWidgetItem parent = w.parent();
3617 if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Created &&
3618 w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Since)
3619 return Global.createdSinceFilter;
3620 if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Created &&
3621 w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Before)
3622 return Global.createdBeforeFilter;
3623 if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.LastModified &&
3624 w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Since)
3625 return Global.changedSinceFilter;
3626 if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.LastModified &&
3627 w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Before)
3628 return Global.changedBeforeFilter;
3633 // Show/Hide attribute search window
3634 @SuppressWarnings("unused")
3635 private void toggleAttributesWindow() {
3636 logger.log(logger.HIGH, "Entering NeverNote.toggleAttributesWindow");
3637 if (attributeTree.isVisible())
3638 attributeTree.hide();
3640 attributeTree.show();
3641 menuBar.hideAttributes.setChecked(attributeTree.isVisible());
3643 Global.saveWindowVisible("attributeTree", attributeTree.isVisible());
3644 logger.log(logger.HIGH, "Leaving NeverNote.toggleAttributeWindow");
3646 private void clearAttributeFilter() {
3647 Global.createdBeforeFilter.reset();
3648 Global.createdSinceFilter.reset();
3649 Global.changedBeforeFilter.reset();
3650 Global.changedSinceFilter.reset();
3651 Global.containsFilter.reset();
3652 attributeTreeSelected = null;
3653 attributeTree.blockSignals(true);
3654 attributeTree.clearSelection();
3655 attributeTree.blockSignals(false);
3659 //***************************************************************
3660 //***************************************************************
3661 //** These functions deal with the GUI Note index table
3662 //***************************************************************
3663 //***************************************************************
3664 // Initialize the note list table
3665 private void initializeNoteTable() {
3666 logger.log(logger.HIGH, "Entering NeverNote.initializeNoteTable");
3667 noteTableView.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection);
3668 noteTableView.selectionModel().selectionChanged.connect(this, "noteTableSelection()");
3669 logger.log(logger.HIGH, "Leaving NeverNote.initializeNoteTable");
3671 // Show/Hide trash window
3672 @SuppressWarnings("unused")
3673 private void toggleNoteListWindow() {
3674 logger.log(logger.HIGH, "Entering NeverNote.toggleNoteListWindow");
3675 if (noteTableView.isVisible())
3676 noteTableView.hide();
3678 noteTableView.show();
3679 menuBar.hideNoteList.setChecked(noteTableView.isVisible());
3681 Global.saveWindowVisible("noteList", noteTableView.isVisible());
3682 logger.log(logger.HIGH, "Leaving NeverNote.toggleNoteListWindow");
3684 // Handle the event that a user selects a note from the table
3685 @SuppressWarnings("unused")
3686 private void noteTableSelection() {
3687 logger.log(logger.HIGH, "Entering NeverNote.noteTableSelection");
3691 // If we have more than one selection, then set the merge note action to true.
3692 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
3693 if (selections.size() > 1)
3694 menuBar.noteMergeAction.setEnabled(true);
3696 menuBar.noteMergeAction.setEnabled(false);
3698 // If the ctrl key is pressed, then they are selecting multiple
3699 // entries and we don't want to change the currently viewed note.
3700 if (QApplication.keyboardModifiers().isSet(KeyboardModifier.ControlModifier) &&
3701 QApplication.mouseButtons().isSet(MouseButton.LeftButton))
3704 if (historyGuids.size() == 0) {
3705 historyGuids.add(currentNoteGuid);
3706 historyPosition = 1;
3708 noteTableView.showColumn(Global.noteTableGuidPosition);
3710 if (!Global.isColumnVisible("guid"))
3711 noteTableView.hideColumn(Global.noteTableGuidPosition);
3713 if (selections.size() > 0) {
3715 menuBar.noteDuplicateAction.setEnabled(true);
3716 menuBar.noteOnlineHistoryAction.setEnabled(true);
3717 menuBar.noteMergeAction.setEnabled(true);
3718 selectedNoteGUIDs.clear();
3719 if (selections.size() != 1 || Global.showDeleted) {
3720 menuBar.noteDuplicateAction.setEnabled(false);
3722 if (selections.size() != 1 || !Global.isConnected) {
3723 menuBar.noteOnlineHistoryAction.setEnabled(false);
3725 if (selections.size() == 1) {
3726 menuBar.noteMergeAction.setEnabled(false);
3728 for (int i=0; i<selections.size(); i++) {
3729 int row = selections.get(i).row();
3731 upButton.setEnabled(false);
3733 upButton.setEnabled(true);
3734 if (row < listManager.getNoteTableModel().rowCount()-1)
3735 downButton.setEnabled(true);
3737 downButton.setEnabled(false);
3738 index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
3739 SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
3740 currentNoteGuid = (String)ix.values().toArray()[0];
3741 selectedNoteGUIDs.add(currentNoteGuid);
3745 nextButton.setEnabled(true);
3746 prevButton.setEnabled(true);
3748 int endPosition = historyGuids.size()-1;
3749 for (int j=historyPosition; j<=endPosition; j++) {
3750 historyGuids.remove(historyGuids.size()-1);
3752 historyGuids.add(currentNoteGuid);
3753 historyPosition = historyGuids.size();
3755 if (historyPosition <= 1)
3756 prevButton.setEnabled(false);
3757 if (historyPosition == historyGuids.size())
3758 nextButton.setEnabled(false);
3760 fromHistory = false;
3761 scrollToGuid(currentNoteGuid);
3762 refreshEvernoteNote(true);
3764 logger.log(logger.HIGH, "Leaving NeverNote.noteTableSelection");
3766 // Trigger a refresh when the note db has been updated
3767 private void noteIndexUpdated(boolean reload) {
3768 logger.log(logger.HIGH, "Entering NeverNote.noteIndexUpdated");
3770 refreshEvernoteNoteList();
3771 logger.log(logger.HIGH, "Calling note table reload in NeverNote.noteIndexUpdated() - "+reload);
3772 noteTableView.load(reload);
3773 if (currentNoteGuid == null || currentNoteGuid.equals("")) {
3775 if (noteTableView.proxyModel.sortOrder() == SortOrder.AscendingOrder)
3776 pos = noteTableView.proxyModel.rowCount();
3779 if (noteTableView.proxyModel.rowCount() == 0)
3782 QModelIndex i = noteTableView.proxyModel.index(pos-1, Global.noteTableGuidPosition);
3784 currentNoteGuid = (String)i.data();
3788 if (!noteTableView.isColumnHidden(Global.noteTableGuidPosition))
3790 scrollToGuid(currentNoteGuid);
3791 logger.log(logger.HIGH, "Leaving NeverNote.noteIndexUpdated");
3793 // Called when the list of notes is updated
3794 private void refreshEvernoteNoteList() {
3795 logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNoteList");
3796 browserWindow.setDisabled(false);
3797 if (selectedNoteGUIDs == null)
3798 selectedNoteGUIDs = new ArrayList<String>();
3799 selectedNoteGUIDs.clear(); // clear out old entries
3801 String saveCurrentNoteGuid = new String();
3802 String tempNoteGuid = new String();
3804 historyGuids.clear();
3805 historyPosition = 0;
3806 prevButton.setEnabled(false);
3807 nextButton.setEnabled(false);
3809 if (currentNoteGuid == null)
3810 currentNoteGuid = new String();
3812 //determine current note guid
3813 for (Note note : listManager.getNoteIndex()) {
3814 tempNoteGuid = note.getGuid();
3815 if (currentNoteGuid.equals(tempNoteGuid)) {
3816 saveCurrentNoteGuid = tempNoteGuid;
3820 if (listManager.getNoteIndex().size() == 0) {
3821 currentNoteGuid = "";
3823 browserWindow.clear();
3824 browserWindow.setDisabled(true);
3828 if (Global.showDeleted && listManager.getNoteIndex().size() > 0 && saveCurrentNoteGuid.equals("")) {
3829 currentNoteGuid = listManager.getNoteIndex().get(0).getGuid();
3830 saveCurrentNoteGuid = currentNoteGuid;
3831 refreshEvernoteNote(true);
3834 if (!saveCurrentNoteGuid.equals("")) {
3835 refreshEvernoteNote(false);
3837 currentNoteGuid = "";
3839 reloadTagTree(false);
3841 logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNoteList");
3843 // Called when the previous arrow button is clicked
3844 @SuppressWarnings("unused")
3845 private void previousViewedAction() {
3846 if (!prevButton.isEnabled())
3848 if (historyPosition == 0)
3851 if (historyPosition <= 0)
3853 String historyGuid = historyGuids.get(historyPosition-1);
3855 for (int i=0; i<noteTableView.model().rowCount(); i++) {
3856 QModelIndex modelIndex = noteTableView.model().index(i, Global.noteTableGuidPosition);
3857 if (modelIndex != null) {
3858 SortedMap<Integer, Object> ix = noteTableView.model().itemData(modelIndex);
3859 String tableGuid = (String)ix.values().toArray()[0];
3860 if (tableGuid.equals(historyGuid)) {
3861 noteTableView.selectRow(i);
3867 @SuppressWarnings("unused")
3868 private void nextViewedAction() {
3869 if (!nextButton.isEnabled())
3871 String historyGuid = historyGuids.get(historyPosition);
3874 for (int i=0; i<noteTableView.model().rowCount(); i++) {
3875 QModelIndex modelIndex = noteTableView.model().index(i, Global.noteTableGuidPosition);
3876 if (modelIndex != null) {
3877 SortedMap<Integer, Object> ix = noteTableView.model().itemData(modelIndex);
3878 String tableGuid = (String)ix.values().toArray()[0];
3879 if (tableGuid.equals(historyGuid)) {
3880 noteTableView.selectRow(i);
3886 // Called when the up arrow is clicked
3887 @SuppressWarnings("unused")
3888 private void upAction() {
3889 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
3890 int row = selections.get(0).row();
3892 noteTableView.selectRow(row-1);
3895 // Called when the down arrow is clicked
3896 @SuppressWarnings("unused")
3897 private void downAction() {
3898 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
3899 int row = selections.get(0).row();
3900 int max = listManager.getNoteTableModel().rowCount();
3902 noteTableView.selectRow(row+1);
3905 // Update a tag string for a specific note in the list
3906 @SuppressWarnings("unused")
3907 private void updateListTags(String guid, List<String> tags) {
3908 logger.log(logger.HIGH, "Entering NeverNote.updateListTags");
3909 StringBuffer tagBuffer = new StringBuffer();
3910 for (int i=0; i<tags.size(); i++) {
3911 tagBuffer.append(tags.get(i));
3912 if (i<tags.size()-1)
3913 tagBuffer.append(", ");
3916 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3917 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3918 if (modelIndex != null) {
3919 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3920 String tableGuid = (String)ix.values().toArray()[0];
3921 if (tableGuid.equals(guid)) {
3922 listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition,tagBuffer.toString());
3923 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
3924 noteTableView.proxyModel.invalidate();
3929 logger.log(logger.HIGH, "Leaving NeverNote.updateListTags");
3931 // Update a title for a specific note in the list
3932 @SuppressWarnings("unused")
3933 private void updateListAuthor(String guid, String author) {
3934 logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
3936 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3937 //QModelIndex modelIndex = noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
3938 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3939 if (modelIndex != null) {
3940 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3941 String tableGuid = (String)ix.values().toArray()[0];
3942 if (tableGuid.equals(guid)) {
3943 listManager.getNoteTableModel().setData(i, Global.noteTableAuthorPosition,author);
3944 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
3945 noteTableView.proxyModel.invalidate();
3951 logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
3953 private void updateListNoteNotebook(String guid, String notebook) {
3954 logger.log(logger.HIGH, "Entering NeverNote.updateListNoteNotebook");
3955 listManager.getNoteTableModel().updateNoteSyncStatus(guid, false);
3956 logger.log(logger.HIGH, "Leaving NeverNote.updateListNoteNotebook");
3958 // Update a title for a specific note in the list
3959 @SuppressWarnings("unused")
3960 private void updateListSourceUrl(String guid, String url) {
3961 logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
3963 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3964 //QModelIndex modelIndex = noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
3965 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3966 if (modelIndex != null) {
3967 // SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex);
3968 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3969 String tableGuid = (String)ix.values().toArray()[0];
3970 if (tableGuid.equals(guid)) {
3971 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
3972 listManager.getNoteTableModel().setData(i, Global.noteTableSourceUrlPosition,url);
3973 noteTableView.proxyModel.invalidate();
3978 logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
3980 @SuppressWarnings("unused")
3981 private void updateListGuid(String oldGuid, String newGuid) {
3982 logger.log(logger.HIGH, "Entering NeverNote.updateListTitle");
3984 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
3985 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
3986 if (modelIndex != null) {
3987 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
3988 String tableGuid = (String)ix.values().toArray()[0];
3989 if (tableGuid.equals(oldGuid)) {
3990 listManager.getNoteTableModel().setData(i, Global.noteTableGuidPosition,newGuid);
3991 //listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
3996 logger.log(logger.HIGH, "Leaving NeverNote.updateListTitle");
3998 private void updateListTagName(String guid) {
3999 logger.log(logger.HIGH, "Entering NeverNote.updateTagName");
4001 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
4002 if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) {
4003 String newName = listManager.getTagNamesForNote(listManager.getNoteIndex().get(j));
4005 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4006 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4007 if (modelIndex != null) {
4008 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4009 String noteGuid = (String)ix.values().toArray()[0];
4010 if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) {
4011 listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition, newName);
4012 i=listManager.getNoteTableModel().rowCount();
4018 logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebook");
4020 private void removeListTagName(String guid) {
4021 logger.log(logger.HIGH, "Entering NeverNote.updateTagName");
4023 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
4024 if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) {
4025 for (int i=listManager.getNoteIndex().get(j).getTagGuids().size()-1; i>=0; i--) {
4026 if (listManager.getNoteIndex().get(j).getTagGuids().get(i).equals(guid))
4027 listManager.getNoteIndex().get(j).getTagGuids().remove(i);
4030 String newName = listManager.getTagNamesForNote(listManager.getNoteIndex().get(j));
4031 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4032 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4033 if (modelIndex != null) {
4034 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4035 String noteGuid = (String)ix.values().toArray()[0];
4036 if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) {
4037 listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition, newName);
4038 i=listManager.getNoteTableModel().rowCount();
4044 logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebook");
4046 private void updateListNotebookName(String oldName, String newName) {
4047 logger.log(logger.HIGH, "Entering NeverNote.updateListNotebookName");
4049 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4050 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableNotebookPosition);
4051 if (modelIndex != null) {
4052 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4053 String tableName = (String)ix.values().toArray()[0];
4054 if (tableName.equalsIgnoreCase(oldName)) {
4055 listManager.getNoteTableModel().setData(i, Global.noteTableNotebookPosition, newName);
4059 logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebookName");
4061 @SuppressWarnings("unused")
4062 private void updateListDateCreated(String guid, QDateTime date) {
4063 logger.log(logger.HIGH, "Entering NeverNote.updateListDateCreated");
4065 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4066 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4067 if (modelIndex != null) {
4068 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4069 String tableGuid = (String)ix.values().toArray()[0];
4070 if (tableGuid.equals(guid)) {
4071 listManager.getNoteTableModel().setData(i, Global.noteTableCreationPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
4072 noteTableView.proxyModel.invalidate();
4077 logger.log(logger.HIGH, "Leaving NeverNote.updateListDateCreated");
4079 @SuppressWarnings("unused")
4080 private void updateListDateSubject(String guid, QDateTime date) {
4081 logger.log(logger.HIGH, "Entering NeverNote.updateListDateSubject");
4083 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4084 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4085 if (modelIndex != null) {
4086 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4087 String tableGuid = (String)ix.values().toArray()[0];
4088 if (tableGuid.equals(guid)) {
4089 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
4090 listManager.getNoteTableModel().setData(i, Global.noteTableSubjectDatePosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
4091 noteTableView.proxyModel.invalidate();
4096 logger.log(logger.HIGH, "Leaving NeverNote.updateListDateCreated");
4098 private void updateListDateChanged(String guid, QDateTime date) {
4099 logger.log(logger.HIGH, "Entering NeverNote.updateListDateChanged");
4101 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4102 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4103 if (modelIndex != null) {
4104 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4105 String tableGuid = (String)ix.values().toArray()[0];
4106 if (tableGuid.equals(guid)) {
4107 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
4108 listManager.getNoteTableModel().setData(i, Global.noteTableChangedPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
4113 logger.log(logger.HIGH, "Leaving NeverNote.updateListDateChanged");
4115 private void updateListDateChanged() {
4116 logger.log(logger.HIGH, "Entering NeverNote.updateListDateChanged");
4117 QDateTime date = new QDateTime(QDateTime.currentDateTime());
4118 updateListDateChanged(currentNoteGuid, date);
4119 logger.log(logger.HIGH, "Leaving NeverNote.updateListDateChanged");
4122 private void scrollToCurrentGuid() {
4123 //scrollToGuid(currentNoteGuid);
4124 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
4125 if (selections.size() == 0)
4127 QModelIndex index = selections.get(0);
4128 int row = selections.get(0).row();
4129 String guid = (String)index.model().index(row, Global.noteTableGuidPosition).data();
4132 // Scroll to the current GUID in tthe list.
4133 // Scroll to a particular index item
4134 private void scrollToGuid(String guid) {
4135 if (currentNote == null || guid == null)
4137 if (currentNote.isActive() && Global.showDeleted) {
4138 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
4139 if (!listManager.getNoteIndex().get(i).isActive()) {
4140 currentNote = listManager.getNoteIndex().get(i);
4141 currentNoteGuid = currentNote.getGuid();
4142 i = listManager.getNoteIndex().size();
4146 if (!currentNote.isActive() && !Global.showDeleted) {
4147 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
4148 if (listManager.getNoteIndex().get(i).isActive()) {
4149 currentNote = listManager.getNoteIndex().get(i);
4150 currentNoteGuid = currentNote.getGuid();
4151 i = listManager.getNoteIndex().size();
4156 for (int i=0; i<noteTableView.model().rowCount(); i++) {
4157 index = noteTableView.model().index(i, Global.noteTableGuidPosition);
4158 if (currentNoteGuid.equals(index.data())) {
4159 // noteTableView.selectionModel().blockSignals(true);
4160 noteTableView.selectRow(i);
4161 // noteTableView.selectionModel().blockSignals(false);
4162 noteTableView.scrollTo(index, ScrollHint.EnsureVisible); // This should work, but it doesn't
4163 i=listManager.getNoteTableModel().rowCount();
4166 noteTableView.repaint();
4168 // Show/Hide columns
4169 private void showColumns() {
4170 noteTableView.setColumnHidden(Global.noteTableCreationPosition, !Global.isColumnVisible("dateCreated"));
4171 noteTableView.setColumnHidden(Global.noteTableChangedPosition, !Global.isColumnVisible("dateChanged"));
4172 noteTableView.setColumnHidden(Global.noteTableSubjectDatePosition, !Global.isColumnVisible("dateSubject"));
4173 noteTableView.setColumnHidden(Global.noteTableAuthorPosition, !Global.isColumnVisible("author"));
4174 noteTableView.setColumnHidden(Global.noteTableSourceUrlPosition, !Global.isColumnVisible("sourceUrl"));
4175 noteTableView.setColumnHidden(Global.noteTableTagPosition, !Global.isColumnVisible("tags"));
4176 noteTableView.setColumnHidden(Global.noteTableNotebookPosition, !Global.isColumnVisible("notebook"));
4177 noteTableView.setColumnHidden(Global.noteTableSynchronizedPosition, !Global.isColumnVisible("synchronized"));
4178 noteTableView.setColumnHidden(Global.noteTableGuidPosition, !Global.isColumnVisible("guid"));
4179 noteTableView.setColumnHidden(Global.noteTableThumbnailPosition, !Global.isColumnVisible("thumbnail"));
4180 noteTableView.setColumnHidden(Global.noteTableTitlePosition, !Global.isColumnVisible("title"));
4181 noteTableView.setColumnHidden(Global.noteTablePinnedPosition, !Global.isColumnVisible("pinned"));
4183 // Title color has changed
4184 @SuppressWarnings("unused")
4185 private void titleColorChanged(Integer color) {
4186 logger.log(logger.HIGH, "Entering NeverNote.titleColorChanged");
4189 QColor backgroundColor = new QColor();
4190 QColor foregroundColor = new QColor(QColor.black);
4191 backgroundColor.setRgb(color);
4193 if (backgroundColor.rgb() == QColor.black.rgb() || backgroundColor.rgb() == QColor.blue.rgb())
4194 foregroundColor.setRgb(QColor.white.rgb());
4196 if (selectedNoteGUIDs.size() == 0)
4197 selectedNoteGUIDs.add(currentNoteGuid);
4199 for (int j=0; j<selectedNoteGUIDs.size(); j++) {
4200 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4201 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4202 if (modelIndex != null) {
4203 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4204 String tableGuid = (String)ix.values().toArray()[0];
4205 if (tableGuid.equals(selectedNoteGUIDs.get(j))) {
4206 for (int k=0; k<Global.noteTableColumnCount; k++) {
4207 listManager.getNoteTableModel().setData(i, k, backgroundColor, Qt.ItemDataRole.BackgroundRole);
4208 listManager.getNoteTableModel().setData(i, k, foregroundColor, Qt.ItemDataRole.ForegroundRole);
4209 listManager.updateNoteTitleColor(selectedNoteGUIDs.get(j), backgroundColor.rgb());
4211 i=listManager.getNoteTableModel().rowCount();
4216 logger.log(logger.HIGH, "Leaving NeverNote.titleColorChanged");
4218 // A note has been pinned or unpinned
4219 @SuppressWarnings("unused")
4220 private void notePinned() {
4221 logger.log(logger.EXTREME, "Entering NeverNote.notePinned()");
4224 for (int j=0; j<selectedNoteGUIDs.size(); j++) {
4225 NoteMetadata meta = listManager.getNoteMetadata().get(selectedNoteGUIDs.get(j));
4226 boolean pinned = !meta.isPinned();
4227 meta.setPinned(pinned); // Toggle the pinned/unpinned
4229 // Update the list & table
4230 listManager.updateNoteMetadata(meta);
4231 noteTableView.proxyModel.addGuid(selectedNoteGUIDs.get(j), meta);
4234 logger.log(logger.EXTREME, "Leaving NeverNote.setNoteDirty()");
4236 // Wide list was chosen
4237 public void narrowListView() {
4238 saveNoteColumnPositions();
4239 saveNoteIndexWidth();
4241 int sortCol = noteTableView.proxyModel.sortColumn();
4242 int sortOrder = noteTableView.proxyModel.sortOrder().value();
4243 Global.setSortColumn(sortCol);
4244 Global.setSortOrder(sortOrder);
4246 Global.setListView(Global.View_List_Narrow);
4248 menuBar.wideListView.blockSignals(true);
4249 menuBar.narrowListView.blockSignals(true);
4251 menuBar.wideListView.setChecked(false);
4252 menuBar.narrowListView.setChecked(true);
4254 menuBar.wideListView.blockSignals(false);
4255 menuBar.narrowListView.blockSignals(false);
4257 mainLeftRightSplitter.addWidget(noteTableView);
4258 mainLeftRightSplitter.addWidget(browserWindow);
4259 restoreWindowState(false);
4260 noteTableView.repositionColumns();
4261 noteTableView.resizeColumnWidths();
4262 noteTableView.resizeRowHeights();
4264 sortCol = Global.getSortColumn();
4265 sortOrder = Global.getSortOrder();
4266 noteTableView.proxyModel.blocked = true;
4267 noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder));
4268 noteTableView.proxyModel.blocked = false;
4272 noteTableView.load(false);
4273 refreshEvernoteNote(true);
4274 scrollToCurrentGuid();
4276 public void wideListView() {
4277 int sortCol = noteTableView.proxyModel.sortColumn();
4278 int sortOrder = noteTableView.proxyModel.sortOrder().value();
4279 Global.setSortColumn(sortCol);
4280 Global.setSortOrder(sortOrder);
4283 saveNoteColumnPositions();
4284 saveNoteIndexWidth();
4285 Global.setListView(Global.View_List_Wide);
4287 menuBar.wideListView.blockSignals(true);
4288 menuBar.narrowListView.blockSignals(true);
4290 menuBar.wideListView.setChecked(true);
4291 menuBar.narrowListView.setChecked(false);
4293 menuBar.wideListView.blockSignals(false);
4294 menuBar.narrowListView.blockSignals(false);
4295 browserIndexSplitter.setVisible(true);
4296 browserIndexSplitter.addWidget(noteTableView);
4297 browserIndexSplitter.addWidget(browserWindow);
4298 restoreWindowState(false);
4299 noteTableView.repositionColumns();
4300 noteTableView.resizeColumnWidths();
4301 noteTableView.resizeRowHeights();
4303 sortCol = Global.getSortColumn();
4304 sortOrder = Global.getSortOrder();
4305 noteTableView.proxyModel.blocked = true;
4306 noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder));
4307 noteTableView.proxyModel.blocked = false;
4310 noteTableView.load(false);
4311 scrollToCurrentGuid();
4313 // Sort order for the notebook has changed
4314 public void tableSortOrderChanged(Integer column, Integer order) {
4316 // Find what notebook (if any) is selected. We ignore stacks & the "All Notebooks".
4317 List<QTreeWidgetItem> selectedNotebook = notebookTree.selectedItems();
4318 if (selectedNotebook.size() > 0 && !selectedNotebook.get(0).text(0).equalsIgnoreCase("All Notebooks") && !selectedNotebook.get(0).text(2).equalsIgnoreCase("STACK")) {
4319 QTreeWidgetItem currentSelectedNotebook = selectedNotebook.get(0);
4321 notebook = currentSelectedNotebook.text(2);
4322 conn.getNotebookTable().setSortOrder(notebook, column, order);
4326 //***************************************************************
4327 @SuppressWarnings("unused")
4328 private void evernoteLinkClick(String syncGuid, String locGuid) {
4330 if (conn.getNoteTable().guidExists(syncGuid)) {
4333 // If we didn't find it via the synchronized guid, look under the local guid
4334 // Iwe don't find it there, look to see if the GUID is posted under the local GUID, but was
4335 // later synchronized (that causes the guid to change so we need to find the new one).
4336 if (conn.getNoteTable().guidExists(locGuid))
4339 guid = conn.getNoteTable().findAlternateGuid(locGuid);
4342 openExternalEditor(guid);
4346 //If we've gotten this far, we can't find the note
4347 QMessageBox.information(this, tr("Note Not Found"), tr("Sorry, but I can't"+
4348 " seem to find that note."));
4350 //***************************************************************
4351 //***************************************************************
4352 //** External editor window functions
4353 //***************************************************************
4354 //***************************************************************
4355 private void listDoubleClick() {
4357 openExternalEditor(currentNoteGuid);
4359 private void openExternalEditor(String guid) {
4361 if (externalWindows.containsKey(guid)) {
4362 externalWindows.get(guid).raise();
4365 Note note = conn.getNoteTable().getNote(guid, true, true, false, true, true);
4366 // We have a new external editor to create
4367 QIcon appIcon = new QIcon(iconPath+"nevernote.png");
4368 ExternalBrowse newBrowser = new ExternalBrowse(conn);
4369 newBrowser.setWindowIcon(appIcon);
4370 externalWindows.put(guid, newBrowser);
4371 showEditorButtons(newBrowser.getBrowserWindow());
4372 loadNoteBrowserInformation(newBrowser.getBrowserWindow(), guid, note);
4373 setupBrowserWindowListeners(newBrowser.getBrowserWindow(), false);
4374 newBrowser.windowClosing.connect(this, "externalWindowClosing(String)");
4375 //newBrowser.getBrowserWindow().noteSignal.titleChanged.connect(this, "externalWindowTitleEdited(String, String)");
4376 newBrowser.getBrowserWindow().noteSignal.tagsChanged.connect(this, "externalWindowTagsEdited(String, List)");
4377 newBrowser.contentsChanged.connect(this, "saveNoteExternalBrowser(String, String, Boolean, BrowserWindow)");
4378 newBrowser.getBrowserWindow().blockApplication.connect(this, "blockApplication(BrowserWindow)");
4379 newBrowser.getBrowserWindow().unblockApplication.connect(this, "unblockApplication()");
4381 browserWindow.noteSignal.tagsChanged.connect(newBrowser, "updateTags(String, List)");
4382 browserWindow.noteSignal.titleChanged.connect(newBrowser, "updateTitle(String, String)");
4383 browserWindow.noteSignal.notebookChanged.connect(newBrowser, "updateNotebook(String, String)");
4387 @SuppressWarnings({ "rawtypes", "unused" })
4388 private void externalWindowTagsEdited(String guid, List values) {
4389 StringBuffer line = new StringBuffer(100);
4390 for (int i=0; i<values.size(); i++) {
4392 line.append(Global.tagDelimeter+" ");
4393 line.append(values.get(i));
4395 if (guid.equals(currentNoteGuid)) {
4396 browserWindow.setTag(line.toString());
4399 @SuppressWarnings("unused")
4400 private void externalWindowClosing(String guid) {
4401 externalWindows.remove(guid);
4406 //***************************************************************
4407 //***************************************************************
4408 //** These functions deal with Note specific things
4409 //***************************************************************
4410 //***************************************************************
4411 private void setNoteDirty() {
4412 logger.log(logger.EXTREME, "Entering NeverNote.setNoteDirty()");
4414 // Find if the note is being edited externally. If it is, update it.
4415 if (externalWindows.containsKey(currentNoteGuid)) {
4416 QTextCodec codec = QTextCodec.codecForName("UTF-8");
4417 QByteArray unicode = codec.fromUnicode(browserWindow.getContent());
4418 ExternalBrowse window = externalWindows.get(currentNoteGuid);
4419 window.getBrowserWindow().setContent(unicode);
4422 // If the note is dirty, then it is unsynchronized by default.
4426 // Set the note as dirty and check if its status is synchronized in the display table
4428 if (listManager.getNoteMetadata().containsKey(currentNoteGuid) &&
4429 listManager.getNoteMetadata().get(currentNoteGuid).isDirty()) {
4433 // If this wasn't already marked as unsynchronized, then we need to update the table
4434 listManager.getNoteTableModel().updateNoteSyncStatus(currentNoteGuid, false);
4435 // listManager.getUnsynchronizedNotes().add(currentNoteGuid);
4436 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4437 QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4438 if (modelIndex != null) {
4439 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4440 String tableGuid = (String)ix.values().toArray()[0];
4441 if (tableGuid.equals(currentNoteGuid)) {
4442 listManager.getNoteTableModel().proxyModel.setData(i, Global.noteTableSynchronizedPosition, "false");
4448 logger.log(logger.EXTREME, "Leaving NeverNote.setNoteDirty()");
4450 @SuppressWarnings("unused")
4451 private void saveNoteExternalBrowser(String guid, String content, Boolean save, BrowserWindow browser) {
4452 QTextCodec codec = QTextCodec.codecForName("UTF-8");
4453 QByteArray unicode = codec.fromUnicode(content);
4454 noteCache.remove(guid);
4455 noteCache.put(guid, unicode.toString());
4456 if (guid.equals(currentNoteGuid)) {
4458 browserWindow.setContent(unicode);
4461 thumbnailRunner.addWork("GENERATE "+ guid);
4462 saveNote(guid, browser);
4466 private void saveNote() {
4468 saveNote(currentNoteGuid, browserWindow);
4469 thumbnailRunner.addWork("GENERATE "+ currentNoteGuid);
4473 private void saveNote(String guid, BrowserWindow window) {
4474 logger.log(logger.EXTREME, "Inside NeverNote.saveNote()");
4477 logger.log(logger.EXTREME, "Saving to cache");
4478 QTextCodec codec = QTextCodec.codecForLocale();
4479 // QTextDecoder decoder = codec.makeDecoder();
4480 codec = QTextCodec.codecForName("UTF-8");
4481 QByteArray unicode = codec.fromUnicode(window.getContent());
4482 noteCache.put(guid, unicode.toString());
4484 logger.log(logger.EXTREME, "updating list manager");
4485 listManager.updateNoteContent(guid, window.getContent());
4486 logger.log(logger.EXTREME, "Updating title");
4487 listManager.updateNoteTitle(guid, window.getTitle());
4488 updateListDateChanged();
4490 logger.log(logger.EXTREME, "Looking through note index for refreshed note");
4491 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
4492 if (listManager.getNoteIndex().get(i).getGuid().equals(guid)) {
4493 currentNote = listManager.getNoteIndex().get(i);
4494 i = listManager.getNoteIndex().size();
4499 // Get a note from Evernote (and put it in the browser)
4500 private void refreshEvernoteNote(boolean reload) {
4501 logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNote");
4503 if (Global.disableViewing) {
4504 browserWindow.setEnabled(false);
4509 if (Global.showDeleted || currentNoteGuid == null || currentNoteGuid.equals(""))
4511 Global.cryptCounter =0;
4513 browserWindow.setReadOnly(true);
4520 browserWindow.loadingData(true);
4522 currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true);
4523 if (currentNote == null) {
4527 loadNoteBrowserInformation(browserWindow, currentNoteGuid, currentNote);
4530 private void loadNoteBrowserInformation(BrowserWindow browser, String guid, Note note) {
4531 NoteFormatter formatter = new NoteFormatter(logger, conn, tempFiles);
4532 formatter.setNote(note, Global.pdfPreview());
4533 formatter.setHighlight(listManager.getEnSearch());
4535 if (!noteCache.containsKey(guid)) {
4536 js = new QByteArray();
4537 // We need to prepend the note with <HEAD></HEAD> or encoded characters are ugly
4538 js.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
4539 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>");
4540 js.append("<style type=\"text/css\">en-hilight { background-color: rgb(255,255,0) }</style>");
4541 js.append("<style> img { height:auto; width:auto; max-height:auto; max-width:100%; }</style>");
4542 if (Global.displayRightToLeft())
4543 js.append("<style> body { direction:rtl; }</style>");
4544 js.append("<style type=\"text/css\">en-spell { text-decoration: none; border-bottom: dotted 1px #cc0000; }</style>");
4545 js.append("</head>");
4546 formatter.setNote(note, Global.pdfPreview());
4547 js.append(formatter.rebuildNoteHTML());
4548 js.append("</HTML>");
4549 js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml.dtd'>", "");
4550 js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml2.dtd'>", "");
4551 js.replace("<?xml version='1.0' encoding='UTF-8'?>", "");
4552 // if (Global.enableHTMLEntitiesFix) {
4553 // browser.getBrowser().setContent(new QByteArray(StringEscapeUtils.unescapeHtml(js.toString())));
4555 browser.setContent(js);
4556 noteCache.put(guid, js.toString());
4558 if (formatter.resourceError)
4559 resourceErrorMessage();
4560 if (formatter.formatError) {
4562 QMessageBox.information(this, tr("Error"),
4563 tr("NixNote had issues formatting this note." +
4564 " To protect your data this note is being marked as read-only."));
4567 readOnly = formatter.readOnly;
4568 inkNote = formatter.inkNote;
4570 readOnlyCache.put(guid, true);
4572 inkNoteCache.put(guid, true);
4574 logger.log(logger.HIGH, "Note content is being pulled from the cache");
4575 String cachedContent = formatter.modifyCachedTodoTags(noteCache.get(guid));
4576 js = new QByteArray(cachedContent);
4577 browser.setContent(js);
4578 if (readOnlyCache.containsKey(guid))
4580 if (inkNoteCache.containsKey(guid))
4583 if (conn.getNoteTable().isThumbnailNeeded(guid)) {
4584 thumbnailHTMLReady(guid, js, Global.calculateThumbnailZoom(js.toString()));
4586 if (readOnly || inkNote ||
4587 (note.getAttributes() != null && note.getAttributes().getContentClass() != null && note.getAttributes().getContentClass() != ""))
4588 browser.getBrowser().page().setContentEditable(false); // We don't allow editing of ink notes
4590 browser.getBrowser().page().setContentEditable(true);
4591 browser.setReadOnly(readOnly);
4592 deleteButton.setEnabled(!readOnly);
4593 tagButton.setEnabled(!readOnly);
4594 menuBar.noteDelete.setEnabled(!readOnly);
4595 menuBar.noteTags.setEnabled(!readOnly);
4596 browser.setNote(note);
4598 if (note != null && note.getNotebookGuid() != null &&
4599 conn.getNotebookTable().isLinked(note.getNotebookGuid())) {
4600 deleteButton.setEnabled(false);
4601 menuBar.notebookDeleteAction.setEnabled(false);
4603 deleteButton.setEnabled(true);
4604 menuBar.notebookDeleteAction.setEnabled(true);
4607 // Build a list of non-closed notebooks
4608 List<Notebook> nbooks = new ArrayList<Notebook>();
4609 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
4610 boolean found=false;
4611 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
4612 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
4616 nbooks.add(listManager.getNotebookIndex().get(i));
4619 browser.setTitle(note.getTitle());
4620 browser.setTag(getTagNamesForNote(note));
4621 browser.setAuthor(note.getAttributes().getAuthor());
4623 browser.setAltered(note.getUpdated());
4624 browser.setCreation(note.getCreated());
4625 if (note.getAttributes().getSubjectDate() > 0)
4626 browser.setSubjectDate(note.getAttributes().getSubjectDate());
4628 browser.setSubjectDate(note.getCreated());
4629 browser.setUrl(note.getAttributes().getSourceURL());
4631 FilterEditorTags tagFilter = new FilterEditorTags(conn, logger);
4632 List<Tag> tagList = tagFilter.getValidTags(note);
4633 browser.setAllTags(tagList);
4635 browser.setCurrentTags(note.getTagNames());
4639 browser.loadingData(false);
4640 if (thumbnailViewer.isActiveWindow())
4643 FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger);
4644 browser.setNotebookList(notebookFilter.getValidNotebooks(note, listManager.getNotebookIndex()));
4647 logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNote");
4649 // Save a generated thumbnail
4650 private void toggleNoteInformation() {
4651 logger.log(logger.HIGH, "Entering NeverNote.toggleNoteInformation");
4652 browserWindow.toggleInformation();
4653 menuBar.noteAttributes.setChecked(browserWindow.isExtended());
4654 Global.saveWindowVisible("noteInformation", browserWindow.isExtended());
4655 logger.log(logger.HIGH, "Leaving NeverNote.toggleNoteInformation");
4657 // Listener triggered when a print button is pressed
4658 @SuppressWarnings("unused")
4659 private void printNote() {
4660 logger.log(logger.HIGH, "Entering NeverNote.printNote");
4662 QPrintDialog dialog = new QPrintDialog();
4663 if (dialog.exec() == QDialog.DialogCode.Accepted.value()) {
4664 QPrinter printer = dialog.printer();
4665 browserWindow.getBrowser().print(printer);
4667 logger.log(logger.HIGH, "Leaving NeverNote.printNote");
4670 // Listener triggered when the email button is pressed
4671 @SuppressWarnings("unused")
4672 private void emailNote() {
4673 logger.log(logger.HIGH, "Entering NeverNote.emailNote");
4675 if (Desktop.isDesktopSupported()) {
4676 Desktop desktop = Desktop.getDesktop();
4678 String text2 = browserWindow.getContentsToEmail();
4679 QUrl url = new QUrl("mailto:");
4680 url.addQueryItem("subject", currentNote.getTitle());
4681 // url.addQueryItem("body", QUrl.toPercentEncoding(text2).toString());
4682 url.addQueryItem("body", text2);
4683 QDesktopServices.openUrl(url);
4687 if (desktop.isSupported(Desktop.Action.MAIL)) {
4688 URI uriMailTo = null;
4690 //String text = browserWindow.getBrowser().page().currentFrame().toPlainText();
4691 String text = browserWindow.getContentsToEmail();
4692 //text = "<b>" +text +"</b>";
4693 uriMailTo = new URI("mailto", "&SUBJECT="+currentNote.getTitle()
4694 +"&BODY=" +text, null);
4695 uriMailTo = new URI("mailto", "&SUBJECT="+currentNote.getTitle()
4696 +"&ATTACHMENT=d:/test.pdf", null);
4697 desktop.mail(uriMailTo);
4698 } catch (URISyntaxException e) {
4699 e.printStackTrace();
4700 } catch (IOException e) {
4701 e.printStackTrace();
4708 logger.log(logger.HIGH, "Leaving NeverNote.emailNote");
4710 // Reindex all notes
4711 @SuppressWarnings("unused")
4712 private void fullReindex() {
4713 logger.log(logger.HIGH, "Entering NeverNote.fullReindex");
4714 indexRunner.addWork("REINDEXALL");
4715 setMessage(tr("Database will be reindexed."));
4716 logger.log(logger.HIGH, "Leaving NeverNote.fullReindex");
4718 // Listener when a user wants to reindex a specific note
4719 @SuppressWarnings("unused")
4720 private void reindexNote() {
4721 logger.log(logger.HIGH, "Entering NeverNote.reindexNote");
4722 for (int i=0; i<selectedNoteGUIDs.size(); i++) {
4723 indexRunner.addWork("REINDEXNOTE "+selectedNoteGUIDs.get(i));
4725 if (selectedNotebookGUIDs.size() > 1)
4726 setMessage(tr("Notes will be reindexed."));
4728 setMessage(tr("Note will be reindexed."));
4729 logger.log(logger.HIGH, "Leaving NeverNote.reindexNote");
4732 @SuppressWarnings("unused")
4733 private void deleteNote() {
4734 logger.log(logger.HIGH, "Entering NeverNote.deleteNote");
4735 if (currentNote == null)
4737 if (currentNoteGuid.equals(""))
4739 String title = null;
4740 if (selectedNoteGUIDs.size() == 1)
4741 title = conn.getNoteTable().getNote(selectedNoteGUIDs.get(0),false,false,false,false,false).getTitle();
4743 // If we are deleting non-trash notes
4744 if (currentNote.isActive()) {
4745 if (Global.verifyDelete()) {
4747 if (selectedNoteGUIDs.size() > 1) {
4748 msg = new String(tr("Delete ") +selectedNoteGUIDs.size() +" notes?");
4751 msg = new String(tr("Delete note \"") +title +"\"?");
4753 msg = new String(tr("Delete note selected note?"));
4755 if (QMessageBox.question(this, tr("Confirmation"), msg,
4756 QMessageBox.StandardButton.Yes,
4757 QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) {
4761 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals(""))
4762 selectedNoteGUIDs.add(currentNoteGuid);
4763 for (int i=0; i<selectedNoteGUIDs.size(); i++) {
4764 listManager.deleteNote(selectedNoteGUIDs.get(i));
4767 // If we are deleting from the trash.
4768 if (Global.verifyDelete()) {
4770 if (selectedNoteGUIDs.size() > 1) {
4771 msg = new String(tr("Permanently delete ") +selectedNoteGUIDs.size() +" notes?");
4774 msg = new String(tr("Permanently delete note \"") +title +"\"?");
4776 msg = new String(tr("Permanently delete note selected note?"));
4778 if (QMessageBox.question(this, "Confirmation", msg,
4779 QMessageBox.StandardButton.Yes,
4780 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
4784 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals(""))
4785 selectedNoteGUIDs.add(currentNoteGuid);
4786 for (int i=selectedNoteGUIDs.size()-1; i>=0; i--) {
4787 for (int j=listManager.getNoteTableModel().rowCount()-1; j>=0; j--) {
4788 QModelIndex modelIndex = listManager.getNoteTableModel().index(j, Global.noteTableGuidPosition);
4789 if (modelIndex != null) {
4790 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4791 String tableGuid = (String)ix.values().toArray()[0];
4792 if (tableGuid.equals(selectedNoteGUIDs.get(i))) {
4793 listManager.getNoteTableModel().removeRow(j);
4798 listManager.expungeNote(selectedNoteGUIDs.get(i));
4801 currentNoteGuid = "";
4802 listManager.loadNotesIndex();
4803 noteIndexUpdated(false);
4804 refreshEvernoteNote(true);
4805 scrollToGuid(currentNoteGuid);
4806 logger.log(logger.HIGH, "Leaving NeverNote.deleteNote");
4809 @SuppressWarnings("unused")
4810 private void addNote() {
4811 logger.log(logger.HIGH, "Inside NeverNote.addNote");
4812 // browserWindow.setEnabled(true);
4813 browserWindow.setReadOnly(false);
4815 Calendar currentTime = new GregorianCalendar();
4816 StringBuffer noteString = new StringBuffer(100);
4817 noteString.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
4818 "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">\n" +
4821 if (Global.overrideDefaultFont()) {
4822 noteString.append("<font face=\"" +Global.getDefaultFont() +"\" >");
4823 noteString.append("<span style=\"font-size:" +Global.getDefaultFontSize() +"pt;\">");
4824 noteString.append("<br clear=\"none\" />\n");
4825 noteString.append("</span>\n</font>\n");
4827 noteString.append("<br clear=\"none\" />\n");
4828 noteString.append("</en-note>");
4830 Long l = new Long(currentTime.getTimeInMillis());
4831 String randint = new String(Long.toString(l));
4833 // Find a notebook. We first look for a selected notebook (the "All Notebooks" one doesn't count).
4835 // for the first non-archived notebook. Finally, if nothing else we
4836 // pick the first notebook in the list.
4837 String notebook = null;
4838 listManager.getNotebookIndex().get(0).getGuid();
4839 List<QTreeWidgetItem> selectedNotebook = notebookTree.selectedItems();
4840 if (selectedNotebook.size() > 0 && !selectedNotebook.get(0).text(0).equalsIgnoreCase("All Notebooks") && !selectedNotebook.get(0).text(2).equalsIgnoreCase("STACK")) {
4841 QTreeWidgetItem currentSelectedNotebook = selectedNotebook.get(0);
4842 notebook = currentSelectedNotebook.text(2);
4844 boolean found = false;
4845 List<Notebook> goodNotebooks = new ArrayList<Notebook>();
4846 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
4847 boolean match = false;
4848 for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
4849 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid())) {
4851 j = listManager.getArchiveNotebookIndex().size();
4855 //goodNotebooks.add(listManager.getNotebookIndex().get(i).deepCopy());
4856 goodNotebooks.add((Notebook)Global.deepCopy(listManager.getNotebookIndex().get(i)));
4858 // Now we have a list of good notebooks, so we can look for the default
4860 for (int i=0; i<goodNotebooks.size(); i++) {
4861 if (goodNotebooks.get(i).isDefaultNotebook()) {
4862 notebook = goodNotebooks.get(i).getGuid();
4864 i = goodNotebooks.size();
4868 if (goodNotebooks.size() > 0 && !found)
4869 notebook = goodNotebooks.get(0).getGuid();
4872 notebook = listManager.getNotebookIndex().get(0).getGuid();
4875 Note newNote = new Note();
4876 newNote.setUpdateSequenceNum(0);
4877 newNote.setGuid(randint);
4878 newNote.setNotebookGuid(notebook);
4879 newNote.setTitle("Untitled Note");
4880 newNote.setContent(noteString.toString());
4881 newNote.setDeleted(0);
4882 newNote.setCreated(System.currentTimeMillis());
4883 newNote.setUpdated(System.currentTimeMillis());
4884 newNote.setActive(true);
4885 NoteAttributes na = new NoteAttributes();
4886 na.setLatitude(0.0);
4887 na.setLongitude(0.0);
4888 na.setAltitude(0.0);
4889 newNote.setAttributes(new NoteAttributes());
4890 newNote.setTagGuids(new ArrayList<String>());
4891 newNote.setTagNames(new ArrayList<String>());
4893 // If new notes are to be created based upon the selected tags, then we need to assign the tags
4894 if (Global.newNoteWithSelectedTags()) {
4895 List<QTreeWidgetItem> selections = tagTree.selectedItems();
4896 QTreeWidgetItem currentSelection;
4897 for (int i=0; i<selections.size(); i++) {
4898 currentSelection = selections.get(i);
4899 newNote.getTagGuids().add(currentSelection.text(2));
4900 newNote.getTagNames().add(currentSelection.text(0));
4904 conn.getNoteTable().addNote(newNote, true);
4905 NoteMetadata metadata = new NoteMetadata();
4906 metadata.setGuid(newNote.getGuid());
4907 metadata.setDirty(true);
4908 listManager.addNote(newNote, metadata);
4909 // noteTableView.insertRow(newNote, true, -1);
4911 currentNote = newNote;
4912 currentNoteGuid = currentNote.getGuid();
4913 noteTableView.clearSelection();
4914 refreshEvernoteNote(true);
4915 listManager.countNotebookResults(listManager.getNoteIndex());
4916 browserWindow.titleLabel.setFocus();
4917 browserWindow.titleLabel.selectAll();
4918 // notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
4920 // If the window is hidden, then we want to popup this in an external window &
4924 logger.log(logger.HIGH, "Leaving NeverNote.addNote");
4926 // Restore a note from the trash;
4927 @SuppressWarnings("unused")
4928 private void restoreNote() {
4930 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals(""))
4931 selectedNoteGUIDs.add(currentNoteGuid);
4932 for (int i=0; i<selectedNoteGUIDs.size(); i++) {
4933 listManager.restoreNote(selectedNoteGUIDs.get(i));
4935 currentNoteGuid = "";
4936 listManager.loadNotesIndex();
4937 noteIndexUpdated(false);
4940 // Search a note for specific txt
4941 @SuppressWarnings("unused")
4942 private void findText() {
4944 find.setFocusOnTextField();
4946 @SuppressWarnings("unused")
4947 private void doFindText() {
4948 browserWindow.getBrowser().page().findText(find.getText(), find.getFlags());
4951 @SuppressWarnings("unused")
4952 private void updateNoteTitle(String guid, String title) {
4953 listManager.setNoteSynchronized(guid, false);
4955 // We do this manually because if we've edited the note in an
4956 // external window we run into the possibility of signal recursion
4958 if (guid.equals(currentNoteGuid)) {
4959 browserWindow.titleLabel.blockSignals(true);
4960 browserWindow.titleLabel.setText(title);
4961 browserWindow.titleLabel.blockSignals(false);
4964 // Signal received that note content has changed. Normally we just need the guid to remove
4965 // it from the cache.
4966 @SuppressWarnings("unused")
4967 private void invalidateNoteCache(String guid, String content) {
4968 noteCache.remove(guid);
4969 refreshEvernoteNote(true);
4971 // Signal received that a note guid has changed
4972 @SuppressWarnings("unused")
4973 private void noteGuidChanged(String oldGuid, String newGuid) {
4974 if (noteCache.containsKey(oldGuid)) {
4975 if (!oldGuid.equals(currentNoteGuid)) {
4976 String cache = noteCache.get(oldGuid);
4977 noteCache.put(newGuid, cache);
4978 noteCache.remove(oldGuid);
4980 noteCache.remove(oldGuid);
4981 noteCache.put(newGuid, browserWindow.getContent());
4985 listManager.updateNoteGuid(oldGuid, newGuid, false);
4986 if (currentNoteGuid.equals(oldGuid)) {
4987 if (currentNote != null)
4988 currentNote.setGuid(newGuid);
4989 currentNoteGuid = newGuid;
4992 if (externalWindows.containsKey(oldGuid)) {
4993 ExternalBrowse b = externalWindows.get(oldGuid);
4994 externalWindows.remove(oldGuid);
4995 b.getBrowserWindow().getNote().setGuid(newGuid);
4996 externalWindows.put(newGuid, b);
4999 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
5000 if (listManager.getNoteIndex().get(i).getGuid().equals(newGuid)) {
5001 noteTableView.proxyModel.addGuid(newGuid, listManager.getNoteMetadata().get(newGuid));
5002 i=listManager.getNoteIndex().size();
5006 if (listManager.getNoteTableModel().metaData.containsKey(oldGuid)) {
5007 NoteMetadata meta = listManager.getNoteTableModel().metaData.get(oldGuid);
5008 listManager.getNoteTableModel().metaData.put(newGuid, meta);
5009 listManager.getNoteTableModel().metaData.remove(oldGuid);
5013 // Toggle the note editor button bar
5014 private void toggleEditorButtonBar() {
5015 if (browserWindow.buttonsVisible) {
5016 browserWindow.hideButtons();
5017 menuBar.showEditorBar.setChecked(browserWindow.buttonsVisible);
5018 // Global.saveWindowVisible("editorButtonBar", browserWindow.buttonsVisible);
5020 browserWindow.buttonsVisible = true;
5021 showEditorButtons(browserWindow);
5023 Global.saveWindowVisible("editorButtonBar", browserWindow.buttonsVisible);
5025 // Show editor buttons
5026 private void showEditorButtons(BrowserWindow browser) {
5027 browser.buttonLayout.setVisible(true);
5028 browser.undoAction.setVisible(false);
5030 browser.undoButton.setVisible(false);
5032 browser.undoAction.setVisible(Global.isEditorButtonVisible("undo"));
5033 browser.redoAction.setVisible(Global.isEditorButtonVisible("redo"));
5034 browser.cutAction.setVisible(Global.isEditorButtonVisible("cut"));
5035 browser.copyAction.setVisible(Global.isEditorButtonVisible("copy"));
5036 browser.pasteAction.setVisible(Global.isEditorButtonVisible("paste"));
5037 browser.strikethroughAction.setVisible(Global.isEditorButtonVisible("strikethrough"));
5038 browser.underlineAction.setVisible(Global.isEditorButtonVisible("underline"));
5039 browser.boldAction.setVisible(Global.isEditorButtonVisible("bold"));
5040 browser.italicAction.setVisible(Global.isEditorButtonVisible("italic"));
5041 browser.hlineAction.setVisible(Global.isEditorButtonVisible("hline"));
5042 browser.indentAction.setVisible(Global.isEditorButtonVisible("indent"));
5043 browser.outdentAction.setVisible(Global.isEditorButtonVisible("outdent"));
5044 browser.bulletListAction.setVisible(Global.isEditorButtonVisible("bulletList"));
5045 browser.numberListAction.setVisible(Global.isEditorButtonVisible("numberList"));
5046 browser.fontListAction.setVisible(Global.isEditorButtonVisible("font"));
5047 browser.fontSizeAction.setVisible(Global.isEditorButtonVisible("fontSize"));
5048 browser.fontColorAction.setVisible(Global.isEditorButtonVisible("fontColor"));
5049 browser.fontHilightAction.setVisible(Global.isEditorButtonVisible("fontHilight"));
5050 browser.leftAlignAction.setVisible(Global.isEditorButtonVisible("alignLeft"));
5051 browser.centerAlignAction.setVisible(Global.isEditorButtonVisible("alignCenter"));
5052 browser.rightAlignAction.setVisible(Global.isEditorButtonVisible("alignRight"));
5053 browser.spellCheckAction.setVisible(Global.isEditorButtonVisible("spellCheck"));
5054 browser.todoAction.setVisible(Global.isEditorButtonVisible("todo"));
5056 private void duplicateNote(String guid) {
5058 Note oldNote = conn.getNoteTable().getNote(guid, true, false,false,false,true);
5059 List<Resource> resList = conn.getNoteTable().noteResourceTable.getNoteResources(guid, true);
5060 oldNote.setContent(conn.getNoteTable().getNoteContentNoUTFConversion(guid));
5061 oldNote.setResources(resList);
5062 duplicateNote(oldNote);
5064 private void duplicateNote(Note oldNote) {
5066 // Now that we have a good notebook guid, we need to move the conflicting note
5067 // to the local notebook
5068 Calendar currentTime = new GregorianCalendar();
5069 Long l = new Long(currentTime.getTimeInMillis());
5070 String newGuid = new String(Long.toString(l));
5072 // Note newNote = oldNote.deepCopy();
5073 Note newNote = (Note)Global.deepCopy(oldNote);
5074 newNote.setUpdateSequenceNum(0);
5075 newNote.setGuid(newGuid);
5076 newNote.setDeleted(0);
5077 newNote.setActive(true);
5080 List<String> tagNames = new ArrayList<String>();
5081 List<String> tagGuids = new ArrayList<String>();;
5082 for (int i=0; i<oldNote.getTagGuidsSize(); i++) {
5083 tagNames.add(oldNote.getTagNames().get(i));
5084 tagGuids.add(oldNote.getTagGuids().get(i));
5087 // Sort note Tags to make them look nice
5088 for (int i=0; i<tagNames.size()-1; i++) {
5089 if (tagNames.get(i).compareTo(tagNames.get(i+1))<0) {
5090 String n1 = tagNames.get(i);
5091 String n2 = tagNames.get(i+1);
5092 tagNames.set(i, n2);
5093 tagNames.set(i+1, n1);
5096 newNote.setTagGuids(tagGuids);
5097 newNote.setTagNames(tagNames);
5099 // Add tag guids to note
5102 // Duplicate resources
5103 List<Resource> resList = oldNote.getResources();
5104 if (resList == null)
5105 resList = new ArrayList<Resource>();
5107 for (int i=0; i<resList.size(); i++) {
5109 while (l == prevGuid) {
5110 currentTime = new GregorianCalendar();
5111 l = new Long(currentTime.getTimeInMillis());
5114 String newResGuid = new String(Long.toString(l));
5115 resList.get(i).setNoteGuid(newGuid);
5116 resList.get(i).setGuid(newResGuid);
5117 resList.get(i).setUpdateSequenceNum(0);
5118 resList.get(i).setActive(true);
5119 conn.getNoteTable().noteResourceTable.saveNoteResource(
5120 (Resource)Global.deepCopy(resList.get(i)), true);
5122 newNote.setResources(resList);
5124 // Add note to the database
5125 conn.getNoteTable().addNote(newNote, true);
5126 NoteMetadata metaData = new NoteMetadata();
5127 NoteMetadata oldMeta = listManager.getNoteMetadata().get(oldNote.getGuid());
5128 metaData.copy(oldMeta);
5129 metaData.setGuid(newNote.getGuid());
5130 listManager.addNote(newNote, metaData);
5131 noteTableView.insertRow(newNote, metaData, true, -1);
5132 currentNoteGuid = newNote.getGuid();
5133 currentNote = newNote;
5134 refreshEvernoteNote(true);
5135 listManager.countNotebookResults(listManager.getNoteIndex());
5139 @SuppressWarnings("unused")
5140 private void allNotes() {
5141 clearAttributeFilter();
5142 clearNotebookFilter();
5143 clearSavedSearchFilter();
5146 searchField.clear();
5147 if (Global.mimicEvernoteInterface) {
5148 notebookTree.selectGuid("");
5150 notebookTreeSelection();
5151 refreshEvernoteNote(true);
5154 @SuppressWarnings("unused")
5155 private void mergeNotes() {
5156 logger.log(logger.HIGH, "Merging notes");
5159 String masterGuid = null;
5160 List<String> sources = new ArrayList<String>();
5162 for (int i=0; i<noteTableView.selectionModel().selectedRows().size(); i++) {
5163 int r = noteTableView.selectionModel().selectedRows().get(i).row();
5164 index = noteTableView.proxyModel.index(r, Global.noteTableGuidPosition);
5165 SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
5167 masterGuid = (String)ix.values().toArray()[0];
5169 sources.add((String)ix.values().toArray()[0]);
5172 logger.log(logger.EXTREME, "Master guid=" +masterGuid);
5173 logger.log(logger.EXTREME, "Children count: "+sources.size());
5174 mergeNoteContents(masterGuid, sources);
5175 currentNoteGuid = masterGuid;
5176 noteIndexUpdated(false);
5177 refreshEvernoteNote(true);
5180 private void mergeNoteContents(String targetGuid, List<String> sources) {
5181 Note target = conn.getNoteTable().getNote(targetGuid, true, false, false, false, false);
5182 String newContent = target.getContent();
5183 newContent = newContent.replace("</en-note>", "<br></br>");
5185 for (int i=0; i<sources.size(); i++) {
5186 Note source = conn.getNoteTable().getNote(sources.get(i), true, true, false, false, false);
5187 if (source.isSetTitle()) {
5188 newContent = newContent +("<table bgcolor=\"lightgrey\"><tr><td><font size=\"6\"><b>" +source.getTitle() +"</b></font></td></tr></table>");
5190 String sourceContent = source.getContent();
5191 logger.log(logger.EXTREME, "Merging contents into note");
5192 logger.log(logger.EXTREME, sourceContent);
5193 logger.log(logger.EXTREME, "End of content");
5194 int startOfNote = sourceContent.indexOf("<en-note>");
5195 sourceContent = sourceContent.substring(startOfNote+9);
5196 int endOfNote = sourceContent.indexOf("</en-note>");
5197 sourceContent = sourceContent.substring(0,endOfNote);
5198 newContent = newContent + sourceContent;
5199 logger.log(logger.EXTREME, "New note content");
5200 logger.log(logger.EXTREME, newContent);
5201 logger.log(logger.EXTREME, "End of content");
5202 for (int j=0; j<source.getResourcesSize(); j++) {
5203 logger.log(logger.EXTREME, "Reassigning resource: "+source.getResources().get(j).getGuid());
5204 Resource r = source.getResources().get(j);
5205 Resource newRes = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), true);
5207 Calendar currentTime = new GregorianCalendar();
5208 Long l = new Long(currentTime.getTimeInMillis());
5212 while (l == prevGuid) {
5213 currentTime = new GregorianCalendar();
5214 l = new Long(currentTime.getTimeInMillis());
5216 String newResGuid = new String(Long.toString(l));
5217 newRes.setNoteGuid(targetGuid);
5218 newRes.setGuid(newResGuid);
5219 newRes.setUpdateSequenceNum(0);
5220 newRes.setActive(true);
5221 conn.getNoteTable().noteResourceTable.saveNoteResource(newRes, true);
5224 logger.log(logger.EXTREME, "Updating note");
5225 conn.getNoteTable().updateNoteContent(targetGuid, newContent +"</en-note>");
5226 for (int i=0; i<sources.size(); i++) {
5227 logger.log(logger.EXTREME, "Deleting note " +sources.get(i));
5228 listManager.deleteNote(sources.get(i));
5230 logger.log(logger.EXTREME, "Exiting merge note");
5232 // A resource within a note has had a guid change
5233 @SuppressWarnings("unused")
5234 private void noteResourceGuidChanged(String noteGuid, String oldGuid, String newGuid) {
5235 if (oldGuid != null && !oldGuid.equals(newGuid))
5236 Global.resourceMap.put(oldGuid, newGuid);
5238 // View a thumbnail of the note
5239 public void thumbnailView() {
5241 String thumbnailName = Global.getFileManager().getResDirPath("thumbnail-" + currentNoteGuid + ".png");
5242 QFile thumbnail = new QFile(thumbnailName);
5243 if (!thumbnail.exists()) {
5245 QImage img = new QImage();
5246 img.loadFromData(conn.getNoteTable().getThumbnail(currentNoteGuid));
5247 thumbnailViewer.setThumbnail(img);
5249 thumbnailViewer.setThumbnail(thumbnailName);
5250 if (!thumbnailViewer.isVisible())
5251 thumbnailViewer.showFullScreen();
5253 // An error happened while saving a note. Inform the user
5254 @SuppressWarnings("unused")
5255 private void saveRunnerError(String guid, String msg) {
5257 String title = "*Unknown*";
5258 for (int i=0; i<listManager.getMasterNoteIndex().size(); i++) {
5259 if (listManager.getMasterNoteIndex().get(i).getGuid().equals(guid)) {
5260 title = listManager.getMasterNoteIndex().get(i).getTitle();
5261 i=listManager.getMasterNoteIndex().size();
5264 msg = tr("An error has happened while saving the note \"") +title+
5265 tr("\".\n\nThis is probably due to a document that is too complex for NixNote to process. "+
5266 "As a result, changes to the note may not be saved properly in the database."+
5267 "\n\nA cached copy is being preserved so you can recover any data, but data may" +
5268 "\nbe lost. Please review the note to recover any critical data before restarting.");
5270 QMessageBox.information(this, tr("Error Saving Note"), tr(msg));
5273 private void thumbnailHTMLReady(String guid, QByteArray html, Integer zoom) {
5274 logger.log(logger.HIGH, "Entering thumnailHTMLReady()");
5275 logger.log(logger.HIGH, "Thumbnail ready for " +guid);
5276 // Find an idle preview object
5277 for (int i=0; i<thumbGenerators.size(); i++) {
5278 if (thumbGenerators.get(i).mutex.tryLock()) {
5279 logger.log(logger.EXTREME, "Idle generator found - loading thumbnail for " +guid);
5280 thumbGenerators.get(i).loadContent(guid, html, zoom);
5284 if (thumbGenerators.size() >= 1) {
5285 logger.log(logger.EXTREME, "No available thumbnail generators. Aborting " +guid);
5289 logger.log(logger.EXTREME, "Creating new thumbnail generator " +guid);
5290 Thumbnailer preview = new Thumbnailer(logger, conn, listManager, thumbnailRunner);
5291 thumbGenerators.add(preview);
5293 if (preview.mutex.tryLock()) {
5294 logger.log(logger.EXTREME, "Loading thumbnail for " +guid);
5295 preview.loadContent(guid, html, zoom);
5297 logger.log(logger.HIGH, "Exiting thumnailHTMLReady()");
5302 //**********************************************************
5303 //**********************************************************
5304 //* Online user actions
5305 //**********************************************************
5306 //**********************************************************
5307 private void setupOnlineMenu() {
5308 if (!Global.isConnected) {
5309 menuBar.noteOnlineHistoryAction.setEnabled(false);
5310 menuBar.selectiveSyncAction.setEnabled(false);
5313 menuBar.noteOnlineHistoryAction.setEnabled(true);
5314 menuBar.selectiveSyncAction.setEnabled(true);
5317 @SuppressWarnings("unused")
5318 private void viewNoteHistory() {
5319 if (currentNoteGuid == null || currentNoteGuid.equals(""))
5321 if (currentNote.getUpdateSequenceNum() == 0) {
5322 setMessage(tr("Note has never been synchronized."));
5323 QMessageBox.information(this, tr("Error"), tr("This note has never been sent to Evernote, so there is no history."));
5327 setMessage(tr("Getting Note History"));
5329 Note currentOnlineNote = null;
5332 if (Global.isPremium())
5333 versions = syncRunner.localNoteStore.listNoteVersions(syncRunner.authToken, currentNoteGuid);
5335 versions = new ArrayList<NoteVersionId>();
5336 currentOnlineNote = syncRunner.localNoteStore.getNote(syncRunner.authToken, currentNoteGuid, true, true, false, false);
5337 } catch (EDAMUserException e) {
5338 setMessage("EDAMUserException: " +e.getMessage());
5340 } catch (EDAMSystemException e) {
5341 setMessage("EDAMSystemException: " +e.getMessage());
5343 } catch (EDAMNotFoundException e) {
5344 setMessage(tr("Note not found on server."));
5345 QMessageBox.information(this, tr("Error"), tr("This note could not be found on Evernote's servers."));
5347 } catch (TException e) {
5348 setMessage("EDAMTransactionException: " +e.getMessage());
5352 // If we've gotten this far, we have a good note.
5353 if (historyWindow == null) {
5354 historyWindow = new OnlineNoteHistory(logger, conn);
5355 historyWindow.historyCombo.activated.connect(this, "reloadHistoryWindow(String)");
5356 historyWindow.restoreAsNew.clicked.connect(this, "restoreHistoryNoteAsNew()");
5357 historyWindow.restore.clicked.connect(this, "restoreHistoryNote()");
5359 historyWindow.historyCombo.clear();
5361 boolean isDirty = conn.getNoteTable().isNoteDirty(currentNoteGuid);
5362 if (currentNote.getUpdateSequenceNum() != currentOnlineNote.getUpdateSequenceNum())
5364 historyWindow.setCurrent(isDirty);
5366 loadHistoryWindowContent(currentOnlineNote);
5367 historyWindow.load(versions);
5368 setMessage(tr("History retrieved"));
5370 historyWindow.exec();
5372 private Note reloadHistoryWindow(String selection) {
5374 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
5375 String dateTimeFormat = new String(fmt);
5376 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
5380 for (int i=0; i<versions.size(); i++) {
5381 StringBuilder versionDate = new StringBuilder(simple.format(versions.get(i).getSaved()));
5382 if (versionDate.toString().equals(selection))
5386 if (index > -1 || selection.indexOf("Current") > -1) {
5387 Note historyNote = null;
5390 usn = versions.get(index).getUpdateSequenceNum();
5391 historyNote = syncRunner.localNoteStore.getNoteVersion(syncRunner.authToken, currentNoteGuid, usn, true, true, true);
5393 historyNote = syncRunner.localNoteStore.getNote(syncRunner.authToken, currentNoteGuid, true,true,true,true);
5394 } catch (EDAMUserException e) {
5395 setMessage("EDAMUserException: " +e.getMessage());
5398 } catch (EDAMSystemException e) {
5399 setMessage("EDAMSystemException: " +e.getMessage());
5402 } catch (EDAMNotFoundException e) {
5403 setMessage("EDAMNotFoundException: " +e.getMessage());
5406 } catch (TException e) {
5407 setMessage("EDAMTransactionException: " +e.getMessage());
5413 if (historyNote != null)
5414 historyWindow.setContent(historyNote);
5420 private void loadHistoryWindowContent(Note note) {
5421 note.setUpdateSequenceNum(0);
5422 historyWindow.setContent(note);
5424 @SuppressWarnings("unused")
5425 private void restoreHistoryNoteAsNew() {
5426 setMessage(tr("Restoring as new note."));
5427 duplicateNote(reloadHistoryWindow(historyWindow.historyCombo.currentText()));
5428 setMessage(tr("Note has been restored as a new note."));
5430 @SuppressWarnings("unused")
5431 private void restoreHistoryNote() {
5432 setMessage(tr("Restoring note."));
5433 Note n = reloadHistoryWindow(historyWindow.historyCombo.currentText());
5434 conn.getNoteTable().expungeNote(n.getGuid(), true, false);
5437 for (int i=0; i<n.getResourcesSize(); i++) {
5438 n.getResources().get(i).setActive(true);
5439 conn.getNoteTable().noteResourceTable.saveNoteResource(n.getResources().get(i), true);
5441 NoteMetadata metadata = new NoteMetadata();
5442 metadata.setGuid(n.getGuid());
5443 listManager.addNote(n, metadata);
5444 conn.getNoteTable().addNote(n, true);
5445 refreshEvernoteNote(true);
5446 setMessage(tr("Note has been restored."));
5448 @SuppressWarnings("unused")
5449 private void setupSelectiveSync() {
5451 // Get a list of valid notebooks
5452 List<Notebook> notebooks = null;
5453 List<Tag> tags = null;
5454 List<LinkedNotebook> linkedNotebooks = null;
5456 notebooks = syncRunner.localNoteStore.listNotebooks(syncRunner.authToken);
5457 tags = syncRunner.localNoteStore.listTags(syncRunner.authToken);
5458 linkedNotebooks = syncRunner.localNoteStore.listLinkedNotebooks(syncRunner.authToken);
5459 } catch (EDAMUserException e) {
5460 setMessage("EDAMUserException: " +e.getMessage());
5462 } catch (EDAMSystemException e) {
5463 setMessage("EDAMSystemException: " +e.getMessage());
5465 } catch (TException e) {
5466 setMessage("EDAMTransactionException: " +e.getMessage());
5468 } catch (EDAMNotFoundException e) {
5469 setMessage("EDAMNotFoundException: " +e.getMessage());
5473 // Split up notebooks into synchronized & non-synchronized
5474 List<Notebook> ignoredBooks = new ArrayList<Notebook>();
5475 List<String> dbIgnoredNotebooks = conn.getSyncTable().getIgnoreRecords("NOTEBOOK");
5477 for (int i=notebooks.size()-1; i>=0; i--) {
5478 for (int j=0; j<dbIgnoredNotebooks.size(); j++) {
5479 if (notebooks.get(i).getGuid().equalsIgnoreCase(dbIgnoredNotebooks.get(j))) {
5480 ignoredBooks.add(notebooks.get(i));
5481 j=dbIgnoredNotebooks.size();
5486 // split up tags into synchronized & non-synchronized
5487 List<Tag> ignoredTags = new ArrayList<Tag>();
5488 List<String> dbIgnoredTags = conn.getSyncTable().getIgnoreRecords("TAG");
5490 for (int i=tags.size()-1; i>=0; i--) {
5491 for (int j=0; j<dbIgnoredTags.size(); j++) {
5492 if (tags.get(i).getGuid().equalsIgnoreCase(dbIgnoredTags.get(j))) {
5493 ignoredTags.add(tags.get(i));
5494 j=dbIgnoredTags.size();
5499 // split up linked notebooks into synchronized & non-synchronized
5500 List<LinkedNotebook> ignoredLinkedNotebooks = new ArrayList<LinkedNotebook>();
5501 List<String> dbIgnoredLinkedNotebooks = conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK");
5502 for (int i=linkedNotebooks.size()-1; i>=0; i--) {
5503 String notebookGuid = linkedNotebooks.get(i).getGuid();
5504 for (int j=0; j<dbIgnoredLinkedNotebooks.size(); j++) {
5505 if (notebookGuid.equalsIgnoreCase(dbIgnoredLinkedNotebooks.get(j))) {
5506 ignoredLinkedNotebooks.add(linkedNotebooks.get(i));
5507 j=dbIgnoredLinkedNotebooks.size();
5512 IgnoreSync ignore = new IgnoreSync(notebooks, ignoredBooks, tags, ignoredTags, linkedNotebooks, ignoredLinkedNotebooks);
5514 if (!ignore.okClicked())
5519 // Clear out old notebooks & add the new ones
5520 List<String> oldIgnoreNotebooks = conn.getSyncTable().getIgnoreRecords("NOTEBOOK");
5521 for (int i=0; i<oldIgnoreNotebooks.size(); i++) {
5522 conn.getSyncTable().deleteRecord("IGNORENOTEBOOK-"+oldIgnoreNotebooks.get(i));
5525 List<String> newNotebooks = new ArrayList<String>();
5526 for (int i=ignore.getIgnoredBookList().count()-1; i>=0; i--) {
5527 String text = ignore.getIgnoredBookList().takeItem(i).text();
5528 for (int j=0; j<notebooks.size(); j++) {
5529 if (notebooks.get(j).getName().equalsIgnoreCase(text)) {
5530 Notebook n = notebooks.get(j);
5531 conn.getSyncTable().addRecord("IGNORENOTEBOOK-"+n.getGuid(), n.getGuid());
5533 newNotebooks.add(n.getGuid());
5538 // Clear out old tags & add new ones
5539 List<String> oldIgnoreTags = conn.getSyncTable().getIgnoreRecords("TAG");
5540 for (int i=0; i<oldIgnoreTags.size(); i++) {
5541 conn.getSyncTable().deleteRecord("IGNORETAG-"+oldIgnoreTags.get(i));
5544 List<String> newTags = new ArrayList<String>();
5545 for (int i=ignore.getIgnoredTagList().count()-1; i>=0; i--) {
5546 String text = ignore.getIgnoredTagList().takeItem(i).text();
5547 for (int j=0; j<tags.size(); j++) {
5548 if (tags.get(j).getName().equalsIgnoreCase(text)) {
5549 Tag t = tags.get(j);
5550 conn.getSyncTable().addRecord("IGNORETAG-"+t.getGuid(), t.getGuid());
5551 newTags.add(t.getGuid());
5557 // Clear out old tags & add new ones
5558 List<String> oldIgnoreLinkedNotebooks = conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK");
5559 for (int i=0; i<oldIgnoreLinkedNotebooks.size(); i++) {
5560 conn.getSyncTable().deleteRecord("IGNORELINKEDNOTEBOOK-"+oldIgnoreLinkedNotebooks.get(i));
5563 List<String> newLinked = new ArrayList<String>();
5564 for (int i=ignore.getIgnoredLinkedNotebookList().count()-1; i>=0; i--) {
5565 String text = ignore.getIgnoredLinkedNotebookList().takeItem(i).text();
5566 for (int j=0; j<linkedNotebooks.size(); j++) {
5567 if (linkedNotebooks.get(j).getShareName().equalsIgnoreCase(text)) {
5568 LinkedNotebook t = linkedNotebooks.get(j);
5569 conn.getSyncTable().addRecord("IGNORELINKEDNOTEBOOK-"+t.getGuid(), t.getGuid());
5570 newLinked.add(t.getGuid());
5571 j=linkedNotebooks.size();
5576 conn.getNoteTable().expungeIgnoreSynchronizedNotes(newNotebooks, newTags, newLinked);
5582 //**********************************************************
5583 //**********************************************************
5584 //* XML Modifying methods
5585 //**********************************************************
5586 //**********************************************************
5587 // An error has happended fetching a resource. let the user know
5588 private void resourceErrorMessage() {
5592 QMessageBox.information(this, tr("DOUGH!!!"), tr("Well, this is embarrassing."+
5593 "\n\nSome attachments or images for this note appear to be missing from my database.\n"+
5594 "In a perfect world this wouldn't happen, but it has.\n" +
5595 "It is embarasing when a program like me, designed to save all your\n"+
5596 "precious data, has a problem finding data.\n\n" +
5597 "I guess life isn't fair, but I'll survive. Somehow...\n\n" +
5598 "In the mean time, I'm not going to let you make changes to this note.\n" +
5599 "Don't get angry. I'm doing it to prevent you from messing up\n"+
5600 "this note on the Evernote servers. Sorry."+
5601 "\n\nP.S. You might want to re-synchronize to see if it corrects this problem.\nWho knows, you might get lucky."));
5603 browserWindow.setReadOnly(true);
5610 //**********************************************************
5611 //**********************************************************
5613 //**********************************************************
5614 //**********************************************************
5615 // We should now do a sync with Evernote
5616 private void syncTimer() {
5617 logger.log(logger.EXTREME, "Entering NeverNote.syncTimer()");
5618 syncRunner.syncNeeded = true;
5619 syncRunner.disableUploads = Global.disableUploads;
5621 logger.log(logger.EXTREME, "Leaving NeverNote.syncTimer()");
5623 private void syncStart() {
5624 logger.log(logger.EXTREME, "Entering NeverNote.syncStart()");
5626 if (!syncRunning && Global.isConnected) {
5627 syncRunner.setConnected(true);
5628 syncRunner.setKeepRunning(Global.keepRunning);
5629 syncRunner.syncDeletedContent = Global.synchronizeDeletedContent();
5631 if (syncThreadsReady > 0) {
5632 thumbnailRunner.interrupt = true;
5633 saveNoteIndexWidth();
5634 saveNoteColumnPositions();
5635 if (syncRunner.addWork("SYNC")) {
5637 syncRunner.syncNeeded = true;
5642 logger.log(logger.EXTREME, "Leaving NeverNote.syncStart");
5644 @SuppressWarnings("unused")
5645 private void syncThreadComplete(Boolean refreshNeeded) {
5646 setMessage(tr("Finalizing Synchronization"));
5648 syncRunning = false;
5649 syncRunner.syncNeeded = false;
5650 synchronizeAnimationTimer.stop();
5651 synchronizeButton.setIcon(new QIcon(iconPath+"synchronize.png"));
5653 if (currentNote == null) {
5654 currentNote = conn.getNoteTable().getNote(currentNoteGuid, false, false, false, false, true);
5656 listManager.refreshNoteMetadata();
5657 noteIndexUpdated(true);
5658 noteTableView.selectionModel().blockSignals(true);
5659 scrollToGuid(currentNoteGuid);
5660 noteTableView.selectionModel().blockSignals(false);
5661 refreshEvernoteNote(false);
5662 scrollToGuid(currentNoteGuid);
5665 // Check to see if there were any shared notebook errors
5666 if (syncRunner.error && syncRunner.errorSharedNotebooks.size() > 0) {
5667 String guid = syncRunner.errorSharedNotebooks.get(0);
5668 String notebookGuid = conn.getLinkedNotebookTable().getLocalNotebookGuid(guid);
5669 String localName = listManager.getNotebookNameByGuid(notebookGuid);
5670 SharedNotebookSyncError syncDialog = new SharedNotebookSyncError(localName);
5672 if (syncDialog.okPressed()) {
5673 if (syncDialog.doNothing.isChecked()) {
5674 syncRunner.errorSharedNotebooksIgnored.put(guid, guid);
5677 if (syncDialog.deleteNotebook.isChecked()) {
5678 conn.getNoteTable().expungeNotesByNotebook(notebookGuid, true, false);
5679 conn.getNotebookTable().expungeNotebook(notebookGuid, false);
5680 conn.getLinkedNotebookTable().expungeNotebook(guid, false);
5681 conn.getLinkedNotebookTable().expungeNotebook(guid, false);
5689 // Finalize the synchronization
5690 if (!syncRunner.error)
5691 setMessage(tr("Synchronization Complete"));
5693 setMessage(tr("Synchronization completed with errors. Please check the log for details."));
5694 logger.log(logger.MEDIUM, "Sync complete.");
5696 public void saveUploadAmount(long t) {
5697 Global.saveUploadAmount(t);
5699 public void saveUserInformation(User user) {
5700 Global.saveUserInformation(user);
5702 public void saveEvernoteUpdateCount(int i) {
5703 Global.saveEvernoteUpdateCount(i);
5705 public void refreshLists() {
5706 logger.log(logger.EXTREME, "Entering NeverNote.refreshLists");
5708 listManager.refreshLists(currentNote, noteDirty, browserWindow.getContent());
5709 tagIndexUpdated(true);
5710 notebookIndexUpdated();
5711 savedSearchIndexUpdated();
5712 listManager.loadNotesIndex();
5714 noteTableView.selectionModel().blockSignals(true);
5715 noteIndexUpdated(true);
5716 noteTableView.selectionModel().blockSignals(false);
5717 logger.log(logger.EXTREME, "Leaving NeverNote.refreshLists");
5721 @SuppressWarnings("unused")
5722 private void authTimer() {
5723 Calendar cal = Calendar.getInstance();
5725 // If we are not connected let's get out of here
5726 if (!Global.isConnected)
5729 // If this is the first time through, then we need to set this
5730 // if (syncRunner.authRefreshTime == 0 || cal.getTimeInMillis() > syncRunner.authRefreshTime)
5731 // syncRunner.authRefreshTime = cal.getTimeInMillis();
5733 // long now = new Date().getTime();
5734 // if (now > Global.authRefreshTime && Global.isConnected) {
5735 syncRunner.authRefreshNeeded = true;
5739 @SuppressWarnings("unused")
5740 private void authRefreshComplete(boolean goodSync) {
5741 logger.log(logger.EXTREME, "Entering NeverNote.authRefreshComplete");
5742 Global.isConnected = syncRunner.isConnected;
5744 // authTimer.start((int)syncRunner.authTimeRemaining/4);
5745 authTimer.start(1000*60*15);
5746 logger.log(logger.LOW, "Authentication token has been renewed");
5747 // setMessage("Authentication token has been renewed.");
5749 authTimer.start(1000*60*5);
5750 logger.log(logger.LOW, "Authentication token renew has failed - retry in 5 minutes.");
5751 // setMessage("Authentication token renew has failed - retry in 5 minutes.");
5753 logger.log(logger.EXTREME, "Leaving NeverNote.authRefreshComplete");
5757 @SuppressWarnings("unused")
5758 private synchronized void indexTimer() {
5759 logger.log(logger.EXTREME, "Index timer activated. Sync running="+syncRunning);
5762 if (!indexDisabled && indexRunner.idle) {
5763 thumbnailRunner.interrupt = true;
5764 indexRunner.addWork("SCAN");
5766 logger.log(logger.EXTREME, "Leaving NixNote index timer");
5769 @SuppressWarnings("unused")
5770 private void indexStarted() {
5771 setMessage(tr("Indexing notes"));
5773 @SuppressWarnings("unused")
5774 private void indexComplete() {
5775 setMessage(tr("Index complete"));
5777 @SuppressWarnings("unused")
5778 private synchronized void toggleNoteIndexing() {
5779 logger.log(logger.HIGH, "Entering NeverNote.toggleIndexing");
5780 indexDisabled = !indexDisabled;
5782 setMessage(tr("Indexing is now enabled."));
5784 setMessage(tr("Indexing is now disabled."));
5785 menuBar.disableIndexing.setChecked(indexDisabled);
5786 logger.log(logger.HIGH, "Leaving NeverNote.toggleIndexing");
5789 @SuppressWarnings("unused")
5790 private void threadMonitorCheck() {
5795 alive = listManager.threadCheck(Global.tagCounterThreadId);
5798 if (tagDeadCount > MAX && !disableTagThreadCheck) {
5799 QMessageBox.information(this, tr("A thread has died."), tr("It appears as the tag counter thread has died. I recommend "+
5800 "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry."));
5801 disableTagThreadCheck = true;
5806 alive = listManager.threadCheck(Global.notebookCounterThreadId);
5808 notebookThreadDeadCount++;
5809 if (notebookThreadDeadCount > MAX && !disableNotebookThreadCheck) {
5810 QMessageBox.information(this, tr("A thread has died."), tr("It appears as the notebook counter thread has died. I recommend "+
5811 "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry."));
5812 disableNotebookThreadCheck=true;
5815 notebookThreadDeadCount=0;
5817 alive = listManager.threadCheck(Global.trashCounterThreadId);
5820 if (trashDeadCount > MAX && !disableTrashThreadCheck) {
5821 QMessageBox.information(this, tr("A thread has died."), ("It appears as the trash counter thread has died. I recommend "+
5822 "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry."));
5823 disableTrashThreadCheck = true;
5828 alive = listManager.threadCheck(Global.saveThreadId);
5830 saveThreadDeadCount++;
5831 if (saveThreadDeadCount > MAX && !disableSaveThreadCheck) {
5832 QMessageBox.information(this, tr("A thread has died."), tr("It appears as the note saver thread has died. I recommend "+
5833 "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry."));
5834 disableSaveThreadCheck = true;
5837 saveThreadDeadCount=0;
5839 if (!syncThread.isAlive()) {
5840 syncThreadDeadCount++;
5841 if (syncThreadDeadCount > MAX && !disableSyncThreadCheck) {
5842 QMessageBox.information(this, tr("A thread has died."), tr("It appears as the synchronization thread has died. I recommend "+
5843 "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry."));
5844 disableSyncThreadCheck = true;
5847 syncThreadDeadCount=0;
5849 if (!indexThread.isAlive()) {
5850 indexThreadDeadCount++;
5851 if (indexThreadDeadCount > MAX && !disableIndexThreadCheck) {
5852 QMessageBox.information(this, tr("A thread has died."), tr("It appears as the index thread has died. I recommend "+
5853 "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry."));
5854 disableIndexThreadCheck = true;
5857 indexThreadDeadCount=0;
5862 private void thumbnailTimer() {
5863 if (Global.enableThumbnails() && !syncRunning && indexRunner.idle) {
5864 thumbnailRunner.addWork("SCAN");
5868 //**************************************************
5869 //* Backup & Restore
5870 //**************************************************
5871 @SuppressWarnings("unused")
5872 private void databaseBackup() {
5873 QFileDialog fd = new QFileDialog(this);
5874 fd.setFileMode(FileMode.AnyFile);
5875 fd.setConfirmOverwrite(true);
5876 fd.setWindowTitle(tr("Backup Database"));
5877 fd.setFilter(tr("NixNote Export (*.nnex);;All Files (*.*)"));
5878 fd.setAcceptMode(AcceptMode.AcceptSave);
5879 if (saveLastPath == null || saveLastPath.equals(""))
5880 fd.setDirectory(System.getProperty("user.home"));
5882 fd.setDirectory(saveLastPath);
5883 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
5889 saveLastPath = fd.selectedFiles().get(0);
5890 saveLastPath = saveLastPath.substring(0,saveLastPath.lastIndexOf("/"));
5891 setMessage(tr("Backing up database"));
5893 // conn.backupDatabase(Global.getUpdateSequenceNumber(), Global.getSequenceDate());
5895 ExportData noteWriter = new ExportData(conn, true);
5896 String fileName = fd.selectedFiles().get(0);
5898 if (!fileName.endsWith(".nnex"))
5899 fileName = fileName +".nnex";
5900 noteWriter.exportData(fileName);
5901 setMessage(tr("Database backup completed."));
5906 @SuppressWarnings("unused")
5907 private void databaseRestore() {
5908 if (QMessageBox.question(this, tr("Confirmation"),
5909 tr("This is used to restore a database from backups.\n" +
5910 "It is HIGHLY recommened that this only be used to populate\n" +
5911 "an empty database. Restoring into a database that\n already has data" +
5912 " can cause problems.\n\nAre you sure you want to continue?"),
5913 QMessageBox.StandardButton.Yes,
5914 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
5919 QFileDialog fd = new QFileDialog(this);
5920 fd.setFileMode(FileMode.ExistingFile);
5921 fd.setConfirmOverwrite(true);
5922 fd.setWindowTitle(tr("Restore Database"));
5923 fd.setFilter(tr("NixNote Export (*.nnex);;All Files (*.*)"));
5924 fd.setAcceptMode(AcceptMode.AcceptOpen);
5925 if (saveLastPath == null || saveLastPath.equals(""))
5926 fd.setDirectory(System.getProperty("user.home"));
5928 fd.setDirectory(saveLastPath);
5929 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
5935 saveLastPath = fd.selectedFiles().get(0);
5936 saveLastPath = saveLastPath.substring(0,saveLastPath.lastIndexOf("/"));
5938 setMessage(tr("Restoring database"));
5939 ImportData noteReader = new ImportData(conn, true);
5940 noteReader.importData(fd.selectedFiles().get(0));
5942 if (noteReader.lastError != 0) {
5943 setMessage(noteReader.getErrorMessage());
5944 logger.log(logger.LOW, "Restore problem: " +noteReader.lastError);
5949 listManager.loadNoteTitleColors();
5951 refreshEvernoteNote(true);
5952 setMessage(tr("Database has been restored."));
5955 @SuppressWarnings("unused")
5956 private void exportNotes() {
5957 QFileDialog fd = new QFileDialog(this);
5958 fd.setFileMode(FileMode.AnyFile);
5959 fd.setConfirmOverwrite(true);
5960 fd.setWindowTitle(tr("Backup Database"));
5961 fd.setFilter(tr("NixNote Export (*.nnex);;All Files (*.*)"));
5962 fd.setAcceptMode(AcceptMode.AcceptSave);
5963 fd.setDirectory(System.getProperty("user.home"));
5964 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
5970 setMessage(tr("Exporting Notes"));
5973 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals(""))
5974 selectedNoteGUIDs.add(currentNoteGuid);
5976 ExportData noteWriter = new ExportData(conn, false, selectedNoteGUIDs);
5977 String fileName = fd.selectedFiles().get(0);
5979 if (!fileName.endsWith(".nnex"))
5980 fileName = fileName +".nnex";
5981 noteWriter.exportData(fileName);
5982 setMessage(tr("Export completed."));
5988 @SuppressWarnings("unused")
5989 private void importNotes() {
5990 QFileDialog fd = new QFileDialog(this);
5991 fd.setFileMode(FileMode.ExistingFile);
5992 fd.setConfirmOverwrite(true);
5993 fd.setWindowTitle(tr("Import Notes"));
5994 fd.setFilter(tr("NixNote Export (*.nnex);;Evernote Export (*.enex);;All Files (*.*)"));
5995 fd.setAcceptMode(AcceptMode.AcceptOpen);
5996 if (saveLastPath == null || saveLastPath.equals(""))
5997 fd.setDirectory(System.getProperty("user.home"));
5999 fd.setDirectory(saveLastPath);
6000 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
6006 setMessage(tr("Importing Notes"));
6009 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals(""))
6010 selectedNoteGUIDs.add(currentNoteGuid);
6012 String fileName = fd.selectedFiles().get(0);
6013 // saveLastPath.substring(0,fileName.lastIndexOf("/"));
6015 if (fileName.endsWith(".nnex")) {
6016 ImportData noteReader = new ImportData(conn, false);
6017 if (selectedNotebookGUIDs != null && selectedNotebookGUIDs.size() > 0)
6018 noteReader.setNotebookGuid(selectedNotebookGUIDs.get(0));
6020 noteReader.setNotebookGuid(listManager.getNotebookIndex().get(0).getGuid());
6022 noteReader.importData(fileName);
6024 if (noteReader.lastError != 0) {
6025 setMessage(noteReader.getErrorMessage());
6026 logger.log(logger.LOW, "Import problem: " +noteReader.lastError);
6031 if (fileName.endsWith(".enex")) {
6032 ImportEnex noteReader = new ImportEnex(conn, false);
6033 if (selectedNotebookGUIDs != null && selectedNotebookGUIDs.size() > 0)
6034 noteReader.setNotebookGuid(selectedNotebookGUIDs.get(0));
6036 noteReader.setNotebookGuid(listManager.getNotebookIndex().get(0).getGuid());
6039 if (QMessageBox.question(this, tr("Confirmation"),
6040 tr("Create new tags from import?"),
6041 QMessageBox.StandardButton.Yes,
6042 QMessageBox.StandardButton.No) == StandardButton.Yes.value()) {
6043 noteReader.createNewTags = true;
6045 noteReader.createNewTags = false;
6047 noteReader.importData(fileName);
6049 if (noteReader.lastError != 0) {
6050 setMessage(noteReader.getErrorMessage());
6051 logger.log(logger.LOW, "Import problem: " +noteReader.lastError);
6058 listManager.loadNoteTitleColors();
6060 refreshEvernoteNote(false);
6061 setMessage(tr("Notes have been imported."));
6064 setMessage(tr("Import completed."));
6071 //**************************************************
6072 //* Duplicate a note
6073 //**************************************************
6074 @SuppressWarnings("unused")
6075 private void duplicateNote() {
6077 duplicateNote(currentNoteGuid);
6080 //**************************************************
6081 //* Action from when a user clicks Copy As URL
6082 //**************************************************
6083 @SuppressWarnings("unused")
6084 private void copyAsUrlClicked() {
6085 QClipboard clipboard = QApplication.clipboard();
6086 QMimeData mime = new QMimeData();
6088 mime.setText(currentNoteGuid);
6089 List<QUrl> urls = new ArrayList<QUrl>();
6091 // Start building the URL
6092 User user = Global.getUserInformation();
6094 // Check that we have everything we need
6095 if ((user.getShardId().equals("") || user.getId() == 0) && !Global.bypassSynchronizationWarning()) {
6096 SynchronizationRequiredWarning warning = new SynchronizationRequiredWarning(this);
6098 if (!warning.neverSynchronize())
6101 Global.setBypassSynchronizationWarning(true);
6102 user.setShardId("s0");
6108 // Start building a list of URLs based upon the selected notes
6109 noteTableView.showColumn(Global.noteTableGuidPosition);
6111 List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
6112 if (!Global.isColumnVisible("guid"))
6113 noteTableView.hideColumn(Global.noteTableGuidPosition);
6115 // Check that the note is either synchronized, or in a local notebook
6116 for (int i=0; i<selections.size(); i++) {
6118 int row = selections.get(i).row();
6119 index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
6120 SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
6121 String selectedGuid = (String)ix.values().toArray()[0];
6123 Note n = conn.getNoteTable().getNote(selectedGuid, false, false, false, false, false);
6124 if (n.getUpdateSequenceNum() == 0 && !conn.getNotebookTable().isNotebookLocal(n.getNotebookGuid())) {
6125 QMessageBox.critical(this, tr("Please Synchronize") ,tr("Please either synchronize or move any " +
6126 "new notes to a local notebook."));
6131 // Start building the URLs
6132 for (int i=0; i<selections.size(); i++) {
6134 int row = selections.get(i).row();
6135 index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
6136 SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
6137 String selectedGuid = (String)ix.values().toArray()[0];
6138 mime.setText(selectedGuid);
6142 Note selectedNote = conn.getNoteTable().getNote(selectedGuid, false, false, false, false, false);
6143 if (selectedNote.getUpdateSequenceNum() > 0) {
6147 gid = "00000000-0000-0000-0000-000000000000";
6150 url = new String("evernote://///view/") + new String(user.getId() + "/" +user.getShardId() +"/"
6152 urls.add(new QUrl(url));
6155 clipboard.setMimeData(mime);
6159 //**************************************************
6161 //**************************************************
6162 public void setupFolderImports() {
6163 List<WatchFolderRecord> records = conn.getWatchFolderTable().getAll();
6165 if (importKeepWatcher == null)
6166 importKeepWatcher = new QFileSystemWatcher();
6167 if (importDeleteWatcher == null) {
6168 importDeleteWatcher = new QFileSystemWatcher();
6169 for (int i=0; i<records.size(); i++) {
6170 if (!records.get(i).keep)
6171 folderImportDelete(records.get(i).folder);
6177 // importKeepWatcher.addPath(records.get(i).folder.replace('\\', '/'));
6178 for (int i=0; i<records.size(); i++) {
6179 logger.log(logger.LOW, "Adding file monitor: " +records.get(i).folder);
6180 if (records.get(i).keep)
6181 importKeepWatcher.addPath(records.get(i).folder);
6183 importDeleteWatcher.addPath(records.get(i).folder);
6186 logger.log(logger.EXTREME, "List of directories being watched (kept)...");
6187 List<String> monitorDelete = importKeepWatcher.directories();
6188 for (int i=0; i<monitorDelete.size(); i++) {
6189 logger.log(logger.EXTREME, monitorDelete.get(i));
6191 logger.log(logger.EXTREME, "<end of list>");
6192 logger.log(logger.EXTREME, "List of directories being watched (delete)...");
6193 monitorDelete = importDeleteWatcher.directories();
6194 for (int i=0; i<monitorDelete.size(); i++) {
6195 logger.log(logger.EXTREME, monitorDelete.get(i));
6197 logger.log(logger.EXTREME, "<end of list>");
6199 importKeepWatcher.directoryChanged.connect(this, "folderImportKeep(String)");
6200 importDeleteWatcher.directoryChanged.connect(this, "folderImportDelete(String)");
6202 // Look at the files already there so we don't import them again if a new file is created
6203 if (importedFiles == null) {
6204 importedFiles = new ArrayList<String>();
6205 for (int j=0; j<records.size(); j++) {
6206 QDir dir = new QDir(records.get(j).folder);
6207 List<QFileInfo> list = dir.entryInfoList();
6208 for (int k=0; k<list.size(); k++) {
6209 if (list.get(k).isFile())
6210 importedFiles.add(list.get(k).absoluteFilePath());
6216 // Menu folderImport action triggered
6217 public void folderImport() {
6218 List<WatchFolderRecord> recs = conn.getWatchFolderTable().getAll();
6219 WatchFolder dialog = new WatchFolder(recs, listManager.getNotebookIndex());
6221 if (!dialog.okClicked())
6224 // We have some sort of update.
6225 if (importKeepWatcher.directories().size() > 0)
6226 importKeepWatcher.removePaths(importKeepWatcher.directories());
6227 if (importDeleteWatcher.directories().size() > 0)
6228 importDeleteWatcher.removePaths(importDeleteWatcher.directories());
6230 conn.getWatchFolderTable().expungeAll();
6231 // Start building from the table
6232 for (int i=0; i<dialog.table.rowCount(); i++) {
6233 QTableWidgetItem item = dialog.table.item(i, 0);
6234 String dir = item.text();
6235 item = dialog.table.item(i, 1);
6236 String notebook = item.text();
6237 item = dialog.table.item(i, 2);
6239 if (item.text().equalsIgnoreCase("Keep"))
6244 String guid = conn.getNotebookTable().findNotebookByName(notebook);
6245 conn.getWatchFolderTable().addWatchFolder(dir, guid, keep, 0);
6247 setupFolderImports();
6251 public void folderImportKeep(String dirName) throws NoSuchAlgorithmException {
6252 logger.log(logger.LOW, "Inside folderImportKeep");
6253 String whichOS = System.getProperty("os.name");
6254 if (whichOS.contains("Windows"))
6255 dirName = dirName.replace('/','\\');
6257 FileImporter importer = new FileImporter(logger, conn);
6259 QDir dir = new QDir(dirName);
6260 List<QFileInfo> list = dir.entryInfoList();
6261 String notebook = conn.getWatchFolderTable().getNotebook(dirName);
6263 for (int i=0; i<list.size(); i++){
6264 logger.log(logger.LOW, "File found: " +list.get(i).fileName());
6265 boolean redundant = false;
6266 // Check if we've already imported this one or if it existed before
6267 for (int j=0; j<importedFiles.size(); j++) {
6268 logger.log(logger.LOW, "redundant file list: " +list.get(i).absoluteFilePath());
6269 if (importedFiles.get(j).equals(list.get(i).absoluteFilePath()))
6273 logger.log(logger.LOW, "Checking if redundant: " +redundant);
6275 importer.setFileInfo(list.get(i));
6276 importer.setFileName(list.get(i).absoluteFilePath());
6279 logger.log(logger.LOW, "File importing is a file: " +list.get(i).isFile());
6280 logger.log(logger.LOW, "File importing is a valid: " +importer.isValidType());
6281 if (list.get(i).isFile() && importer.isValidType()) {
6283 if (!importer.importFile()) {
6284 // If we can't get to the file, it is probably locked. We'll try again later.
6285 logger.log(logger.LOW, "Unable to save externally edited file. Saving for later.");
6286 importFilesKeep.add(list.get(i).absoluteFilePath());
6289 Note newNote = importer.getNote();
6290 newNote.setNotebookGuid(notebook);
6291 newNote.setTitle(dir.at(i));
6292 NoteMetadata metadata = new NoteMetadata();
6293 metadata.setDirty(true);
6294 metadata.setGuid(newNote.getGuid());
6295 listManager.addNote(newNote, metadata);
6296 conn.getNoteTable().addNote(newNote, true);
6297 noteTableView.insertRow(newNote, metadata, true, -1);
6298 listManager.updateNoteContent(newNote.getGuid(), importer.getNoteContent());
6299 listManager.countNotebookResults(listManager.getNoteIndex());
6300 importedFiles.add(list.get(i).absoluteFilePath());
6309 public void folderImportDelete(String dirName) {
6310 logger.log(logger.LOW, "Inside folderImportDelete");
6311 String whichOS = System.getProperty("os.name");
6312 if (whichOS.contains("Windows"))
6313 dirName = dirName.replace('/','\\');
6315 FileImporter importer = new FileImporter(logger, conn);
6316 QDir dir = new QDir(dirName);
6317 List<QFileInfo> list = dir.entryInfoList();
6318 String notebook = conn.getWatchFolderTable().getNotebook(dirName);
6320 for (int i=0; i<list.size(); i++){
6321 logger.log(logger.LOW, "File found: " +list.get(i).fileName());
6322 importer.setFileInfo(list.get(i));
6323 importer.setFileName(list.get(i).absoluteFilePath());
6325 logger.log(logger.LOW, "File importing is a file: " +list.get(i).isFile());
6326 logger.log(logger.LOW, "File importing is a valid: " +importer.isValidType());
6327 if (list.get(i).isFile() && importer.isValidType()) {
6329 if (!importer.importFile()) {
6330 // If we can't get to the file, it is probably locked. We'll try again later.
6331 logger.log(logger.LOW, "Unable to save externally edited file. Saving for later.");
6332 importFilesKeep.add(list.get(i).absoluteFilePath());
6335 Note newNote = importer.getNote();
6336 newNote.setNotebookGuid(notebook);
6337 newNote.setTitle(dir.at(i));
6338 NoteMetadata metadata = new NoteMetadata();
6339 metadata.setDirty(true);
6340 metadata.setGuid(newNote.getGuid());
6341 listManager.addNote(newNote, metadata);
6342 conn.getNoteTable().addNote(newNote, true);
6343 noteTableView.insertRow(newNote, metadata, true, -1);
6344 listManager.updateNoteContent(newNote.getGuid(), importer.getNoteContent());
6345 listManager.countNotebookResults(listManager.getNoteIndex());
6346 dir.remove(dir.at(i));
6353 //**************************************************
6355 //**************************************************
6356 private void externalFileEdited(String fileName) throws NoSuchAlgorithmException {
6357 logger.log(logger.HIGH, "Entering exernalFileEdited");
6359 // Strip URL prefix and base dir path
6360 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
6361 String name = fileName.replace(dPath, "");
6362 int pos = name.lastIndexOf('.');
6365 guid = guid.substring(0,pos);
6367 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
6369 guid = name.substring(0, pos);
6372 QFile file = new QFile(fileName);
6373 if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly))) {
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);
6379 QByteArray binData = file.readAll();
6381 if (binData.size() == 0) {
6382 // If we can't get to the file, it is probably locked. We'll try again later.
6383 logger.log(logger.LOW, "Unable to save externally edited file. Saving for later.");
6384 externalFiles.add(fileName);
6388 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
6390 r = conn.getNoteTable().noteResourceTable.getNoteResource(Global.resourceMap.get(guid), true);
6391 if (r == null || r.getData() == null || r.getData().getBody() == null)
6393 String oldHash = Global.byteArrayToHexString(r.getData().getBodyHash());
6394 MessageDigest md = MessageDigest.getInstance("MD5");
6395 md.update(binData.toByteArray());
6396 byte[] hash = md.digest();
6397 String newHash = Global.byteArrayToHexString(hash);
6398 if (r.getNoteGuid().equalsIgnoreCase(currentNoteGuid)) {
6399 updateResourceContentHash(browserWindow, r.getGuid(), oldHash, newHash);
6401 if (externalWindows.containsKey(r.getNoteGuid())) {
6402 updateResourceContentHash(externalWindows.get(r.getNoteGuid()).getBrowserWindow(),
6403 r.getGuid(), oldHash, newHash);
6405 conn.getNoteTable().updateResourceContentHash(r.getNoteGuid(), oldHash, newHash);
6406 Data data = r.getData();
6407 data.setBody(binData.toByteArray());
6408 data.setBodyHash(hash);
6409 logger.log(logger.LOW, "externalFileEdited: " +data.getSize() +" bytes");
6411 conn.getNoteTable().noteResourceTable.updateNoteResource(r,true);
6413 if (r.getNoteGuid().equals(currentNoteGuid)) {
6414 QWebSettings.setMaximumPagesInCache(0);
6415 QWebSettings.setObjectCacheCapacities(0, 0, 0);
6416 refreshEvernoteNote(true);
6417 browserWindow.getBrowser().triggerPageAction(WebAction.Reload);
6420 if (externalWindows.containsKey(r.getNoteGuid())) {
6421 QWebSettings.setMaximumPagesInCache(0);
6422 QWebSettings.setObjectCacheCapacities(0, 0, 0);
6423 externalWindows.get(r.getNoteGuid()).getBrowserWindow().getBrowser().triggerPageAction(WebAction.Reload);
6427 logger.log(logger.HIGH, "Exiting externalFielEdited");
6429 // This is a timer event that tries to save any external files that were edited. This
6430 // is only needed if we couldn't save a file earlier.
6431 public void externalFileEditedSaver() {
6432 for (int i=externalFiles.size()-1; i>=0; i--) {
6434 logger.log(logger.MEDIUM, "Trying to save " +externalFiles.get(i));
6435 externalFileEdited(externalFiles.get(i));
6436 externalFiles.remove(i);
6437 } catch (NoSuchAlgorithmException e) {e.printStackTrace();}
6439 for (int i=0; i<importFilesKeep.size(); i++) {
6441 logger.log(logger.MEDIUM, "Trying to save " +importFilesKeep.get(i));
6442 folderImportKeep(importFilesKeep.get(i));
6443 importFilesKeep.remove(i);
6444 } catch (NoSuchAlgorithmException e) {e.printStackTrace();}
6446 for (int i=0; i<importFilesDelete.size(); i++) {
6447 logger.log(logger.MEDIUM, "Trying to save " +importFilesDelete.get(i));
6448 folderImportDelete(importFilesDelete.get(i));
6449 importFilesDelete.remove(i);
6456 // If an attachment on the current note was edited, we need to update the current notes's hash
6457 // Update a note content's hash. This happens if a resource is edited outside of NN
6458 public void updateResourceContentHash(BrowserWindow browser, String guid, String oldHash, String newHash) {
6459 int position = browserWindow.getContent().indexOf("en-tag=\"en-media\" guid=\""+guid+"\" type=");
6461 for (;position>-1;) {
6462 endPos = browser.getContent().indexOf(">", position+1);
6463 String oldSegment = browser.getContent().substring(position,endPos);
6464 int hashPos = oldSegment.indexOf("hash=\"");
6465 int hashEnd = oldSegment.indexOf("\"", hashPos+7);
6466 String hash = oldSegment.substring(hashPos+6, hashEnd);
6467 if (hash.equalsIgnoreCase(oldHash)) {
6468 String newSegment = oldSegment.replace(oldHash, newHash);
6469 String content = browser.getContent().substring(0,position) +
6471 browser.getContent().substring(endPos);
6472 browser.setContent(new QByteArray(content));;
6475 position = browser.getContent().indexOf("en-tag=\"en-media\" guid=\""+guid+"\" type=", position+1);
6480 //*************************************************
6481 //* Minimize to tray
6482 //*************************************************
6484 public void changeEvent(QEvent e) {
6485 if (e.type() == QEvent.Type.WindowStateChange) {
6486 if (QSystemTrayIcon.isSystemTrayAvailable()) {
6487 if (isMinimized() && (Global.showTrayIcon() || Global.showTrayIcon())) {
6489 QTimer.singleShot(10, this, "hide()");
6493 windowMaximized = true;
6495 windowMaximized = false;
6500 //*************************************************
6501 //* Check database userid & passwords
6502 //*************************************************
6503 private static boolean databaseCheck(String url,String userid, String userPassword, String cypherPassword) {
6504 Connection connection;
6507 Class.forName("org.h2.Driver");
6508 } catch (ClassNotFoundException e1) {
6509 e1.printStackTrace();
6514 String passwordString = null;
6515 if (cypherPassword==null || cypherPassword.trim().equals(""))
6516 passwordString = userPassword;
6518 passwordString = cypherPassword+" "+userPassword;
6519 connection = DriverManager.getConnection(url,userid,passwordString);
6520 } catch (SQLException e) {
6525 } catch (SQLException e) {
6526 e.printStackTrace();
6531 //*************************************************
6532 //* View / Hide source HTML for a note
6533 //*************************************************
6534 public void viewSource() {
6535 browserWindow.showSource(menuBar.viewSource.isChecked());
6537 //*************************************************
6538 // Block the program. This is used for things
6539 // like async web calls.
6540 //*************************************************
6541 @SuppressWarnings("unused")
6542 private void blockApplication(BrowserWindow b) {
6543 // Block all signals
6547 blockTimer = new QTimer();
6548 blockTimer.setSingleShot(true);
6549 blockTimer.setInterval(15000);
6550 blockTimer.timeout.connect(this, "unblockApplication()");
6555 @SuppressWarnings("unused")
6556 private void unblockApplication() {
6558 if (blockingWindow != null && new GregorianCalendar().getTimeInMillis() > blockingWindow.unblockTime && blockingWindow.unblockTime != -1) {
6559 QMessageBox.critical(null, tr("No Response from CodeCogs") ,tr("Unable to contact CodeCogs for LaTeX formula."));
6560 blockingWindow.unblockTime = -1;
6561 blockingWindow.awaitingHttpResponse = false;
6563 blockingWindow = null;
6564 blockSignals(false);