X-Git-Url: http://git.sourceforge.jp/view?p=neighbornote%2FNeighborNote.git;a=blobdiff_plain;f=src%2Fcx%2Ffbn%2Fnevernote%2FNeverNote.java;h=128040832fcf547108066b44cc8452bfe33cb04c;hp=699e1fa02e35eb90429d4b8fb1c86755a7a5159c;hb=a2374669b35e3f686e611278fb31c8d8fd3f3fc2;hpb=8479f389335a5510806321b2ebf61d83e5c7388d diff --git a/src/cx/fbn/nevernote/NeverNote.java b/src/cx/fbn/nevernote/NeverNote.java index 699e1fa..1280408 100644 --- a/src/cx/fbn/nevernote/NeverNote.java +++ b/src/cx/fbn/nevernote/NeverNote.java @@ -1,5 +1,5 @@ /* - * This file is part of NeverNote + * This file is part of NixNote * Copyright 2009 Randy Baumgarte * * This file may be licensed under the terms of of the @@ -43,6 +43,8 @@ import java.util.List; import java.util.SortedMap; import java.util.Vector; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; import org.apache.thrift.TException; import org.h2.tools.ChangeFileEncryption; @@ -52,9 +54,11 @@ import com.evernote.edam.error.EDAMUserException; import com.evernote.edam.notestore.NoteFilter; import com.evernote.edam.notestore.NoteVersionId; import com.evernote.edam.type.Data; +import com.evernote.edam.type.LinkedNotebook; import com.evernote.edam.type.Note; import com.evernote.edam.type.NoteAttributes; import com.evernote.edam.type.Notebook; +import com.evernote.edam.type.Publishing; import com.evernote.edam.type.QueryFormat; import com.evernote.edam.type.Resource; import com.evernote.edam.type.SavedSearch; @@ -71,6 +75,7 @@ import com.trolltech.qt.core.QFileSystemWatcher; import com.trolltech.qt.core.QIODevice; import com.trolltech.qt.core.QIODevice.OpenModeFlag; import com.trolltech.qt.core.QLocale; +import com.trolltech.qt.core.QMimeData; import com.trolltech.qt.core.QModelIndex; import com.trolltech.qt.core.QSize; import com.trolltech.qt.core.QTemporaryFile; @@ -82,16 +87,19 @@ import com.trolltech.qt.core.QUrl; import com.trolltech.qt.core.Qt; import com.trolltech.qt.core.Qt.BGMode; import com.trolltech.qt.core.Qt.ItemDataRole; +import com.trolltech.qt.core.Qt.KeyboardModifier; +import com.trolltech.qt.core.Qt.MouseButton; import com.trolltech.qt.core.Qt.SortOrder; import com.trolltech.qt.core.Qt.WidgetAttribute; import com.trolltech.qt.gui.QAbstractItemView; import com.trolltech.qt.gui.QAbstractItemView.ScrollHint; import com.trolltech.qt.gui.QAction; import com.trolltech.qt.gui.QApplication; +import com.trolltech.qt.gui.QClipboard; import com.trolltech.qt.gui.QCloseEvent; import com.trolltech.qt.gui.QColor; import com.trolltech.qt.gui.QComboBox; -import com.trolltech.qt.gui.QComboBox.InsertPolicy; +import com.trolltech.qt.gui.QCursor; import com.trolltech.qt.gui.QDesktopServices; import com.trolltech.qt.gui.QDialog; import com.trolltech.qt.gui.QFileDialog; @@ -101,8 +109,8 @@ import com.trolltech.qt.gui.QGridLayout; import com.trolltech.qt.gui.QHBoxLayout; import com.trolltech.qt.gui.QIcon; import com.trolltech.qt.gui.QImage; +import com.trolltech.qt.gui.QKeySequence; import com.trolltech.qt.gui.QLabel; -import com.trolltech.qt.gui.QListWidget; import com.trolltech.qt.gui.QMainWindow; import com.trolltech.qt.gui.QMenu; import com.trolltech.qt.gui.QMessageBox; @@ -112,7 +120,7 @@ import com.trolltech.qt.gui.QPalette.ColorRole; import com.trolltech.qt.gui.QPixmap; import com.trolltech.qt.gui.QPrintDialog; import com.trolltech.qt.gui.QPrinter; -import com.trolltech.qt.gui.QProgressBar; +import com.trolltech.qt.gui.QShortcut; import com.trolltech.qt.gui.QSizePolicy; import com.trolltech.qt.gui.QSizePolicy.Policy; import com.trolltech.qt.gui.QSpinBox; @@ -124,6 +132,9 @@ import com.trolltech.qt.gui.QTableWidgetItem; import com.trolltech.qt.gui.QTextEdit; import com.trolltech.qt.gui.QToolBar; import com.trolltech.qt.gui.QTreeWidgetItem; +import com.trolltech.qt.network.QNetworkAccessManager; +import com.trolltech.qt.network.QNetworkReply; +import com.trolltech.qt.network.QNetworkRequest; import com.trolltech.qt.webkit.QWebPage.WebAction; import com.trolltech.qt.webkit.QWebSettings; @@ -135,14 +146,27 @@ import cx.fbn.nevernote.dialog.DBEncryptDialog; import cx.fbn.nevernote.dialog.DatabaseLoginDialog; import cx.fbn.nevernote.dialog.DatabaseStatus; import cx.fbn.nevernote.dialog.FindDialog; +import cx.fbn.nevernote.dialog.IgnoreSync; +import cx.fbn.nevernote.dialog.LogFileDialog; import cx.fbn.nevernote.dialog.LoginDialog; import cx.fbn.nevernote.dialog.NotebookArchive; import cx.fbn.nevernote.dialog.NotebookEdit; import cx.fbn.nevernote.dialog.OnlineNoteHistory; +import cx.fbn.nevernote.dialog.PublishNotebook; import cx.fbn.nevernote.dialog.SavedSearchEdit; +import cx.fbn.nevernote.dialog.SetIcon; +import cx.fbn.nevernote.dialog.ShareNotebook; +import cx.fbn.nevernote.dialog.SharedNotebookSyncError; +import cx.fbn.nevernote.dialog.StackNotebook; +import cx.fbn.nevernote.dialog.SynchronizationRequiredWarning; import cx.fbn.nevernote.dialog.TagEdit; +import cx.fbn.nevernote.dialog.TagMerge; import cx.fbn.nevernote.dialog.ThumbnailViewer; +import cx.fbn.nevernote.dialog.UpgradeAvailableDialog; import cx.fbn.nevernote.dialog.WatchFolder; +import cx.fbn.nevernote.evernote.NoteMetadata; +import cx.fbn.nevernote.filters.FilterEditorNotebooks; +import cx.fbn.nevernote.filters.FilterEditorTags; import cx.fbn.nevernote.gui.AttributeTreeWidget; import cx.fbn.nevernote.gui.BrowserWindow; import cx.fbn.nevernote.gui.DateAttributeFilterTable; @@ -150,10 +174,12 @@ import cx.fbn.nevernote.gui.ExternalBrowse; import cx.fbn.nevernote.gui.MainMenuBar; import cx.fbn.nevernote.gui.NotebookTreeWidget; import cx.fbn.nevernote.gui.SavedSearchTreeWidget; +import cx.fbn.nevernote.gui.SearchPanel; import cx.fbn.nevernote.gui.TableView; import cx.fbn.nevernote.gui.TagTreeWidget; import cx.fbn.nevernote.gui.Thumbnailer; import cx.fbn.nevernote.gui.TrashTreeWidget; +import cx.fbn.nevernote.gui.controls.QuotaProgressBar; import cx.fbn.nevernote.sql.DatabaseConnection; import cx.fbn.nevernote.sql.WatchFolderRecord; import cx.fbn.nevernote.threads.IndexRunner; @@ -184,6 +210,7 @@ public class NeverNote extends QMainWindow{ QAction trayExitAction; // Exit the application QAction trayShowAction; // toggle the show/hide action QAction trayAddNoteAction; // Add a note from the system tray + QNetworkAccessManager versionChecker; // Used when checking for new versions NotebookTreeWidget notebookTree; // List of notebooks AttributeTreeWidget attributeTree; // List of note attributes @@ -195,8 +222,9 @@ public class NeverNote extends QMainWindow{ public BrowserWindow browserWindow; // Window containing browser & labels public QToolBar toolBar; // The tool bar under the menu QComboBox searchField; // search filter bar on the toolbar; + QShortcut searchShortcut; // Shortcut to search bar boolean searchPerformed = false; // Search was done? - QProgressBar quotaBar; // The current quota usage + QuotaProgressBar quotaBar; // The current quota usage ApplicationLogger logger; List selectedNotebookGUIDs; // List of notebook GUIDs @@ -209,7 +237,9 @@ public class NeverNote extends QMainWindow{ String currentNoteGuid; // GUID of the current note Note currentNote; // The currently viewed note boolean noteDirty; // Has the note been changed? - boolean inkNote; // if this is an ink note, it is read only + boolean inkNote; // if this is an ink note, it is read only + boolean readOnly; // Is this note read-only? + ListManager listManager; // DB runnable task @@ -251,7 +281,7 @@ public class NeverNote extends QMainWindow{ QAction synchronizeButton; // Synchronize with Evernote QAction allNotesButton; // Reset & view all notes QTimer synchronizeAnimationTimer; // Timer to change animation button - double synchronizeIconAngle; // Used to rotate sync icon + int synchronizeIconAngle; // Used to rotate sync icon QAction printButton; // Print Button QAction tagButton; // Tag edit button QAction attributeButton; // Attribute information button @@ -261,6 +291,8 @@ public class NeverNote extends QMainWindow{ QSpinBox zoomSpinner; // Zoom zoom QAction searchClearButton; // Clear the search field + SearchPanel searchLayout; // Widget to hold search field, zoom, & quota + QSplitter mainLeftRightSplitter; // main splitter for left/right side QSplitter leftSplitter1; // first left hand splitter QSplitter browserIndexSplitter; // splitter between note index & note text @@ -280,8 +312,16 @@ public class NeverNote extends QMainWindow{ int tagDeadCount=0; // number of consecutive dead times for the tag thread int trashDeadCount=0; // number of consecutive dead times for the trash thread int saveThreadDeadCount=0; // number of consecutive dead times for the save thread + boolean disableTagThreadCheck=false; + boolean disableNotebookThreadCheck=false; + boolean disableTrashThreadCheck=false; + boolean disableSaveThreadCheck=false; + boolean disableSyncThreadCheck=false; + boolean disableIndexThreadCheck=false; HashMap noteCache; // Cash of note content + HashMap readOnlyCache; // List of cashe notes that are read-only + HashMap inkNoteCache; // List of cache notes that are ink notes List historyGuids; // GUIDs of previously viewed items int historyPosition; // Position within the viewed items boolean fromHistory; // Is this from the history queue? @@ -294,7 +334,13 @@ public class NeverNote extends QMainWindow{ Signal0 minimizeToTray; boolean windowMaximized = false; // Keep track of the window state for restores List pdfReadyQueue; // Queue of PDFs that are ready to be rendered. - + List syncIcons; // Array of icons used in sync animation + private boolean closeAction = false; // Used to say when to close or when to minimize + private static Logger log = Logger.getLogger(NeverNote.class); + private String saveLastPath; // last path we used + private final QTimer messageTimer; // Timer to clear the status message. + private QTimer blockTimer; + BrowserWindow blockingWindow; String iconPath = new String("classpath:cx/fbn/nevernote/icons/"); @@ -305,18 +351,19 @@ public class NeverNote extends QMainWindow{ //*************************************************************** //*************************************************************** // Application Constructor + @SuppressWarnings("static-access") public NeverNote(DatabaseConnection dbConn) { conn = dbConn; if (conn.getConnection() == null) { - String msg = "Unable to connect to the database.\n\nThe most probable reason is that some other process\n" + - "is accessing the database or NeverNote is already running.\n\n" + - "Please end any other process or shutdown the other NeverNote before starting.\n\nExiting program."; + String msg = new String(tr("Unable to connect to the database.\n\nThe most probable reason is that some other process\n" + + "is accessing the database or NixNote is already running.\n\n" + + "Please end any other process or shutdown the other NixNote before starting.\n\nExiting program.")); - QMessageBox.critical(null, "Database Connection Error",msg); + QMessageBox.critical(null, tr("Database Connection Error") ,msg); System.exit(16); } - - thread().setPriority(Thread.MAX_PRIORITY); + setObjectName("mainWindow"); +// thread().setPriority(Thread.MAX_PRIORITY); logger = new ApplicationLogger("nevernote.log"); logger.log(logger.HIGH, "Starting Application"); @@ -345,7 +392,7 @@ public class NeverNote extends QMainWindow{ QApplication.setStyle(Global.getStyle()); if (Global.useStandardPalette()) QApplication.setPalette(QApplication.style().standardPalette()); - setWindowTitle("NeverNote"); + setWindowTitle(tr("NixNote")); mainLeftRightSplitter = new QSplitter(); setCentralWidget(mainLeftRightSplitter); @@ -356,16 +403,23 @@ public class NeverNote extends QMainWindow{ browserIndexSplitter.setOrientation(Qt.Orientation.Vertical); //* Setup threads & thread timers - int indexRunnerCount = Global.getIndexThreads(); - indexRunnerCount = 1; - QThreadPool.globalInstance().setMaxThreadCount(indexRunnerCount+5); // increase max thread count +// int indexRunnerCount = Global.getIndexThreads(); +// indexRunnerCount = 1; + QThreadPool.globalInstance().setMaxThreadCount(Global.threadCount); // increase max thread count logger.log(logger.EXTREME, "Building list manager"); listManager = new ListManager(conn, logger); logger.log(logger.EXTREME, "Building index runners & timers"); - indexRunner = new IndexRunner("indexRunner.log", Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword); + indexRunner = new IndexRunner("indexRunner.log", + Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), + Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword); indexThread = new QThread(indexRunner, "Index Thread"); + indexRunner.indexAttachmentsLocally = Global.indexAttachmentsLocally(); + indexRunner.indexImageRecognition = Global.indexImageRecognition(); + indexRunner.indexNoteBody = Global.indexNoteBody(); + indexRunner.indexNoteTitle = Global.indexNoteTitle(); + indexRunner.specialIndexCharacters = Global.getSpecialIndexCharacters(); indexThread.start(); synchronizeAnimationTimer = new QTimer(); @@ -380,7 +434,9 @@ public class NeverNote extends QMainWindow{ logger.log(logger.EXTREME, "Setting sync thread & timers"); syncThreadsReady=1; - syncRunner = new SyncRunner("syncRunner.log", Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword); + syncRunner = new SyncRunner("syncRunner.log", + Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), + Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword); syncTime = new SyncTimes().timeValue(Global.getSyncInterval()); syncTimer = new QTimer(); syncTimer.timeout.connect(this, "syncTimer()"); @@ -402,7 +458,9 @@ public class NeverNote extends QMainWindow{ logger.log(logger.EXTREME, "Starting thumnail thread"); pdfReadyQueue = new ArrayList(); - thumbnailRunner = new ThumbnailRunner("thumbnailRunner.log", Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword); + thumbnailRunner = new ThumbnailRunner("thumbnailRunner.log", + Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), + Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword); thumbnailThread = new QThread(thumbnailRunner, "Thumbnail Thread"); thumbnailRunner.noteSignal.thumbnailPageReady.connect(this, "thumbnailHTMLReady(String,QByteArray,Integer)"); thumbnailThread.start(); @@ -410,7 +468,7 @@ public class NeverNote extends QMainWindow{ thumbnailTimer = new QTimer(); thumbnailTimer.timeout.connect(this, "thumbnailTimer()"); thumbnailTimer(); - thumbnailTimer.setInterval(5*1000); // Thumbnail every 2 min + thumbnailTimer.setInterval(500*1000); // Thumbnail every minute thumbnailTimer.start(); logger.log(logger.EXTREME, "Starting authentication timer"); @@ -437,23 +495,50 @@ public class NeverNote extends QMainWindow{ importFilesKeep = new ArrayList(); externalFileSaveTimer.start(); - notebookTree = new NotebookTreeWidget(); + notebookTree = new NotebookTreeWidget(conn); attributeTree = new AttributeTreeWidget(); tagTree = new TagTreeWidget(conn); savedSearchTree = new SavedSearchTreeWidget(); trashTree = new TrashTreeWidget(); - noteTableView = new TableView(logger, listManager); + noteTableView = new TableView(logger, listManager); + + searchField = new QComboBox(); + searchField.setObjectName("searchField"); + //setStyleSheet("QComboBox#searchField { background-color: yellow }"); + searchField.setEditable(true); + searchField.activatedIndex.connect(this, "searchFieldChanged()"); + searchField.setDuplicatesEnabled(false); + searchField.editTextChanged.connect(this,"searchFieldTextChanged(String)"); + searchShortcut = new QShortcut(this); + setupShortcut(searchShortcut, "Focus_Search"); + searchShortcut.activated.connect(this, "focusSearch()"); + + quotaBar = new QuotaProgressBar(); + // Setup the zoom + zoomSpinner = new QSpinBox(); + zoomSpinner.setMinimum(10); + zoomSpinner.setMaximum(1000); + zoomSpinner.setAccelerated(true); + zoomSpinner.setSingleStep(10); + zoomSpinner.setValue(100); + zoomSpinner.valueChanged.connect(this, "zoomChanged()"); + + searchLayout = new SearchPanel(searchField, quotaBar, notebookTree, zoomSpinner); + QGridLayout leftGrid = new QGridLayout(); + leftSplitter1.setContentsMargins(5, 0, 0, 7); leftSplitter1.setLayout(leftGrid); - leftGrid.addWidget(notebookTree, 1, 1); + leftGrid.addWidget(searchLayout,1,1); leftGrid.addWidget(tagTree,2,1); leftGrid.addWidget(attributeTree,3,1); leftGrid.addWidget(savedSearchTree,4,1); - leftGrid.addWidget(trashTree, 5, 1); + leftGrid.addWidget(trashTree,5, 1); // Setup the browser window noteCache = new HashMap(); + readOnlyCache = new HashMap(); + inkNoteCache = new HashMap(); browserWindow = new BrowserWindow(conn); mainLeftRightSplitter.addWidget(leftSplitter1); @@ -466,14 +551,6 @@ public class NeverNote extends QMainWindow{ mainLeftRightSplitter.addWidget(noteTableView); mainLeftRightSplitter.addWidget(browserWindow); } - - searchField = new QComboBox(); - searchField.setEditable(true); - searchField.activatedIndex.connect(this, "searchFieldChanged()"); - searchField.setDuplicatesEnabled(false); - searchField.editTextChanged.connect(this,"searchFieldTextChanged(String)"); - - quotaBar = new QProgressBar(); // Setup the thumbnail viewer thumbnailViewer = new ThumbnailViewer(); @@ -500,23 +577,38 @@ public class NeverNote extends QMainWindow{ emitLog = new ArrayList(); tagTree.setDeleteAction(menuBar.tagDeleteAction); + tagTree.setMergeAction(menuBar.tagMergeAction); tagTree.setEditAction(menuBar.tagEditAction); tagTree.setAddAction(menuBar.tagAddAction); + tagTree.setIconAction(menuBar.tagIconAction); tagTree.setVisible(Global.isWindowVisible("tagTree")); + leftSplitter1.setVisible(Global.isWindowVisible("leftPanel")); tagTree.noteSignal.tagsAdded.connect(this, "tagsAdded(String, String)"); menuBar.hideTags.setChecked(Global.isWindowVisible("tagTree")); listManager.tagSignal.listChanged.connect(this, "reloadTagTree()"); + + if (!Global.isWindowVisible("zoom")) { + searchLayout.hideZoom(); + menuBar.hideZoom.setChecked(false); + } notebookTree.setDeleteAction(menuBar.notebookDeleteAction); notebookTree.setEditAction(menuBar.notebookEditAction); notebookTree.setAddAction(menuBar.notebookAddAction); + notebookTree.setIconAction(menuBar.notebookIconAction); + notebookTree.setStackAction(menuBar.notebookStackAction); + notebookTree.setPublishAction(menuBar.notebookPublishAction); + notebookTree.setShareAction(menuBar.notebookShareAction); notebookTree.setVisible(Global.isWindowVisible("notebookTree")); notebookTree.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)"); + notebookTree.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)"); + notebookTree.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)"); menuBar.hideNotebooks.setChecked(Global.isWindowVisible("notebookTree")); savedSearchTree.setAddAction(menuBar.savedSearchAddAction); savedSearchTree.setEditAction(menuBar.savedSearchEditAction); savedSearchTree.setDeleteAction(menuBar.savedSearchDeleteAction); + savedSearchTree.setIconAction(menuBar.savedSearchIconAction); savedSearchTree.itemSelectionChanged.connect(this, "updateSavedSearchSelection()"); savedSearchTree.setVisible(Global.isWindowVisible("savedSearchTree")); menuBar.hideSavedSearches.setChecked(Global.isWindowVisible("savedSearchTree")); @@ -527,11 +619,14 @@ public class NeverNote extends QMainWindow{ noteTableView.setNoteDuplicateAction(menuBar.noteDuplicateAction); noteTableView.setNoteHistoryAction(menuBar.noteOnlineHistoryAction); noteTableView.noteSignal.titleColorChanged.connect(this, "titleColorChanged(Integer)"); + noteTableView.noteSignal.notePinned.connect(this, "notePinned()"); noteTableView.setMergeNotesAction(menuBar.noteMergeAction); - noteTableView.rowChanged.connect(this, "scrollToGuid(String)"); - noteTableView.resetViewport.connect(this, "scrollToCurrentGuid()"); + noteTableView.setCopyAsUrlAction(menuBar.noteCopyAsUrlAction); noteTableView.doubleClicked.connect(this, "listDoubleClick()"); listManager.trashSignal.countChanged.connect(trashTree, "updateCounts(Integer)"); + + quotaBar.setMouseClickAction(menuBar.accountAction); + trashTree.load(); trashTree.itemSelectionChanged.connect(this, "trashTreeSelection()"); trashTree.setEmptyAction(menuBar.emptyTrashAction); @@ -550,6 +645,15 @@ public class NeverNote extends QMainWindow{ menuBar.hideLeftSide.setChecked(true); if (Global.isWindowVisible("noteInformation")) toggleNoteInformation(); + quotaBar.setVisible(Global.isWindowVisible("quota")); + if (!quotaBar.isVisible()) + menuBar.hideQuota.setChecked(false); + searchField.setVisible(Global.isWindowVisible("searchField")); + if (!searchField.isVisible()) + menuBar.hideSearch.setChecked(false); + + if (searchField.isHidden() && quotaBar.isHidden() && zoomSpinner.isHidden() && notebookTree.isHidden()) + searchLayout.hide(); setMenuBar(menuBar); setupToolBar(); @@ -557,11 +661,11 @@ public class NeverNote extends QMainWindow{ find.getOkButton().clicked.connect(this, "doFindText()"); // Setup the tray icon menu bar - trayShowAction = new QAction("Show/Hide", this); - trayExitAction = new QAction("Exit", this); - trayAddNoteAction = new QAction("Add Note", this); + trayShowAction = new QAction(tr("Show/Hide"), this); + trayExitAction = new QAction(tr("Exit"), this); + trayAddNoteAction = new QAction(tr("Add Note"), this); - trayExitAction.triggered.connect(this, "close()"); + trayExitAction.triggered.connect(this, "closeNeverNote()"); trayAddNoteAction.triggered.connect(this, "addNote()"); trayShowAction.triggered.connect(this, "trayToggleVisible()"); @@ -572,7 +676,7 @@ public class NeverNote extends QMainWindow{ trayIcon = new QSystemTrayIcon(this); - trayIcon.setToolTip("NeverNote"); + trayIcon.setToolTip(tr("NixNote")); trayIcon.setContextMenu(trayMenu); trayIcon.activated.connect(this, "trayActivated(com.trolltech.qt.gui.QSystemTrayIcon$ActivationReason)"); @@ -633,14 +737,18 @@ public class NeverNote extends QMainWindow{ historyGuids.add(currentNoteGuid); historyPosition = 1; + menuBar.blockSignals(true); + menuBar.narrowListView.blockSignals(true); + menuBar.wideListView.blockSignals(true); if (Global.getListView() == Global.View_List_Narrow) { menuBar.narrowListView.setChecked(true); -// narrowListView(); } else{ menuBar.wideListView.setChecked(true); -// wideListView(); } + menuBar.blockSignals(false); + menuBar.narrowListView.blockSignals(false); + menuBar.wideListView.blockSignals(false); if (Global.getListView() == Global.View_List_Wide) { browserIndexSplitter.addWidget(noteTableView); @@ -650,15 +758,25 @@ public class NeverNote extends QMainWindow{ mainLeftRightSplitter.addWidget(browserWindow); } + messageTimer = new QTimer(); + messageTimer.timeout.connect(this, "clearMessage()"); + messageTimer.setInterval(1000*15); + clearMessage(); + int sortCol = Global.getSortColumn(); int sortOrder = Global.getSortOrder(); + noteTableView.proxyModel.blocked = true; noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder)); - + noteTableView.proxyModel.blocked = false; + noteTableView.proxyModel.sortChanged.connect(this, "tableSortOrderChanged(Integer,Integer)"); + + if (Global.checkVersionUpgrade()) + checkForUpdates(); } - - + // Main entry point public static void main(String[] args) { + log.setLevel(Level.FATAL); QApplication.initialize(args); QPixmap pixmap = new QPixmap("classpath:cx/fbn/nevernote/icons/splash_logo.png"); QSplashScreen splash = new QSplashScreen(pixmap); @@ -676,7 +794,7 @@ public class NeverNote extends QMainWindow{ dbConn = setupDatabaseConnection(); // Must be last stage of setup - only safe once DB is open hence we know we are the only instance running - Global.getFileManager().purgeResDirectory(); + Global.getFileManager().purgeResDirectory(true); } catch (InitializationException e) { // Fatal @@ -713,9 +831,14 @@ public class NeverNote extends QMainWindow{ ApplicationLogger logger = new ApplicationLogger("nevernote-database.log"); File f = Global.getFileManager().getDbDirFile(Global.databaseName + ".h2.db"); - boolean dbExists = f.exists(); - if (!dbExists) + File fr = Global.getFileManager().getDbDirFile(Global.resourceDatabaseName + ".h2.db"); + File fi = Global.getFileManager().getDbDirFile(Global.resourceDatabaseName + ".h2.db"); + if (!f.exists()) Global.setDatabaseUrl(""); + if (!fr.exists()) + Global.setResourceDatabaseUrl(""); + if (!fi.exists()) + Global.setIndexDatabaseUrl(""); if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") > -1) { boolean goodCheck = false; @@ -729,24 +852,35 @@ public class NeverNote extends QMainWindow{ Global.getDatabaseUserPassword(), Global.cipherPassword); } } - DatabaseConnection dbConn = new DatabaseConnection(logger,Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword); + DatabaseConnection dbConn = new DatabaseConnection(logger,Global.getDatabaseUrl(), + Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), + Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword, 0); return dbConn; } // Encrypt the database upon shutdown private void encryptOnShutdown() { String dbPath= Global.getFileManager().getDbDirPath(""); - String dbName = "NeverNote"; try { + Statement st = conn.getConnection().createStatement(); st.execute("shutdown"); - if (QMessageBox.question(this, "Are you sure", - "Are you sure you wish to encrypt the database?", + st = conn.getResourceConnection().createStatement(); + st.execute("shutdown"); + st = conn.getIndexConnection().createStatement(); + st.execute("shutdown"); + if (QMessageBox.question(this, tr("Are you sure"), + tr("Are you sure you wish to encrypt the database?"), QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No) == StandardButton.Yes.value()) { - ChangeFileEncryption.execute(dbPath, dbName, encryptCipher, null, Global.cipherPassword.toCharArray(), true); + ChangeFileEncryption.execute(dbPath, "NeverNote", encryptCipher, null, Global.cipherPassword.toCharArray(), true); + ChangeFileEncryption.execute(dbPath, "Resources", encryptCipher, null, Global.cipherPassword.toCharArray(), true); + ChangeFileEncryption.execute(dbPath, "Index", encryptCipher, null, Global.cipherPassword.toCharArray(), true); Global.setDatabaseUrl(Global.getDatabaseUrl() + ";CIPHER="+encryptCipher); - QMessageBox.information(this, "Encryption Complete", "Encryption is complete"); + Global.setResourceDatabaseUrl(Global.getResourceDatabaseUrl() + ";CIPHER="+encryptCipher); + Global.setIndexDatabaseUrl(Global.getIndexDatabaseUrl() + ";CIPHER="+encryptCipher); + + QMessageBox.information(this, tr("Encryption Complete"), tr("Encryption is complete")); } } catch (SQLException e) { e.printStackTrace(); @@ -771,6 +905,8 @@ public class NeverNote extends QMainWindow{ ChangeFileEncryption.execute(dbPath, dbName, encryptCipher, Global.cipherPassword.toCharArray(), null, true); Global.setDatabaseUrl(""); + Global.setResourceDatabaseUrl(""); + Global.setIndexDatabaseUrl(""); QMessageBox.information(this, tr("Decryption Complete"), tr("Decryption is complete")); } } catch (SQLException e) { @@ -801,7 +937,7 @@ public class NeverNote extends QMainWindow{ } } else { DBEncryptDialog dialog = new DBEncryptDialog(); - dialog.setWindowTitle("Database Decryption"); + dialog.setWindowTitle(tr("Database Decryption")); dialog.hideEncryption(); dialog.exec(); if (dialog.okPressed()) { @@ -834,6 +970,11 @@ public class NeverNote extends QMainWindow{ // Exit point @Override public void closeEvent(QCloseEvent event) { + if (Global.minimizeOnClose() && !closeAction && Global.showTrayIcon()) { + event.ignore(); + hide(); + return; + } logger.log(logger.HIGH, "Entering NeverNote.closeEvent"); waitCursor(true); @@ -857,17 +998,17 @@ public class NeverNote extends QMainWindow{ externalFileEditedSaver(); if (Global.isConnected && Global.synchronizeOnClose()) { setMessage(tr("Performing synchronization before closing.")); + syncRunner.syncNeeded = true; syncRunner.addWork("SYNC"); + } else { + syncRunner.keepRunning = false; } + syncRunner.addWork("STOP"); setMessage("Closing Program."); threadMonitorTimer.stop(); - syncRunner.addWork("STOP"); - syncRunner.keepRunning = false; thumbnailRunner.addWork("STOP"); - syncRunner.keepRunning = false; indexRunner.addWork("STOP"); - syncRunner.keepRunning = false; saveNote(); listManager.stop(); saveWindowState(); @@ -909,19 +1050,31 @@ public class NeverNote extends QMainWindow{ Global.keepRunning = false; try { logger.log(logger.MEDIUM, "Waiting for indexThread to stop"); - indexRunner.thread().join(50); - logger.log(logger.MEDIUM, "Index thread has stopped"); + if (indexRunner.thread().isAlive()) + indexRunner.thread().join(50); + if (!indexRunner.thread().isAlive()) + logger.log(logger.MEDIUM, "Index thread has stopped"); + else { + logger.log(logger.MEDIUM, "Index thread still running - interrupting"); + indexRunner.thread().interrupt(); + } } catch (InterruptedException e1) { e1.printStackTrace(); } - if (!syncRunner.isIdle()) { - try { - logger.log(logger.MEDIUM, "Waiting for syncThread to stop"); - syncThread.join(); - logger.log(logger.MEDIUM, "Sync thread has stopped"); - } catch (InterruptedException e1) { - e1.printStackTrace(); + + if (!syncRunner.thread().isAlive()) { + logger.log(logger.MEDIUM, "Waiting for syncThread to stop"); + if (syncRunner.thread().isAlive()) { + System.out.println(tr("Synchronizing. Please be patient.")); + for(;syncRunner.thread().isAlive();) { + try { + wait(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } } + logger.log(logger.MEDIUM, "Sync thread has stopped"); } if (encryptOnShutdown) { @@ -930,28 +1083,59 @@ public class NeverNote extends QMainWindow{ if (decryptOnShutdown) { decryptOnShutdown(); } + try { + Global.getFileManager().purgeResDirectory(false); + } catch (InitializationException e) { + System.out.println(tr("Empty res directory purge failed")); + e.printStackTrace(); + } logger.log(logger.HIGH, "Leaving NeverNote.closeEvent"); } + @SuppressWarnings("unused") + private void closeNeverNote() { + closeAction = true; + close(); + } public void setMessage(String s) { logger.log(logger.HIGH, "Entering NeverNote.setMessage"); + + statusBar.show(); logger.log(logger.HIGH, "Message: " +s); statusBar.showMessage(s); emitLog.add(s); + + + messageTimer.stop(); + messageTimer.setSingleShot(true); + messageTimer.start(); + + logger.log(logger.HIGH, "Leaving NeverNote.setMessage"); } + + private void clearMessage() { + statusBar.clearMessage(); + statusBar.hide(); + } private void waitCursor(boolean wait) { -// if (wait) -// QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.WaitCursor)); -// else -// QApplication.restoreOverrideCursor(); + if (wait) { + if (QApplication.overrideCursor() == null) + QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.WaitCursor)); + } + else { + while (QApplication.overrideCursor() != null) + QApplication.restoreOverrideCursor(); + } + listManager.refreshCounters(); } private void setupIndexListeners() { - indexRunner.noteSignal.noteIndexed.connect(this, "indexThreadComplete(String)"); - indexRunner.resourceSignal.resourceIndexed.connect(this, "indexThreadComplete(String)"); -// indexRunner.threadSignal.indexNeeded.connect(listManager, "setIndexNeeded(String, String, Boolean)"); +// indexRunner.noteSignal.noteIndexed.connect(this, "indexThreadComplete(String)"); +// indexRunner.resourceSignal.resourceIndexed.connect(this, "indexThreadComplete(String)"); + indexRunner.signal.indexStarted.connect(this, "indexStarted()"); + indexRunner.signal.indexFinished.connect(this, "indexComplete()"); } private void setupSyncSignalListeners() { syncRunner.tagSignal.listChanged.connect(this, "tagIndexUpdated()"); @@ -968,6 +1152,7 @@ public class NeverNote extends QMainWindow{ syncRunner.noteSignal.noteChanged.connect(this, "invalidateNoteCache(String, String)"); syncRunner.resourceSignal.resourceGuidChanged.connect(this, "noteResourceGuidChanged(String,String,String)"); syncRunner.noteSignal.noteDownloaded.connect(listManager, "noteDownloaded(Note)"); + syncRunner.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)"); syncRunner.syncSignal.refreshLists.connect(this, "refreshLists()"); } @@ -991,10 +1176,22 @@ public class NeverNote extends QMainWindow{ browser.noteSignal.geoChanged.connect(listManager, "updateNoteGeoTag(String, Double,Double,Double)"); browser.noteSignal.geoChanged.connect(this, "setNoteDirty()"); browser.noteSignal.sourceUrlChanged.connect(listManager, "updateNoteSourceUrl(String, String)"); + browser.blockApplication.connect(this, "blockApplication(BrowserWindow)"); + browser.unblockApplication.connect(this, "unblockApplication()"); if (master) browser.focusLost.connect(this, "saveNote()"); browser.resourceSignal.contentChanged.connect(this, "externalFileEdited(String)"); + browser.evernoteLinkClicked.connect(this, "evernoteLinkClick(String, String)"); } + //************************************************** + //* Setup shortcuts + //************************************************** + private void setupShortcut(QShortcut action, String text) { + if (!Global.shortcutKeys.containsAction(text)) + return; + action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text))); + } + //*************************************************************** //*************************************************************** //* Settings and look & feel @@ -1014,6 +1211,11 @@ public class NeverNote extends QMainWindow{ indexTimer.start(indexTime); // reset indexing timer settings.exec(); + indexRunner.indexAttachmentsLocally = Global.indexAttachmentsLocally(); + indexRunner.indexNoteBody = Global.indexNoteBody(); + indexRunner.indexNoteTitle = Global.indexNoteTitle(); + indexRunner.specialIndexCharacters = Global.getSpecialIndexCharacters(); + indexRunner.indexImageRecognition = Global.indexImageRecognition(); if (Global.showTrayIcon()) trayIcon.show(); else @@ -1028,19 +1230,29 @@ public class NeverNote extends QMainWindow{ else saveTimer.stop(); - // This is a hack to force a reload of the index in case the date or time changed. -// if (!dateFormat.equals(Global.getDateFormat()) || -// !timeFormat.equals(Global.getTimeFormat())) { - noteCache.clear(); - noteIndexUpdated(true); -// } + // Set special reloads + if (settings.getDebugPage().reloadSharedNotebooksClicked()) { + conn.executeSql("Delete from LinkedNotebook"); + conn.executeSql("delete from SharedNotebook"); + conn.executeSql("Delete from Notebook where linked=true"); + conn.executeSql("Insert into Sync (key, value) values ('FullLinkedNotebookSync', 'true')"); + conn.executeSql("Insert into Sync (key, value) values ('FullSharedNotebookSync', 'true')"); + } + + // Reload user data + noteCache.clear(); + readOnlyCache.clear(); + inkNoteCache.clear(); + noteIndexUpdated(true); + logger.log(logger.HIGH, "Leaving NeverNote.settings"); } // Restore things to the way they were private void restoreWindowState(boolean mainWindow) { // We need to name things or this doesn't work. setObjectName("NeverNote"); + restoreState(Global.restoreState(objectName())); mainLeftRightSplitter.setObjectName("mainLeftRightSplitter"); browserIndexSplitter.setObjectName("browserIndexSplitter"); leftSplitter1.setObjectName("leftSplitter1"); @@ -1059,11 +1271,21 @@ public class NeverNote extends QMainWindow{ Global.saveState(mainLeftRightSplitter.objectName(), mainLeftRightSplitter.saveState()); Global.saveState(browserIndexSplitter.objectName(), browserIndexSplitter.saveState()); Global.saveState(leftSplitter1.objectName(), leftSplitter1.saveState()); + Global.saveState(objectName(), saveState()); } // Load the style sheet private void loadStyleSheet() { - String fileName = Global.getFileManager().getQssDirPath("default.qss"); + String styleSheetName = "default.qss"; + if (Global.getStyle().equalsIgnoreCase("cleanlooks")) + styleSheetName = "default-cleanlooks.qss"; + String fileName = Global.getFileManager().getQssDirPathUser("default.qss"); QFile file = new QFile(fileName); + + // If a user default.qss doesn't exist, we use the one shipped with NeverNote + if (!file.exists()) { + fileName = Global.getFileManager().getQssDirPath(styleSheetName); + file = new QFile(fileName); + } file.open(OpenModeFlag.ReadOnly); String styleSheet = file.readAll().toString(); file.close(); @@ -1093,6 +1315,8 @@ public class NeverNote extends QMainWindow{ Global.setColumnPosition("noteTableGuidPosition", position); position = noteTableView.header.visualIndex(Global.noteTableThumbnailPosition); Global.setColumnPosition("noteTableThumbnailPosition", position); + position = noteTableView.header.visualIndex(Global.noteTablePinnedPosition); + Global.setColumnPosition("noteTablePinnedPosition", position); } // Save column widths for the next time @@ -1124,6 +1348,32 @@ public class NeverNote extends QMainWindow{ Global.setColumnWidth("noteTableGuidPosition", width); } + @SuppressWarnings("unused") + private void toggleSearchWindow() { + logger.log(logger.HIGH, "Entering NeverNote.toggleSearchWindow"); + searchLayout.toggleSearchField(); + menuBar.hideSearch.setChecked(searchField.isVisible()); + Global.saveWindowVisible("searchField", searchField.isVisible()); + logger.log(logger.HIGH, "Leaving NeverNote.toggleSearchWindow"); + } + @SuppressWarnings("unused") + private void toggleQuotaWindow() { + logger.log(logger.HIGH, "Entering NeverNote.toggleQuotaWindow"); + searchLayout.toggleQuotaBar(); + menuBar.hideQuota.setChecked(quotaBar.isVisible()); + Global.saveWindowVisible("quota", quotaBar.isVisible()); + logger.log(logger.HIGH, "Leaving NeverNote.toggleQuotaWindow"); + } + @SuppressWarnings("unused") + private void toggleZoomWindow() { + logger.log(logger.HIGH, "Entering NeverNote.toggleZoomWindow"); + searchLayout.toggleZoom(); + menuBar.hideZoom.setChecked(zoomSpinner.isVisible()); + Global.saveWindowVisible("zoom", zoomSpinner.isVisible()); + logger.log(logger.HIGH, "Leaving NeverNote.toggleZoomWindow"); + } + + //*************************************************************** //*************************************************************** @@ -1133,15 +1383,16 @@ public class NeverNote extends QMainWindow{ // Setup the tree containing the user's notebooks. private void initializeNotebookTree() { logger.log(logger.HIGH, "Entering NeverNote.initializeNotebookTree"); - notebookTree.itemSelectionChanged.connect(this, "notebookTreeSelection()"); +// notebookTree.itemClicked.connect(this, "notebookTreeSelection()"); + notebookTree.selectionSignal.connect(this, "notebookTreeSelection()"); listManager.notebookSignal.refreshNotebookTreeCounts.connect(notebookTree, "updateCounts(List, List)"); - // notebookTree.resize(Global.getSize("notebookTree")); logger.log(logger.HIGH, "Leaving NeverNote.initializeNotebookTree"); } // Listener when a notebook is selected private void notebookTreeSelection() { logger.log(logger.HIGH, "Entering NeverNote.notebookTreeSelection"); - + noteTableView.proxyModel.blocked = true; + clearTrashFilter(); clearAttributeFilter(); clearSavedSearchFilter(); @@ -1152,35 +1403,60 @@ public class NeverNote extends QMainWindow{ menuBar.noteRestoreAction.setVisible(false); menuBar.notebookEditAction.setEnabled(true); menuBar.notebookDeleteAction.setEnabled(true); + menuBar.notebookPublishAction.setEnabled(true); + menuBar.notebookShareAction.setEnabled(true); + menuBar.notebookIconAction.setEnabled(true); + menuBar.notebookStackAction.setEnabled(true); List selections = notebookTree.selectedItems(); - QTreeWidgetItem currentSelection; selectedNotebookGUIDs.clear(); - if (!Global.mimicEvernoteInterface) { - for (int i=0; i 0) { + guid = (selections.get(0).text(2)); + stackName = selections.get(0).text(0); + } + if (!Global.mimicEvernoteInterface) { + // If no notebooks are selected, we make it look like the "all notebooks" one was selected + if (selections.size()==0) { + selectedNotebookGUIDs.clear(); + for (int i=0; i < listManager.getNotebookIndex().size(); i++) { + selectedNotebookGUIDs.add(listManager.getNotebookIndex().get(i).getGuid()); + } + menuBar.notebookEditAction.setEnabled(false); + menuBar.notebookDeleteAction.setEnabled(false); + menuBar.notebookStackAction.setEnabled(false); + menuBar.notebookIconAction.setEnabled(false); + } + } + if (!guid.equals("") && !guid.equals("STACK")) { + selectedNotebookGUIDs.add(guid); + menuBar.notebookIconAction.setEnabled(true); } else { - String guid = ""; - if (selections.size() > 0) - guid = (selections.get(0).text(2)); - if (!guid.equals("")) - selectedNotebookGUIDs.add(guid); + menuBar.notebookIconAction.setEnabled(true); + for (int j=0; j icons = conn.getNotebookTable().getAllIcons(); + notebookTree.setIcons(icons); + + if (selectedNotebookGUIDs == null) selectedNotebookGUIDs = new ArrayList(); List books = conn.getNotebookTable().getAll(); for (int i=books.size()-1; i>=0; i--) { @@ -1218,17 +1499,17 @@ public class NeverNote extends QMainWindow{ if (!found) selectedNotebookGUIDs.remove(i); } + listManager.refreshCounters = true; + listManager.refreshCounters(); notebookTree.blockSignals(false); logger.log(logger.HIGH, "Leaving NeverNote.notebookIndexUpdated"); } // Show/Hide note information + @SuppressWarnings("unused") private void toggleNotebookWindow() { logger.log(logger.HIGH, "Entering NeverNote.toggleNotebookWindow"); - if (notebookTree.isVisible()) - notebookTree.hide(); - else - notebookTree.show(); + searchLayout.toggleNotebook(); menuBar.hideNotebooks.setChecked(notebookTree.isVisible()); Global.saveWindowVisible("notebookTree", notebookTree.isVisible()); logger.log(logger.HIGH, "Leaving NeverNote.toggleNotebookWindow"); @@ -1268,29 +1549,90 @@ public class NeverNote extends QMainWindow{ } // Edit an existing notebook @SuppressWarnings("unused") + private void stackNotebook() { + logger.log(logger.HIGH, "Entering NeverNote.stackNotebook"); + StackNotebook edit = new StackNotebook(); + + List selections = notebookTree.selectedItems(); + QTreeWidgetItem currentSelection; + for (int i=0; i selections = notebookTree.selectedItems(); QTreeWidgetItem currentSelection; currentSelection = selections.get(0); edit.setNotebook(currentSelection.text(0)); - edit.setNotebooks(listManager.getNotebookIndex()); - + String guid = currentSelection.text(2); - for (int i=0; i filteredBooks = notebookFilter.getValidNotebooks(currentNote, listManager.getNotebookIndex()); + browserWindow.setNotebookList(filteredBooks); + Iterator set = externalWindows.keySet().iterator(); + while(set.hasNext()) + externalWindows.get(set.next()).getBrowserWindow().setNotebookList(filteredBooks); logger.log(logger.HIGH, "Leaving NeverNote.editNotebook"); } + // Publish a notebook + @SuppressWarnings("unused") + private void publishNotebook() { + List selections = notebookTree.selectedItems(); + QTreeWidgetItem currentSelection; + currentSelection = selections.get(0); + String guid = currentSelection.text(2); + + if (guid.equalsIgnoreCase("STACK") || guid.equalsIgnoreCase("")) + return; + + Notebook n = null; + int position = 0; + for (int i=0; i selections = notebookTree.selectedItems(); + QTreeWidgetItem currentSelection; + currentSelection = selections.get(0); + String guid = currentSelection.text(2); + + if (guid.equalsIgnoreCase("STACK") || guid.equalsIgnoreCase("")) + return; + + Notebook n = null;; + for (int i=0; i selections = notebookTree.selectedItems(); @@ -1334,13 +1753,18 @@ public class NeverNote extends QMainWindow{ QTreeWidgetItem currentSelection; currentSelection = selections.get(i); String guid = currentSelection.text(2); - for (int j=0; j=0; i--) { - // if (dbRunner.getLocalNotebooks().get(i).equals(arg0)) - // } - notebookTreeSelection(); - notebookTree.load(listManager.getNotebookIndex(), listManager.getLocalNotebooks()); - listManager.countNotebookResults(listManager.getNoteIndex()); -// notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter()); + + notebookIndexUpdated(); +// notebookTreeSelection(); +// notebookTree.load(listManager.getNotebookIndex(), listManager.getLocalNotebooks()); +// listManager.countNotebookResults(listManager.getNoteIndex()); logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook"); } // A note's notebook has been updated @@ -1450,6 +1888,7 @@ public class NeverNote extends QMainWindow{ listManager.loadNotesIndex(); notebookIndexUpdated(); noteIndexUpdated(false); + reloadTagTree(true); // noteIndexUpdated(false); // Build a list of non-closed notebooks @@ -1463,12 +1902,100 @@ public class NeverNote extends QMainWindow{ if (!found) nbooks.add(listManager.getNotebookIndex().get(i)); } + + FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger); + List filteredBooks = notebookFilter.getValidNotebooks(currentNote, listManager.getNotebookIndex()); + browserWindow.setNotebookList(filteredBooks); + + // Update any external windows + Iterator set = externalWindows.keySet().iterator(); + while(set.hasNext()) + externalWindows.get(set.next()).getBrowserWindow().setNotebookList(filteredBooks); + waitCursor(false); - browserWindow.setNotebookList(nbooks); } + // Change the notebook's icon + @SuppressWarnings("unused") + private void setNotebookIcon() { + boolean stackSelected = false; + boolean allNotebookSelected = false; + + QTreeWidgetItem currentSelection; + List selections = notebookTree.selectedItems(); + if (selections.size() == 0) + return; + + currentSelection = selections.get(0); + String guid = currentSelection.text(2); + if (guid.equalsIgnoreCase("")) + allNotebookSelected = true; + if (guid.equalsIgnoreCase("STACK")) + stackSelected = true; + QIcon currentIcon = currentSelection.icon(0); + QIcon icon; + SetIcon dialog; + + if (!stackSelected && !allNotebookSelected) { + icon = conn.getNotebookTable().getIcon(guid); + if (icon == null) { + dialog = new SetIcon(currentIcon, saveLastPath); + dialog.setUseDefaultIcon(true); + } else { + dialog = new SetIcon(icon, saveLastPath); + dialog.setUseDefaultIcon(false); + } + } else { + if (stackSelected) { + icon = conn.getSystemIconTable().getIcon(currentSelection.text(0), "STACK"); + } else { + icon = conn.getSystemIconTable().getIcon(currentSelection.text(0), "ALLNOTEBOOK"); + } + if (icon == null) { + dialog = new SetIcon(currentIcon, saveLastPath); + dialog.setUseDefaultIcon(true); + } else { + dialog = new SetIcon(icon, saveLastPath); + dialog.setUseDefaultIcon(false); + } + } + dialog.exec(); + if (dialog.okPressed()) { + saveLastPath = dialog.getPath(); + + QIcon newIcon = dialog.getIcon(); + if (stackSelected) { + conn.getSystemIconTable().setIcon(currentSelection.text(0), "STACK", newIcon, dialog.getFileType()); + if (newIcon == null) { + newIcon = new QIcon(iconPath+"books2.png"); + } + currentSelection.setIcon(0,newIcon); + return; + } + if (allNotebookSelected) { + conn.getSystemIconTable().setIcon(currentSelection.text(0), "ALLNOTEBOOK", newIcon, dialog.getFileType()); + if (newIcon == null) { + newIcon = new QIcon(iconPath+"notebook-green.png"); + } + currentSelection.setIcon(0,newIcon); + return; + } + conn.getNotebookTable().setIcon(guid, newIcon, dialog.getFileType()); + if (newIcon == null) { + boolean isPublished = false;; + boolean found = false; + for (int i=0; i selections = tagTree.selectedItems(); + QTreeWidgetItem currentSelection = null; + if (selections.size() > 0) { + currentSelection = selections.get(0); + edit.setParentTag(currentSelection.text(0)); + } + edit.exec(); if (!edit.okPressed()) @@ -1495,23 +2030,34 @@ public class NeverNote extends QMainWindow{ newTag.setUpdateSequenceNum(0); newTag.setGuid(randint); newTag.setName(edit.getTag()); + if (edit.getParentTag().isChecked()) { + newTag.setParentGuid(currentSelection.text(2)); + newTag.setParentGuidIsSet(true); + currentSelection.setExpanded(true); + } conn.getTagTable().addTag(newTag, true); listManager.getTagIndex().add(newTag); - reloadTagTree(); + reloadTagTree(true); logger.log(logger.HIGH, "Leaving NeverNote.addTag"); } + @SuppressWarnings("unused") private void reloadTagTree() { + reloadTagTree(false); + } + private void reloadTagTree(boolean reload) { logger.log(logger.HIGH, "Entering NeverNote.reloadTagTree"); - tagIndexUpdated(false); + tagIndexUpdated(reload); boolean filter = false; - listManager.countTagResults(listManager.getNoteIndex()); + if (reload) + listManager.countTagResults(listManager.getNoteIndex()); if (notebookTree.selectedItems().size() > 0 && !notebookTree.selectedItems().get(0).text(0).equalsIgnoreCase("All Notebooks")) filter = true; if (tagTree.selectedItems().size() > 0) filter = true; tagTree.showAllTags(!filter); + tagIndexUpdated(false); logger.log(logger.HIGH, "Leaving NeverNote.reloadTagTree"); } // Edit an existing tag @@ -1592,7 +2138,9 @@ public class NeverNote extends QMainWindow{ // Setup the tree containing the user's tags private void initializeTagTree() { logger.log(logger.HIGH, "Entering NeverNote.initializeTagTree"); - tagTree.itemSelectionChanged.connect(this, "tagTreeSelection()"); +// tagTree.itemSelectionChanged.connect(this, "tagTreeSelection()"); +// tagTree.itemClicked.connect(this, "tagTreeSelection()"); + tagTree.selectionSignal.connect(this, "tagTreeSelection()"); listManager.tagSignal.refreshTagTreeCounts.connect(tagTree, "updateCounts(List)"); logger.log(logger.HIGH, "Leaving NeverNote.initializeTagTree"); } @@ -1616,14 +2164,23 @@ public class NeverNote extends QMainWindow{ if (selections.size() > 0) { menuBar.tagEditAction.setEnabled(true); menuBar.tagDeleteAction.setEnabled(true); + menuBar.tagIconAction.setEnabled(true); } else { menuBar.tagEditAction.setEnabled(false); menuBar.tagDeleteAction.setEnabled(false); + menuBar.tagIconAction.setEnabled(true); } + if (selections.size() > 1) + menuBar.tagMergeAction.setEnabled(true); + else + menuBar.tagMergeAction.setEnabled(false); listManager.setSelectedTags(selectedTagGUIDs); listManager.loadNotesIndex(); noteIndexUpdated(false); + refreshEvernoteNote(true); + listManager.refreshCounters = true; + listManager.refreshCounters(); logger.log(logger.HIGH, "Leaving NeverNote.tagTreeSelection"); } // trigger the tag index to be refreshed @@ -1635,11 +2192,15 @@ public class NeverNote extends QMainWindow{ logger.log(logger.HIGH, "Entering NeverNote.tagIndexUpdated"); if (selectedTagGUIDs == null) selectedTagGUIDs = new ArrayList(); -// selectedTagGUIDs.clear(); // clear out old entries + if (reload) + listManager.reloadTagIndex(); tagTree.blockSignals(true); - if (reload) + if (reload) { + tagTree.setIcons(conn.getTagTable().getAllIcons()); tagTree.load(listManager.getTagIndex()); + } + for (int i=selectedTagGUIDs.size()-1; i>=0; i--) { boolean found = tagTree.selectGuid(selectedTagGUIDs.get(i)); if (!found) @@ -1651,6 +2212,7 @@ public class NeverNote extends QMainWindow{ logger.log(logger.HIGH, "Leaving NeverNote.tagIndexUpdated"); } // Show/Hide note information + @SuppressWarnings("unused") private void toggleTagWindow() { logger.log(logger.HIGH, "Entering NeverNote.toggleTagWindow"); if (tagTree.isVisible()) @@ -1759,12 +2321,76 @@ public class NeverNote extends QMainWindow{ tagTree.clearSelection(); menuBar.noteRestoreAction.setVisible(false); menuBar.tagEditAction.setEnabled(false); + menuBar.tagMergeAction.setEnabled(false); menuBar.tagDeleteAction.setEnabled(false); + menuBar.tagIconAction.setEnabled(false); selectedTagGUIDs.clear(); listManager.setSelectedTags(selectedTagGUIDs); tagTree.blockSignals(false); } + // Change the icon for a tag + @SuppressWarnings("unused") + private void setTagIcon() { + QTreeWidgetItem currentSelection; + List selections = tagTree.selectedItems(); + if (selections.size() == 0) + return; + + currentSelection = selections.get(0); + String guid = currentSelection.text(2); + + QIcon currentIcon = currentSelection.icon(0); + QIcon icon = conn.getTagTable().getIcon(guid); + SetIcon dialog; + if (icon == null) { + dialog = new SetIcon(currentIcon, saveLastPath); + dialog.setUseDefaultIcon(true); + } else { + dialog = new SetIcon(icon, saveLastPath); + dialog.setUseDefaultIcon(false); + } + dialog.exec(); + if (dialog.okPressed()) { + saveLastPath = dialog.getPath(); + QIcon newIcon = dialog.getIcon(); + conn.getTagTable().setIcon(guid, newIcon, dialog.getFileType()); + if (newIcon == null) + newIcon = new QIcon(iconPath+"tag.png"); + currentSelection.setIcon(0, newIcon); + } + } + // Merge tags + @SuppressWarnings("unused") + private void mergeTags() { + List tags = new ArrayList(); + List selections = tagTree.selectedItems(); + for (int i=0; i noteGuids = conn.getNoteTable().noteTagsTable.getTagNotes(tags.get(i).getGuid()); + for (int j=0; j selections = savedSearchTree.selectedItems(); QTreeWidgetItem currentSelection; selectedSavedSearchGUID = ""; @@ -1906,6 +2533,7 @@ public class NeverNote extends QMainWindow{ private void clearSavedSearchFilter() { menuBar.savedSearchEditAction.setEnabled(false); menuBar.savedSearchDeleteAction.setEnabled(false); + menuBar.savedSearchIconAction.setEnabled(false); savedSearchTree.blockSignals(true); savedSearchTree.clearSelection(); savedSearchTree.blockSignals(false); @@ -1919,6 +2547,7 @@ public class NeverNote extends QMainWindow{ if (selectedSavedSearchGUID == null) selectedSavedSearchGUID = new String(); savedSearchTree.blockSignals(true); + savedSearchTree.setIcons(conn.getSavedSearchTable().getAllIcons()); savedSearchTree.load(listManager.getSavedSearchIndex()); savedSearchTree.selectGuid(selectedSavedSearchGUID); savedSearchTree.blockSignals(false); @@ -1930,17 +2559,20 @@ public class NeverNote extends QMainWindow{ menuBar.savedSearchEditAction.setEnabled(true); menuBar.savedSearchDeleteAction.setEnabled(true); + menuBar.savedSearchIconAction.setEnabled(true); List selections = savedSearchTree.selectedItems(); if (selections.size() > 0) { menuBar.savedSearchEditAction.setEnabled(true); menuBar.savedSearchDeleteAction.setEnabled(true); + menuBar.savedSearchIconAction.setEnabled(true); selectedSavedSearchGUID = selections.get(0).text(1); SavedSearch s = conn.getSavedSearchTable().getSavedSearch(selectedSavedSearchGUID); searchField.setEditText(s.getQuery()); } else { menuBar.savedSearchEditAction.setEnabled(false); menuBar.savedSearchDeleteAction.setEnabled(false); + menuBar.savedSearchIconAction.setEnabled(false); selectedSavedSearchGUID = ""; searchField.setEditText(""); } @@ -1951,6 +2583,7 @@ public class NeverNote extends QMainWindow{ } // Show/Hide note information + @SuppressWarnings("unused") private void toggleSavedSearchWindow() { logger.log(logger.HIGH, "Entering NeverNote.toggleSavedSearchWindow"); if (savedSearchTree.isVisible()) @@ -1962,6 +2595,38 @@ public class NeverNote extends QMainWindow{ Global.saveWindowVisible("savedSearchTree", savedSearchTree.isVisible()); logger.log(logger.HIGH, "Leaving NeverNote.toggleSavedSearchWindow"); } + // Change the icon for a saved search + @SuppressWarnings("unused") + private void setSavedSearchIcon() { + QTreeWidgetItem currentSelection; + List selections = savedSearchTree.selectedItems(); + if (selections.size() == 0) + return; + + currentSelection = selections.get(0); + String guid = currentSelection.text(1); + + QIcon currentIcon = currentSelection.icon(0); + QIcon icon = conn.getSavedSearchTable().getIcon(guid); + SetIcon dialog; + if (icon == null) { + dialog = new SetIcon(currentIcon, saveLastPath); + dialog.setUseDefaultIcon(true); + } else { + dialog = new SetIcon(icon, saveLastPath); + dialog.setUseDefaultIcon(false); + } + dialog.exec(); + if (dialog.okPressed()) { + saveLastPath = dialog.getPath(); + QIcon newIcon = dialog.getIcon(); + conn.getSavedSearchTable().setIcon(guid, newIcon, dialog.getFileType()); + if (newIcon == null) + newIcon = new QIcon(iconPath+"search.png"); + currentSelection.setIcon(0, newIcon); + } + + } @@ -1975,6 +2640,7 @@ public class NeverNote extends QMainWindow{ @SuppressWarnings("unused") private void databaseStatus() { waitCursor(true); + indexRunner.interrupt = true; int dirty = conn.getNoteTable().getDirtyCount(); int unindexed = conn.getNoteTable().getUnindexedCount(); DatabaseStatus status = new DatabaseStatus(); @@ -1982,6 +2648,7 @@ public class NeverNote extends QMainWindow{ status.setUnindexed(unindexed); status.setNoteCount(conn.getNoteTable().getNoteCount()); status.setNotebookCount(listManager.getNotebookIndex().size()); + status.setUnindexedResourceCount(conn.getNoteTable().noteResourceTable.getUnindexedCount()); status.setSavedSearchCount(listManager.getSavedSearchIndex().size()); status.setTagCount(listManager.getTagIndex().size()); status.setResourceCount(conn.getNoteTable().noteResourceTable.getResourceCount()); @@ -1995,7 +2662,7 @@ public class NeverNote extends QMainWindow{ logger.log(logger.HIGH, "Entering NeverNote.compactDatabase"); if (QMessageBox.question(this, tr("Confirmation"), tr("This will free unused space in the database, "+ "but please be aware that depending upon the size of your database this can be time consuming " + - "and NeverNote will be unresponsive until it is complete. Do you wish to continue?"), + "and NixNote will be unresponsive until it is complete. Do you wish to continue?"), QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) { return; @@ -2037,15 +2704,8 @@ public class NeverNote extends QMainWindow{ @SuppressWarnings("unused") private void logger() { logger.log(logger.HIGH, "Entering NeverNote.logger"); - QDialog dialog = new QDialog(this); - QHBoxLayout layout = new QHBoxLayout(); - QListWidget textBox = new QListWidget(); - layout.addWidget(textBox); - textBox.addItems(emitLog); - - dialog.setLayout(layout); - dialog.setWindowTitle(tr("Mesasge Log")); - dialog.show(); + LogFileDialog dialog = new LogFileDialog(emitLog); + dialog.exec(); logger.log(logger.HIGH, "Leaving NeverNote.logger"); } // Menu option "help/about" was selected @@ -2053,8 +2713,8 @@ public class NeverNote extends QMainWindow{ private void about() { logger.log(logger.HIGH, "Entering NeverNote.about"); QMessageBox.about(this, - tr("About NeverNote"), - tr("

NeverNote


Version ") + tr("About NixNote"), + tr("

NixNote


Version ") +Global.version +tr("
Evernote" +"An Open Source Evernote Client.

" @@ -2065,7 +2725,9 @@ public class NeverNote extends QMainWindow{ +"JTidy is copyrighted under the World Wide Web Consortium
" +"Apache Common Utilities licensed under the Apache License Version 2.0
" +"Jazzy is licened under the LGPL
" - +"Java is a registered trademark of Oracle Corporation.

")); + +"Java is a registered trademark of Oracle Corporation.

" + +"Special thanks to:
BitRock InstallBuilder for the Windows installer" + +"
CodeCogs (www.codecogs.com) for the LaTeX image rendering.")); logger.log(logger.HIGH, "Leaving NeverNote.about"); } // Hide the entire left hand side @@ -2076,47 +2738,141 @@ public class NeverNote extends QMainWindow{ hidden = !menuBar.hideLeftSide.isChecked(); menuBar.hideLeftSide.setChecked(!hidden); - if (notebookTree.isVisible() != hidden) - toggleNotebookWindow(); - if (savedSearchTree.isVisible() != hidden) - toggleSavedSearchWindow(); - if (tagTree.isVisible() != hidden) - toggleTagWindow(); - if (attributeTree.isVisible() != hidden) - toggleAttributesWindow(); - if (trashTree.isVisible() != hidden) - toggleTrashWindow(); + if (!hidden) + leftSplitter1.setHidden(true); + else + leftSplitter1.setHidden(false); Global.saveWindowVisible("leftPanel", hidden); } + public void checkForUpdates() { + // Send off thread to check for a new version + versionChecker = new QNetworkAccessManager(this); + versionChecker.finished.connect(this, "upgradeFileRead(QNetworkReply)"); + QNetworkRequest request = new QNetworkRequest(); + request.setUrl(new QUrl(Global.getUpdatesAvailableUrl())); + versionChecker.get(request); + } + @SuppressWarnings("unused") + private void upgradeFileRead(QNetworkReply reply) { + if (!reply.isReadable()) + return; + + String winVersion = Global.version; + String osxVersion = Global.version; + String linuxVersion = Global.version; + String linux64Version = Global.version; + String version = Global.version; + + // Determine the versions available + QByteArray data = reply.readLine(); + while (data != null && !reply.atEnd()) { + String line = data.toString(); + String lineVersion; + if (line.contains(":")) + lineVersion = line.substring(line.indexOf(":")+1).replace(" ", "").replace("\n", ""); + else + lineVersion = ""; + if (line.toLowerCase().contains("windows")) + winVersion = lineVersion; + else if (line.toLowerCase().contains("os-x")) + osxVersion = lineVersion; + else if (line.toLowerCase().contains("linux amd64")) + linux64Version = lineVersion; + else if (line.toLowerCase().contains("linux i386")) + linuxVersion = lineVersion; + else if (line.toLowerCase().contains("default")) + version = lineVersion; + // Read the next line + data = reply.readLine(); + } + + // Now we need to determine what system we are on. + if (System.getProperty("os.name").toLowerCase().contains("windows")) + version = winVersion; + if (System.getProperty("os.name").toLowerCase().contains("mac os")) + version = osxVersion; + if (System.getProperty("os.name").toLowerCase().contains("Linux")) { + if (System.getProperty("os.arch").contains("amd64") || + System.getProperty("os.arch").contains("x86_64")) + version = linux64Version; + else + version = linuxVersion; + } + + + for (String validVersion : Global.validVersions) { + if (version.equals(validVersion)) + return; + } + + UpgradeAvailableDialog dialog = new UpgradeAvailableDialog(); + dialog.exec(); + if (dialog.remindMe()) + Global.setCheckVersionUpgrade(true); + else + Global.setCheckVersionUpgrade(false); + } + //*************************************************************** //*************************************************************** //** These functions deal with the Toolbar //*************************************************************** - //*************************************************************** + //*************************************************************** + @SuppressWarnings("unused") + private void focusSearch() { + searchField.setFocus(); + } + // Text in the search bar has been cleared private void searchFieldCleared() { + saveNote(); + + // This is done because we want to force a reload of + // images. Some images we may want to highlight the text. + readOnlyCache.clear(); + inkNoteCache.clear(); + noteCache.clear(); + QWebSettings.setMaximumPagesInCache(0); + QWebSettings.setObjectCacheCapacities(0, 0, 0); + searchField.setEditText(""); saveNoteColumnPositions(); saveNoteIndexWidth(); + noteIndexUpdated(true); + if (currentNote == null && listManager.getNoteIndex().size() > 0) { + currentNote = listManager.getNoteIndex().get(0); + currentNoteGuid = currentNote.getGuid(); + } + refreshEvernoteNote(true); + if (currentNote != null) + loadNoteBrowserInformation(browserWindow, currentNoteGuid, currentNote); } // text in the search bar changed. We only use this to tell if it was cleared, // otherwise we trigger off searchFieldChanged. @SuppressWarnings("unused") private void searchFieldTextChanged(String text) { + QWebSettings.setMaximumPagesInCache(0); + QWebSettings.setObjectCacheCapacities(0, 0, 0); + if (text.trim().equals("")) { searchFieldCleared(); if (searchPerformed) { + + // This is done because we want to force a reload of + // images. Some images we may want to highlight the text. noteCache.clear(); + readOnlyCache.clear(); + inkNoteCache.clear(); + listManager.setEnSearch(""); -///// listManager.clearNoteIndexSearch(); - //noteIndexUpdated(true); listManager.loadNotesIndex(); refreshEvernoteNote(true); noteIndexUpdated(false); + refreshEvernoteNote(true); } searchPerformed = false; } @@ -2125,12 +2881,13 @@ public class NeverNote extends QMainWindow{ private void searchFieldChanged() { logger.log(logger.HIGH, "Entering NeverNote.searchFieldChanged"); noteCache.clear(); + readOnlyCache.clear(); + inkNoteCache.clear(); saveNoteColumnPositions(); saveNoteIndexWidth(); String text = searchField.currentText(); listManager.setEnSearch(text.trim()); listManager.loadNotesIndex(); -//--->>> noteIndexUpdated(true); noteIndexUpdated(false); refreshEvernoteNote(true); searchPerformed = true; @@ -2141,117 +2898,115 @@ public class NeverNote extends QMainWindow{ private void setupToolBar() { logger.log(logger.HIGH, "Entering NeverNote.setupToolBar"); toolBar = addToolBar(tr("Tool Bar")); + toolBar.setObjectName("toolBar"); menuBar.setupToolBarVisible(); if (!Global.isWindowVisible("toolBar")) toolBar.setVisible(false); else toolBar.setVisible(true); - prevButton = toolBar.addAction("Previous"); +// toolBar.addWidget(menuBar); +// menuBar.setSizePolicy(Policy.Minimum, Policy.Minimum); +// toolBar.addSeparator(); + prevButton = toolBar.addAction(tr("Previous")); QIcon prevIcon = new QIcon(iconPath+"back.png"); prevButton.setIcon(prevIcon); prevButton.triggered.connect(this, "previousViewedAction()"); togglePrevArrowButton(Global.isToolbarButtonVisible("prevArrow")); - nextButton = toolBar.addAction("Next"); + nextButton = toolBar.addAction(tr("Next")); QIcon nextIcon = new QIcon(iconPath+"forward.png"); nextButton.setIcon(nextIcon); nextButton.triggered.connect(this, "nextViewedAction()"); toggleNextArrowButton(Global.isToolbarButtonVisible("nextArrow")); - upButton = toolBar.addAction("Up"); + upButton = toolBar.addAction(tr("Up")); QIcon upIcon = new QIcon(iconPath+"up.png"); upButton.setIcon(upIcon); upButton.triggered.connect(this, "upAction()"); toggleUpArrowButton(Global.isToolbarButtonVisible("upArrow")); - downButton = toolBar.addAction("Down"); + downButton = toolBar.addAction(tr("Down")); QIcon downIcon = new QIcon(iconPath+"down.png"); downButton.setIcon(downIcon); downButton.triggered.connect(this, "downAction()"); toggleDownArrowButton(Global.isToolbarButtonVisible("downArrow")); - synchronizeButton = toolBar.addAction("Synchronize"); + synchronizeButton = toolBar.addAction(tr("Synchronize")); synchronizeButton.setIcon(new QIcon(iconPath+"synchronize.png")); synchronizeIconAngle = 0; synchronizeButton.triggered.connect(this, "evernoteSync()"); toggleSynchronizeButton(Global.isToolbarButtonVisible("synchronize")); - printButton = toolBar.addAction("Print"); + printButton = toolBar.addAction(tr("Print")); QIcon printIcon = new QIcon(iconPath+"print.png"); printButton.setIcon(printIcon); printButton.triggered.connect(this, "printNote()"); togglePrintButton(Global.isToolbarButtonVisible("print")); - tagButton = toolBar.addAction("Tag"); + tagButton = toolBar.addAction(tr("Tag")); QIcon tagIcon = new QIcon(iconPath+"tag.png"); tagButton.setIcon(tagIcon); tagButton.triggered.connect(browserWindow, "modifyTags()"); toggleTagButton(Global.isToolbarButtonVisible("tag")); - attributeButton = toolBar.addAction("Attributes"); + attributeButton = toolBar.addAction(tr("Attributes")); QIcon attributeIcon = new QIcon(iconPath+"attribute.png"); attributeButton.setIcon(attributeIcon); attributeButton.triggered.connect(this, "toggleNoteInformation()"); toggleAttributeButton(Global.isToolbarButtonVisible("attribute")); - emailButton = toolBar.addAction("Email"); + emailButton = toolBar.addAction(tr("Email")); QIcon emailIcon = new QIcon(iconPath+"email.png"); emailButton.setIcon(emailIcon); emailButton.triggered.connect(this, "emailNote()"); toggleEmailButton(Global.isToolbarButtonVisible("email")); - deleteButton = toolBar.addAction("Delete"); + deleteButton = toolBar.addAction(tr("Delete")); QIcon deleteIcon = new QIcon(iconPath+"delete.png"); deleteButton.setIcon(deleteIcon); deleteButton.triggered.connect(this, "deleteNote()"); toggleDeleteButton(Global.isToolbarButtonVisible("delete")); - newButton = toolBar.addAction("New"); + newButton = toolBar.addAction(tr("New")); QIcon newIcon = new QIcon(iconPath+"new.png"); newButton.triggered.connect(this, "addNote()"); newButton.setIcon(newIcon); toggleNewButton(Global.isToolbarButtonVisible("new")); - allNotesButton = toolBar.addAction("All Notes"); + allNotesButton = toolBar.addAction(tr("All Notes")); QIcon allIcon = new QIcon(iconPath+"books.png"); allNotesButton.triggered.connect(this, "allNotes()"); allNotesButton.setIcon(allIcon); toggleAllNotesButton(Global.isToolbarButtonVisible("allNotes")); - toolBar.addSeparator(); - toolBar.addWidget(new QLabel(tr("Quota:"))); - toolBar.addWidget(quotaBar); + //toolBar.addSeparator(); + //toolBar.addWidget(new QLabel(tr("Quota:"))); + //toolBar.addWidget(quotaBar); //quotaBar.setSizePolicy(Policy.Minimum, Policy.Minimum); updateQuotaBar(); - toolBar.addSeparator(); + //toolBar.addSeparator(); - // Setup the zoom - zoomSpinner = new QSpinBox(); - zoomSpinner.setMinimum(10); - zoomSpinner.setMaximum(1000); - zoomSpinner.setAccelerated(true); - zoomSpinner.setSingleStep(10); - zoomSpinner.setValue(100); - zoomSpinner.valueChanged.connect(this, "zoomChanged()"); - toolBar.addWidget(new QLabel(tr("Zoom"))); - toolBar.addWidget(zoomSpinner); + //toolBar.addWidget(new QLabel(tr("Zoom"))); + //toolBar.addWidget(zoomSpinner); //toolBar.addWidget(new QLabel(" ")); - toolBar.addSeparator(); - toolBar.addWidget(new QLabel(tr(" Search:"))); - toolBar.addWidget(searchField); + //toolBar.addSeparator(); + //toolBar.addWidget(new QLabel(tr(" Search:"))); + //toolBar.addWidget(searchField); QSizePolicy sizePolicy = new QSizePolicy(); sizePolicy.setHorizontalPolicy(Policy.MinimumExpanding); - searchField.setSizePolicy(sizePolicy); - searchField.setInsertPolicy(InsertPolicy.InsertAtTop); + QLabel spacer = new QLabel(""); + spacer.setSizePolicy(sizePolicy); + toolBar.addWidget(spacer); + //searchField.setInsertPolicy(InsertPolicy.InsertAtTop); - searchClearButton = toolBar.addAction("Search Clear"); - QIcon searchClearIcon = new QIcon(iconPath+"searchclear.png"); - searchClearButton.setIcon(searchClearIcon); - searchClearButton.triggered.connect(this, "searchFieldCleared()"); - toggleSearchClearButton(Global.isToolbarButtonVisible("searchClear")); + //searchClearButton = toolBar.addAction("Search Clear"); + //QIcon searchClearIcon = new QIcon(iconPath+"searchclear.png"); + //searchClearButton.setIcon(searchClearIcon); + //searchClearButton.triggered.connect(this, "searchFieldCleared()"); + //toggleSearchClearButton(Global.isToolbarButtonVisible("searchClear")); logger.log(logger.HIGH, "Leaving NeverNote.setupToolBar"); } @@ -2371,7 +3126,8 @@ public class NeverNote extends QMainWindow{ allNotesButton.setVisible(toggle); Global.saveToolbarButtonsVisible("allNotes", toggle); } - private void toggleSearchClearButton(Boolean toggle) { + @SuppressWarnings("unused") + private void toggleSearchClearButton(Boolean toggle) { searchClearButton.setVisible(toggle); Global.saveToolbarButtonsVisible("searchClear", toggle); } @@ -2382,51 +3138,43 @@ public class NeverNote extends QMainWindow{ @SuppressWarnings("unused") private void updateSyncButton() { - /* synchronizeFrame++; - if (synchronizeFrame == 4) - synchronizeFrame = 0; - synchronizeButton.setIcon(synchronizeAnimation.get(synchronizeFrame)); - */ -/* - QPixmap pix = new QPixmap(iconPath+"synchronize.png"); - QMatrix matrix = new QMatrix(); - synchronizeIconAngle = synchronizeIconAngle + 1.0; - if (synchronizeIconAngle >= 365.0) - synchronizeIconAngle = 0.0; - matrix.translate(pix.size().width()/2, pix.size().height()/2); - matrix.rotate( synchronizeIconAngle ); - matrix.translate(-pix.size().width()/2, -pix.size().height()/2); - pix = pix.transformed(matrix, TransformationMode.SmoothTransformation); - synchronizeButton.setIcon(pix); -*/ - - - QPixmap pix = new QPixmap(iconPath+"synchronize.png"); - QPixmap rotatedPix = new QPixmap(pix.size()); - QPainter p = new QPainter(rotatedPix); - - rotatedPix.fill(toolBar.palette().color(ColorRole.Button)); - QSize size = pix.size(); - p.translate(size.width()/2, size.height()/2); - synchronizeIconAngle = synchronizeIconAngle+1.0; - if (synchronizeIconAngle >= 359.0) - synchronizeIconAngle = 0.0; - p.rotate(synchronizeIconAngle); - p.setBackgroundMode(BGMode.OpaqueMode); - p.translate(-size.width()/2, -size.height()/2); - p.drawPixmap(0,0, pix); - p.end(); - synchronizeButton.setIcon(rotatedPix); + + if (syncIcons == null) { + syncIcons = new ArrayList(); + double angle = 0.0; + synchronizeIconAngle = 0; + QPixmap pix = new QPixmap(iconPath+"synchronize.png"); + syncIcons.add(pix); + for (int i=0; i<=360; i++) { + QPixmap rotatedPix = new QPixmap(pix.size()); + QPainter p = new QPainter(rotatedPix); + rotatedPix.fill(toolBar.palette().color(ColorRole.Button)); + QSize size = pix.size(); + p.translate(size.width()/2, size.height()/2); + angle = angle+1.0; + p.rotate(angle); + p.setBackgroundMode(BGMode.OpaqueMode); + p.translate(-size.width()/2, -size.height()/2); + p.drawPixmap(0,0, pix); + p.end(); + syncIcons.add(rotatedPix); + } + } + + synchronizeIconAngle++; + if (synchronizeIconAngle > 359) + synchronizeIconAngle=0; + synchronizeButton.setIcon(syncIcons.get(synchronizeIconAngle)); } // Synchronize with Evernote - @SuppressWarnings("unused") + private void evernoteSync() { logger.log(logger.HIGH, "Entering NeverNote.evernoteSync"); if (!Global.isConnected) remoteConnect(); if (Global.isConnected) - synchronizeAnimationTimer.start(10); + synchronizeAnimationTimer.start(5); // synchronizeAnimationTimer.start(200); syncTimer(); logger.log(logger.HIGH, "Leaving NeverNote.evernoteSync"); @@ -2527,7 +3275,9 @@ public class NeverNote extends QMainWindow{ @SuppressWarnings("unused") private void emptyTrash() { // browserWindow.clear(); + logger.log(logger.EXTREME, "Emptying Trash"); listManager.emptyTrash(); + logger.log(logger.EXTREME, "Resetting view after trash empty"); if (trashTree.selectedItems().size() > 0) { listManager.getSelectedNotebooks().clear(); listManager.getSelectedTags().clear(); @@ -2547,11 +3297,11 @@ public class NeverNote extends QMainWindow{ menuBar.noteRestoreAction.setVisible(false); listManager.loadNotesIndex(); -//--->>> noteIndexUpdated(true); noteIndexUpdated(false); } } // Show/Hide trash window + @SuppressWarnings("unused") private void toggleTrashWindow() { logger.log(logger.HIGH, "Entering NeverNote.toggleTrashWindow"); if (trashTree.isVisible()) @@ -2586,6 +3336,7 @@ public class NeverNote extends QMainWindow{ menuBar.connectAction.setText(tr("Connect")); menuBar.connectAction.setToolTip(tr("Connect to Evernote")); menuBar.synchronizeAction.setEnabled(false); + Global.isConnected = false; synchronizeAnimationTimer.stop(); return; } @@ -2607,56 +3358,67 @@ public class NeverNote extends QMainWindow{ } catch (FileNotFoundException e) { // File not found, so we'll just get empty strings anyway. } + + if (Global.getProxyValue("url").equals("")) { + System.setProperty("http.proxyHost","") ; + System.setProperty("http.proxyPort", "") ; + System.setProperty("https.proxyHost","") ; + System.setProperty("https.proxyPort", "") ; + } else { + // PROXY + System.setProperty("http.proxyHost",Global.getProxyValue("url")) ; + System.setProperty("http.proxyPort", Global.getProxyValue("port")) ; + System.setProperty("https.proxyHost",Global.getProxyValue("url")) ; + System.setProperty("https.proxyPort", Global.getProxyValue("port")) ; + + if (Global.getProxyValue("userid").equals("")) { + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new + PasswordAuthentication(Global.getProxyValue("userid"),Global.getProxyValue("password").toCharArray()); + } + }); + } + } + + syncRunner.userStoreUrl = Global.userStoreUrl; + syncRunner.noteStoreUrl = Global.noteStoreUrl; + syncRunner.noteStoreUrlBase = Global.noteStoreUrlBase; + String userid = aes.getUserid(); String password = aes.getPassword(); if (!userid.equals("") && !password.equals("")) { Global.username = userid; Global.password = password; + syncRunner.username = Global.username; + syncRunner.password = Global.password; + syncRunner.enConnect(); } - // Show the login dialog box - if (!Global.automaticLogin() || userid.equals("")|| password.equals("")) { - LoginDialog login = new LoginDialog(); - login.exec(); + Global.isConnected = syncRunner.isConnected; - if (!login.okPressed()) { - return; - } + if (!Global.isConnected) { + // Show the login dialog box + if (!Global.automaticLogin() || userid.equals("")|| password.equals("")) { + LoginDialog login = new LoginDialog(); + login.exec(); + + if (!login.okPressed()) { + return; + } - Global.username = login.getUserid(); - Global.password = login.getPassword(); + Global.username = login.getUserid(); + Global.password = login.getPassword(); + } + syncRunner.username = Global.username; + syncRunner.password = Global.password; + syncRunner.enConnect(); + Global.isConnected = syncRunner.isConnected; } - syncRunner.username = Global.username; - syncRunner.password = Global.password; - syncRunner.userStoreUrl = Global.userStoreUrl; - syncRunner.noteStoreUrl = Global.noteStoreUrl; - syncRunner.noteStoreUrlBase = Global.noteStoreUrlBase; - if (Global.getProxyValue("url").equals("")) { - System.setProperty("http.proxyHost","") ; - System.setProperty("http.proxyPort", "") ; - System.setProperty("https.proxyHost","") ; - System.setProperty("https.proxyPort", "") ; - } else { - // PROXY - System.setProperty("http.proxyHost",Global.getProxyValue("url")) ; - System.setProperty("http.proxyPort", Global.getProxyValue("port")) ; - System.setProperty("https.proxyHost",Global.getProxyValue("url")) ; - System.setProperty("https.proxyPort", Global.getProxyValue("port")) ; - - if (Global.getProxyValue("userid").equals("")) { - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new - PasswordAuthentication(Global.getProxyValue("userid"),Global.getProxyValue("password").toCharArray()); - }}); - } - } - - - syncRunner.enConnect(); - Global.isConnected = syncRunner.isConnected; + if (!Global.isConnected) + return; setupOnlineMenu(); setupConnectMenuOptions(); logger.log(logger.HIGH, "Leaving NeverNote.remoteConnect"); @@ -2685,10 +3447,10 @@ public class NeverNote extends QMainWindow{ @SuppressWarnings("unused") private void attributeTreeClicked(QTreeWidgetItem item, Integer integer) { - clearTagFilter(); - clearNotebookFilter(); +// clearTagFilter(); +// clearNotebookFilter(); clearTrashFilter(); - clearSavedSearchFilter(); +// clearSavedSearchFilter(); if (attributeTreeSelected == null || item.nativeId() != attributeTreeSelected.nativeId()) { if (item.childCount() > 0) { @@ -2743,6 +3505,7 @@ public class NeverNote extends QMainWindow{ } // Show/Hide attribute search window + @SuppressWarnings("unused") private void toggleAttributesWindow() { logger.log(logger.HIGH, "Entering NeverNote.toggleAttributesWindow"); if (attributeTree.isVisible()) @@ -2796,7 +3559,15 @@ public class NeverNote extends QMainWindow{ @SuppressWarnings("unused") private void noteTableSelection() { logger.log(logger.HIGH, "Entering NeverNote.noteTableSelection"); + saveNote(); + + // If the ctrl key is pressed, then they are selecting multiple + // entries and we don't want to change the currently viewed note. + if (QApplication.keyboardModifiers().isSet(KeyboardModifier.ControlModifier) && + QApplication.mouseButtons().isSet(MouseButton.LeftButton)) + return; + if (historyGuids.size() == 0) { historyGuids.add(currentNoteGuid); historyPosition = 1; @@ -2866,7 +3637,24 @@ public class NeverNote extends QMainWindow{ refreshEvernoteNoteList(); logger.log(logger.HIGH, "Calling note table reload in NeverNote.noteIndexUpdated() - "+reload); noteTableView.load(reload); - scrollToGuid(currentNoteGuid); + if (currentNoteGuid == null || currentNoteGuid.equals("")) { + int pos; + if (noteTableView.proxyModel.sortOrder() == SortOrder.AscendingOrder) + pos = noteTableView.proxyModel.rowCount(); + else + pos = 1; + if (noteTableView.proxyModel.rowCount() == 0) + pos = 0; + if (pos>0) { + QModelIndex i = noteTableView.proxyModel.index(pos-1, Global.noteTableGuidPosition); + if (i!=null) { + currentNoteGuid = (String)i.data(); + } + } + } + if (!noteTableView.isColumnHidden(Global.noteTableGuidPosition)) + showColumns(); + scrollToGuid(currentNoteGuid); logger.log(logger.HIGH, "Leaving NeverNote.noteIndexUpdated"); } // Called when the list of notes is updated @@ -2888,10 +3676,11 @@ public class NeverNote extends QMainWindow{ if (currentNoteGuid == null) currentNoteGuid = new String(); + //determine current note guid for (Note note : listManager.getNoteIndex()) { tempNoteGuid = note.getGuid(); if (currentNoteGuid.equals(tempNoteGuid)) { - saveCurrentNoteGuid = new String(tempNoteGuid); + saveCurrentNoteGuid = tempNoteGuid; } } @@ -2902,14 +3691,12 @@ public class NeverNote extends QMainWindow{ browserWindow.setDisabled(true); } - if (saveCurrentNoteGuid.equals("") && listManager.getNoteIndex().size() >0) { - currentNoteGuid = listManager.getNoteIndex().get(listManager.getNoteIndex().size()-1).getGuid(); - currentNote = listManager.getNoteIndex().get(listManager.getNoteIndex().size()-1); - refreshEvernoteNote(true); - } else { + if (!saveCurrentNoteGuid.equals("")) { refreshEvernoteNote(false); + } else { + currentNoteGuid = ""; } - reloadTagTree(); + reloadTagTree(false); logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNoteList"); } @@ -3050,6 +3837,7 @@ public class NeverNote extends QMainWindow{ } logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor"); } + @SuppressWarnings("unused") private void updateListGuid(String oldGuid, String newGuid) { logger.log(logger.HIGH, "Entering NeverNote.updateListTitle"); @@ -3167,7 +3955,6 @@ public class NeverNote extends QMainWindow{ } logger.log(logger.HIGH, "Leaving NeverNote.updateListDateCreated"); } - @SuppressWarnings("unused") private void updateListDateChanged(String guid, QDateTime date) { logger.log(logger.HIGH, "Entering NeverNote.updateListDateChanged"); @@ -3192,7 +3979,6 @@ public class NeverNote extends QMainWindow{ logger.log(logger.HIGH, "Leaving NeverNote.updateListDateChanged"); } // Redo scroll - @SuppressWarnings("unused") private void scrollToCurrentGuid() { //scrollToGuid(currentNoteGuid); List selections = noteTableView.selectionModel().selectedRows(); @@ -3203,6 +3989,7 @@ public class NeverNote extends QMainWindow{ String guid = (String)index.model().index(row, Global.noteTableGuidPosition).data(); scrollToGuid(guid); } + // Scroll to the current GUID in tthe list. // Scroll to a particular index item private void scrollToGuid(String guid) { if (currentNote == null || guid == null) @@ -3216,7 +4003,6 @@ public class NeverNote extends QMainWindow{ } } } - if (!currentNote.isActive() && !Global.showDeleted) { for (int i=0; i selectedNotebook = notebookTree.selectedItems(); + if (selectedNotebook.size() > 0 && !selectedNotebook.get(0).text(0).equalsIgnoreCase("All Notebooks") && !selectedNotebook.get(0).text(2).equalsIgnoreCase("STACK")) { + QTreeWidgetItem currentSelectedNotebook = selectedNotebook.get(0); + String notebook; + notebook = currentSelectedNotebook.text(2); + conn.getNotebookTable().setSortOrder(notebook, column, order); + } + } - + //*************************************************************** + @SuppressWarnings("unused") + private void evernoteLinkClick(String syncGuid, String locGuid) { + String guid = null; + if (conn.getNoteTable().guidExists(syncGuid)) { + guid = syncGuid; + } else { + // If we didn't find it via the synchronized guid, look under the local guid + // Iwe don't find it there, look to see if the GUID is posted under the local GUID, but was + // later synchronized (that causes the guid to change so we need to find the new one). + if (conn.getNoteTable().guidExists(locGuid)) + guid = locGuid; + else + guid = conn.getNoteTable().findAlternateGuid(locGuid); + } + if (guid != null) { + openExternalEditor(guid); + return; + } + + //If we've gotten this far, we can't find the note + QMessageBox.information(this, tr("Note Not Found"), tr("Sorry, but I can't"+ + " seem to find that note.")); + } //*************************************************************** //*************************************************************** //** External editor window functions //*************************************************************** //*************************************************************** - @SuppressWarnings("unused") private void listDoubleClick() { - saveNote(); - if (externalWindows.containsKey(currentNoteGuid)) { - externalWindows.get(currentNoteGuid).raise(); + saveNote(); + openExternalEditor(currentNoteGuid); + } + private void openExternalEditor(String guid) { + + if (externalWindows.containsKey(guid)) { + externalWindows.get(guid).raise(); return; } - + Note note = conn.getNoteTable().getNote(guid, true, true, false, true, true); // We have a new external editor to create QIcon appIcon = new QIcon(iconPath+"nevernote.png"); ExternalBrowse newBrowser = new ExternalBrowse(conn); newBrowser.setWindowIcon(appIcon); - externalWindows.put(currentNoteGuid, newBrowser); + externalWindows.put(guid, newBrowser); showEditorButtons(newBrowser.getBrowserWindow()); - loadNoteBrowserInformation(newBrowser.getBrowserWindow()); + loadNoteBrowserInformation(newBrowser.getBrowserWindow(), guid, note); setupBrowserWindowListeners(newBrowser.getBrowserWindow(), false); newBrowser.windowClosing.connect(this, "externalWindowClosing(String)"); newBrowser.getBrowserWindow().noteSignal.titleChanged.connect(this, "externalWindowTitleEdited(String, String)"); newBrowser.getBrowserWindow().noteSignal.tagsChanged.connect(this, "externalWindowTagsEdited(String, List)"); newBrowser.contentsChanged.connect(this, "saveNoteExternalBrowser(String, String, Boolean, BrowserWindow)"); + newBrowser.getBrowserWindow().blockApplication.connect(this, "blockApplication(BrowserWindow)"); + newBrowser.getBrowserWindow().unblockApplication.connect(this, "unblockApplication()"); browserWindow.noteSignal.tagsChanged.connect(newBrowser, "updateTags(String, List)"); browserWindow.noteSignal.titleChanged.connect(newBrowser, "updateTitle(String, String)"); @@ -3378,7 +4247,7 @@ public class NeverNote extends QMainWindow{ browserWindow.setTitle(text); } } - @SuppressWarnings("unused") + @SuppressWarnings({ "rawtypes", "unused" }) private void externalWindowTagsEdited(String guid, List values) { StringBuffer line = new StringBuffer(100); for (int i=0; i ix = listManager.getNoteTableModel().itemData(modelIndex); String tableGuid = (String)ix.values().toArray()[0]; if (tableGuid.equals(currentNoteGuid)) { - listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false"); + listManager.getNoteTableModel().proxyModel.setData(i, Global.noteTableSynchronizedPosition, "false"); return; } } } - */ + logger.log(logger.EXTREME, "Leaving NeverNote.setNoteDirty()"); } @SuppressWarnings("unused") @@ -3449,9 +4319,10 @@ public class NeverNote extends QMainWindow{ noteCache.put(guid, unicode.toString()); if (guid.equals(currentNoteGuid)) { noteDirty = true; - browserWindow.getBrowser().setContent(unicode); + browserWindow.setContent(unicode); } if (save) { + thumbnailRunner.addWork("GENERATE "+ guid); saveNote(guid, browser); } @@ -3459,12 +4330,12 @@ public class NeverNote extends QMainWindow{ private void saveNote() { if (noteDirty) { saveNote(currentNoteGuid, browserWindow); + thumbnailRunner.addWork("GENERATE "+ currentNoteGuid); noteDirty = false; - } + } } private void saveNote(String guid, BrowserWindow window) { logger.log(logger.EXTREME, "Inside NeverNote.saveNote()"); - logger.log(logger.EXTREME, "Note is dirty."); waitCursor(true); logger.log(logger.EXTREME, "Saving to cache"); @@ -3492,18 +4363,21 @@ public class NeverNote extends QMainWindow{ // Get a note from Evernote (and put it in the browser) private void refreshEvernoteNote(boolean reload) { logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNote"); + if (Global.disableViewing) { browserWindow.setEnabled(false); return; } inkNote = false; - if (!Global.showDeleted) - browserWindow.setReadOnly(false); + readOnly = false; + if (Global.showDeleted || currentNoteGuid == null || currentNoteGuid.equals("")) + readOnly = true; Global.cryptCounter =0; - if (currentNoteGuid.equals("")) { + if (readOnly) { browserWindow.setReadOnly(true); return; } + if (!reload) return; @@ -3513,15 +4387,15 @@ public class NeverNote extends QMainWindow{ currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true); if (currentNote == null) return; - - loadNoteBrowserInformation(browserWindow); + loadNoteBrowserInformation(browserWindow, currentNoteGuid, currentNote); } - private void loadNoteBrowserInformation(BrowserWindow browser) { - NoteFormatter formatter = new NoteFormatter(logger, conn, tempFiles); - formatter.setNote(currentNote, Global.pdfPreview()); + + private void loadNoteBrowserInformation(BrowserWindow browser, String guid, Note note) { + NoteFormatter formatter = new NoteFormatter(logger, conn, tempFiles); + formatter.setNote(note, Global.pdfPreview()); formatter.setHighlight(listManager.getEnSearch()); QByteArray js; - if (!noteCache.containsKey(currentNoteGuid) || conn.getNoteTable().isThumbnailNeeded(currentNoteGuid)) { + if (!noteCache.containsKey(guid)) { js = new QByteArray(); // We need to prepend the note with or encoded characters are ugly js.append(""); @@ -3530,30 +4404,65 @@ public class NeverNote extends QMainWindow{ js.append(""); js.append(""); js.append(""); - formatter.setNote(currentNote, Global.pdfPreview()); + formatter.setNote(note, Global.pdfPreview()); js.append(formatter.rebuildNoteHTML()); js.append(""); js.replace("", ""); js.replace("", ""); js.replace("", ""); - browser.getBrowser().setContent(js); - noteCache.put(currentNoteGuid, js.toString()); +// if (Global.enableHTMLEntitiesFix) { +// browser.getBrowser().setContent(new QByteArray(StringEscapeUtils.unescapeHtml(js.toString()))); +// } else + browser.setContent(js); + noteCache.put(guid, js.toString()); + + if (formatter.resourceError) + resourceErrorMessage(); + if (formatter.formatError) { + waitCursor(false); + QMessageBox.information(this, tr("Error"), + tr("NixNote had issues formatting this note." + + " To protect your data this note is being marked as read-only.")); + waitCursor(true); + } + readOnly = formatter.readOnly; + inkNote = formatter.inkNote; + if (readOnly) + readOnlyCache.put(guid, true); + if (inkNote) + inkNoteCache.put(guid, true); } else { logger.log(logger.HIGH, "Note content is being pulled from the cache"); - String cachedContent = formatter.modifyCachedTodoTags(noteCache.get(currentNoteGuid)); + String cachedContent = formatter.modifyCachedTodoTags(noteCache.get(guid)); js = new QByteArray(cachedContent); - browser.getBrowser().setContent(js); + browser.setContent(js); + if (readOnlyCache.containsKey(guid)) + readOnly = true; + if (inkNoteCache.containsKey(guid)) + inkNote = true; } - if (conn.getNoteTable().isThumbnailNeeded(currentNoteGuid)) { - thumbnailHTMLReady(currentNoteGuid, js, Global.calculateThumbnailZoom(js.toString())); + if (conn.getNoteTable().isThumbnailNeeded(guid)) { + thumbnailHTMLReady(guid, js, Global.calculateThumbnailZoom(js.toString())); + } + if (readOnly || inkNote) + browser.getBrowser().page().setContentEditable(false); // We don't allow editing of ink notes + else + browser.getBrowser().page().setContentEditable(true); + browser.setReadOnly(readOnly); + deleteButton.setEnabled(!readOnly); + tagButton.setEnabled(!readOnly); + menuBar.noteDelete.setEnabled(!readOnly); + menuBar.noteTags.setEnabled(!readOnly); + browser.setNote(note); + + if (note != null && note.getNotebookGuid() != null && + conn.getNotebookTable().isLinked(note.getNotebookGuid())) { + deleteButton.setEnabled(false); + menuBar.notebookDeleteAction.setEnabled(false); + } else { + deleteButton.setEnabled(true); + menuBar.notebookDeleteAction.setEnabled(true); } - - if (formatter.resourceError) - resourceErrorMessage(); - inkNote = formatter.readOnly; - - browser.getBrowser().page().setContentEditable(!inkNote); // We don't allow editing of ink notes - browser.setNote(currentNote); // Build a list of non-closed notebooks List nbooks = new ArrayList(); @@ -3567,26 +4476,33 @@ public class NeverNote extends QMainWindow{ nbooks.add(listManager.getNotebookIndex().get(i)); } - browser.setNotebookList(nbooks); - browser.setTitle(currentNote.getTitle()); - browser.setTag(getTagNamesForNote(currentNote)); - browser.setAuthor(currentNote.getAttributes().getAuthor()); - - browser.setAltered(currentNote.getUpdated()); - browser.setCreation(currentNote.getCreated()); - if (currentNote.getAttributes().getSubjectDate() > 0) - browser.setSubjectDate(currentNote.getAttributes().getSubjectDate()); + browser.setTitle(note.getTitle()); + browser.setTag(getTagNamesForNote(note)); + browser.setAuthor(note.getAttributes().getAuthor()); + + browser.setAltered(note.getUpdated()); + browser.setCreation(note.getCreated()); + if (note.getAttributes().getSubjectDate() > 0) + browser.setSubjectDate(note.getAttributes().getSubjectDate()); else - browser.setSubjectDate(currentNote.getCreated()); - browser.setUrl(currentNote.getAttributes().getSourceURL()); - browser.setAllTags(listManager.getTagIndex()); - browser.setCurrentTags(currentNote.getTagNames()); + browser.setSubjectDate(note.getCreated()); + browser.setUrl(note.getAttributes().getSourceURL()); + + FilterEditorTags tagFilter = new FilterEditorTags(conn, logger); + List tagList = tagFilter.getValidTags(note); + browser.setAllTags(tagList); + + browser.setCurrentTags(note.getTagNames()); noteDirty = false; - scrollToGuid(currentNoteGuid); + scrollToGuid(guid); browser.loadingData(false); if (thumbnailViewer.isActiveWindow()) thumbnailView(); + + FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger); + browser.setNotebookList(notebookFilter.getValidNotebooks(note, listManager.getNotebookIndex())); + waitCursor(false); logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNote"); } @@ -3655,31 +4571,16 @@ public class NeverNote extends QMainWindow{ @SuppressWarnings("unused") private void fullReindex() { logger.log(logger.HIGH, "Entering NeverNote.fullReindex"); - // If we are deleting non-trash notes - if (currentNote == null) return; - if (currentNote.getDeleted() == 0) { - if (QMessageBox.question(this, tr("Confirmation"), tr("This will cause all notes & attachments to be reindexed, "+ - "but please be aware that depending upon the size of your database updating all these records " + - "can be time consuming and NeverNote will be unresponsive until it is complete. Do you wish to continue?"), - QMessageBox.StandardButton.Yes, - QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) { - return; - } - } - waitCursor(true); - setMessage(tr("Marking notes for reindex.")); - conn.getNoteTable().reindexAllNotes(); - conn.getNoteTable().noteResourceTable.reindexAll(); + indexRunner.addWork("REINDEXALL"); setMessage(tr("Database will be reindexed.")); - waitCursor(false); - logger.log(logger.HIGH, "Leaving NeverNote.fullRefresh"); + logger.log(logger.HIGH, "Leaving NeverNote.fullReindex"); } // Listener when a user wants to reindex a specific note @SuppressWarnings("unused") private void reindexNote() { logger.log(logger.HIGH, "Entering NeverNote.reindexNote"); for (int i=0; i 1) setMessage(tr("Notes will be reindexed.")); @@ -3695,11 +4596,23 @@ public class NeverNote extends QMainWindow{ return; if (currentNoteGuid.equals("")) return; - + String title = null; + if (selectedNoteGUIDs.size() == 1) + title = conn.getNoteTable().getNote(selectedNoteGUIDs.get(0),false,false,false,false,false).getTitle(); + // If we are deleting non-trash notes if (currentNote.isActive()) { if (Global.verifyDelete()) { - if (QMessageBox.question(this, tr("Confirmation"), tr("Delete selected note(s)?"), + String msg; + if (selectedNoteGUIDs.size() > 1) { + msg = new String(tr("Delete ") +selectedNoteGUIDs.size() +" notes?"); + } else { + if (title != null) + msg = new String(tr("Delete note \"") +title +"\"?"); + else + msg = new String(tr("Delete note selected note?")); + } + if (QMessageBox.question(this, tr("Confirmation"), msg, QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) { return; @@ -3713,7 +4626,16 @@ public class NeverNote extends QMainWindow{ } else { // If we are deleting from the trash. if (Global.verifyDelete()) { - if (QMessageBox.question(this, "Confirmation", "Permanently delete selected note(s)?", + String msg; + if (selectedNoteGUIDs.size() > 1) { + msg = new String(tr("Permanently delete ") +selectedNoteGUIDs.size() +" notes?"); + } else { + if (title != null) + msg = new String(tr("Permanently delete note \"") +title +"\"?"); + else + msg = new String(tr("Permanently delete note selected note?")); + } + if (QMessageBox.question(this, "Confirmation", msg, QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No)==StandardButton.No.value()) { return; @@ -3775,7 +4697,7 @@ public class NeverNote extends QMainWindow{ String notebook = null; listManager.getNotebookIndex().get(0).getGuid(); List selectedNotebook = notebookTree.selectedItems(); - if (selectedNotebook.size() > 0 && !selectedNotebook.get(0).text(0).equalsIgnoreCase("All Notebooks")) { + if (selectedNotebook.size() > 0 && !selectedNotebook.get(0).text(0).equalsIgnoreCase("All Notebooks") && !selectedNotebook.get(0).text(2).equalsIgnoreCase("STACK")) { QTreeWidgetItem currentSelectedNotebook = selectedNotebook.get(0); notebook = currentSelectedNotebook.text(2); } else { @@ -3790,7 +4712,8 @@ public class NeverNote extends QMainWindow{ } } if (!match) - goodNotebooks.add(listManager.getNotebookIndex().get(i).deepCopy()); + //goodNotebooks.add(listManager.getNotebookIndex().get(i).deepCopy()); + goodNotebooks.add((Notebook)Global.deepCopy(listManager.getNotebookIndex().get(i))); } // Now we have a list of good notebooks, so we can look for the default found = false; @@ -3813,7 +4736,7 @@ public class NeverNote extends QMainWindow{ newNote.setUpdateSequenceNum(0); newNote.setGuid(randint); newNote.setNotebookGuid(notebook); - newNote.setTitle(""); + newNote.setTitle("Untitled Note"); newNote.setContent(noteString.toString()); newNote.setDeleted(0); newNote.setCreated(System.currentTimeMillis()); @@ -3839,17 +4762,25 @@ public class NeverNote extends QMainWindow{ } conn.getNoteTable().addNote(newNote, true); - listManager.getUnsynchronizedNotes().add(newNote.getGuid()); - listManager.addNote(newNote); + NoteMetadata metadata = new NoteMetadata(); + metadata.setGuid(newNote.getGuid()); + metadata.setDirty(true); + listManager.addNote(newNote, metadata); // noteTableView.insertRow(newNote, true, -1); currentNote = newNote; currentNoteGuid = currentNote.getGuid(); + noteTableView.clearSelection(); refreshEvernoteNote(true); listManager.countNotebookResults(listManager.getNoteIndex()); browserWindow.titleLabel.setFocus(); browserWindow.titleLabel.selectAll(); -// notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter()); +// notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter()); + + // If the window is hidden, then we want to popup this in an external window & + if (!isVisible()) + listDoubleClick(); + waitCursor(false); logger.log(logger.HIGH, "Leaving NeverNote.addNote"); } // Restore a note from the trash; @@ -3877,48 +4808,56 @@ public class NeverNote extends QMainWindow{ browserWindow.getBrowser().page().findText(find.getText(), find.getFlags()); find.setFocus(); } - private void updateNoteTitle(String guid, String title) { + @SuppressWarnings("unused") + private void updateNoteTitle(String guid, String title) { listManager.setNoteSynchronized(guid, false); } // Signal received that note content has changed. Normally we just need the guid to remove // it from the cache. @SuppressWarnings("unused") private void invalidateNoteCache(String guid, String content) { - String v = noteCache.remove(guid); - if (content != null) { - //noteCache.put(guid, content); - } + noteCache.remove(guid); + refreshEvernoteNote(true); } // Signal received that a note guid has changed @SuppressWarnings("unused") private void noteGuidChanged(String oldGuid, String newGuid) { if (noteCache.containsKey(oldGuid)) { - String cache = noteCache.get(oldGuid); - noteCache.put(newGuid, cache); - noteCache.remove(oldGuid); + if (!oldGuid.equals(currentNoteGuid)) { + String cache = noteCache.get(oldGuid); + noteCache.put(newGuid, cache); + noteCache.remove(oldGuid); + } else { + noteCache.remove(oldGuid); + noteCache.put(newGuid, browserWindow.getContent()); + } } + listManager.updateNoteGuid(oldGuid, newGuid, false); if (currentNoteGuid.equals(oldGuid)) { if (currentNote != null) currentNote.setGuid(newGuid); currentNoteGuid = newGuid; } - if (externalWindows.containsKey(oldGuid)) { + + if (externalWindows.containsKey(oldGuid)) { ExternalBrowse b = externalWindows.get(oldGuid); externalWindows.remove(oldGuid); b.getBrowserWindow().getNote().setGuid(newGuid); externalWindows.put(newGuid, b); } + for (int i=0; i resList = conn.getNoteTable().noteResourceTable.getNoteResources(guid, true); - oldNote.setContent(conn.getNoteTable().getNoteContentBinary(guid)); + oldNote.setContent(conn.getNoteTable().getNoteContentNoUTFConversion(guid)); oldNote.setResources(resList); duplicateNote(oldNote); } @@ -3981,11 +4920,37 @@ public class NeverNote extends QMainWindow{ Long l = new Long(currentTime.getTimeInMillis()); String newGuid = new String(Long.toString(l)); - Note newNote = oldNote.deepCopy(); +// Note newNote = oldNote.deepCopy(); + Note newNote = (Note)Global.deepCopy(oldNote); newNote.setUpdateSequenceNum(0); newNote.setGuid(newGuid); newNote.setDeleted(0); newNote.setActive(true); + + /* + List tagNames = new ArrayList(); + List tagGuids = new ArrayList();; + for (int i=0; i resList = oldNote.getResources(); if (resList == null) resList = new ArrayList(); @@ -4002,17 +4967,27 @@ public class NeverNote extends QMainWindow{ resList.get(i).setGuid(newResGuid); resList.get(i).setUpdateSequenceNum(0); resList.get(i).setActive(true); - conn.getNoteTable().noteResourceTable.saveNoteResource(new Resource(resList.get(i).deepCopy()), true); + conn.getNoteTable().noteResourceTable.saveNoteResource( + (Resource)Global.deepCopy(resList.get(i)), true); } newNote.setResources(resList); - listManager.addNote(newNote); + + // Add note to the database conn.getNoteTable().addNote(newNote, true); - listManager.getUnsynchronizedNotes().add(newNote.getGuid()); - noteTableView.insertRow(newNote, true, -1); + NoteMetadata metaData = new NoteMetadata(); + NoteMetadata oldMeta = listManager.getNoteMetadata().get(oldNote.getGuid()); + metaData.copy(oldMeta); + metaData.setGuid(newNote.getGuid()); + listManager.addNote(newNote, metaData); + noteTableView.insertRow(newNote, metaData, true, -1); + currentNoteGuid = newNote.getGuid(); + currentNote = newNote; + refreshEvernoteNote(true); listManager.countNotebookResults(listManager.getNoteIndex()); waitCursor(false); } // View all notes + @SuppressWarnings("unused") private void allNotes() { clearAttributeFilter(); clearNotebookFilter(); @@ -4024,6 +4999,7 @@ public class NeverNote extends QMainWindow{ notebookTree.selectGuid(""); } notebookTreeSelection(); + refreshEvernoteNote(true); } // Merge notes @SuppressWarnings("unused") @@ -4107,7 +5083,7 @@ public class NeverNote extends QMainWindow{ // A resource within a note has had a guid change @SuppressWarnings("unused") private void noteResourceGuidChanged(String noteGuid, String oldGuid, String newGuid) { - if (!oldGuid.equals(newGuid)) + if (oldGuid != null && !oldGuid.equals(newGuid)) Global.resourceMap.put(oldGuid, newGuid); } // View a thumbnail of the note @@ -4136,17 +5112,16 @@ public class NeverNote extends QMainWindow{ i=listManager.getMasterNoteIndex().size(); } } - msg = "An error has happened while saving the note \"" +title+ - "\".\n\nThis is probably due to a document that is too complex for Nevernote to process. "+ + msg = tr("An error has happened while saving the note \"") +title+ + tr("\".\n\nThis is probably due to a document that is too complex for NixNote to process. "+ "As a result, changes to the note may not be saved properly in the database."+ "\n\nA cached copy is being preserved so you can recover any data, but data may" + - "\nbe lost. Please review the note to recover any critical data before restarting."; + "\nbe lost. Please review the note to recover any critical data before restarting."); QMessageBox.information(this, tr("Error Saving Note"), tr(msg)); } } private void thumbnailHTMLReady(String guid, QByteArray html, Integer zoom) { - logger.log(logger.HIGH, "Entering thumnailHTMLReady()"); logger.log(logger.HIGH, "Thumbnail ready for " +guid); // Find an idle preview object @@ -4183,9 +5158,11 @@ public class NeverNote extends QMainWindow{ private void setupOnlineMenu() { if (!Global.isConnected) { menuBar.noteOnlineHistoryAction.setEnabled(false); + menuBar.selectiveSyncAction.setEnabled(false); return; } else { menuBar.noteOnlineHistoryAction.setEnabled(true); + menuBar.selectiveSyncAction.setEnabled(true); } } @SuppressWarnings("unused") @@ -4204,10 +5181,10 @@ public class NeverNote extends QMainWindow{ versions = null; try { if (Global.isPremium()) - versions = syncRunner.noteStore.listNoteVersions(syncRunner.authToken, currentNoteGuid); + versions = syncRunner.localNoteStore.listNoteVersions(syncRunner.authToken, currentNoteGuid); else versions = new ArrayList(); - currentOnlineNote = syncRunner.noteStore.getNote(syncRunner.authToken, currentNoteGuid, true, true, false, false); + currentOnlineNote = syncRunner.localNoteStore.getNote(syncRunner.authToken, currentNoteGuid, true, true, false, false); } catch (EDAMUserException e) { setMessage("EDAMUserException: " +e.getMessage()); return; @@ -4216,7 +5193,7 @@ public class NeverNote extends QMainWindow{ return; } catch (EDAMNotFoundException e) { setMessage(tr("Note not found on server.")); - QMessageBox.information(this, "Error", "This note could not be found on Evernote's servers."); + QMessageBox.information(this, tr("Error"), tr("This note could not be found on Evernote's servers.")); return; } catch (TException e) { setMessage("EDAMTransactionException: " +e.getMessage()); @@ -4262,9 +5239,9 @@ public class NeverNote extends QMainWindow{ try { if (index > -1) { usn = versions.get(index).getUpdateSequenceNum(); - historyNote = syncRunner.noteStore.getNoteVersion(syncRunner.authToken, currentNoteGuid, usn, true, true, true); + historyNote = syncRunner.localNoteStore.getNoteVersion(syncRunner.authToken, currentNoteGuid, usn, true, true, true); } else - historyNote = syncRunner.noteStore.getNote(syncRunner.authToken, currentNoteGuid, true,true,true,true); + historyNote = syncRunner.localNoteStore.getNote(syncRunner.authToken, currentNoteGuid, true,true,true,true); } catch (EDAMUserException e) { setMessage("EDAMUserException: " +e.getMessage()); waitCursor(false); @@ -4312,12 +5289,145 @@ public class NeverNote extends QMainWindow{ n.getResources().get(i).setActive(true); conn.getNoteTable().noteResourceTable.saveNoteResource(n.getResources().get(i), true); } - listManager.addNote(n); + NoteMetadata metadata = new NoteMetadata(); + metadata.setGuid(n.getGuid()); + listManager.addNote(n, metadata); conn.getNoteTable().addNote(n, true); refreshEvernoteNote(true); setMessage(tr("Note has been restored.")); } - + @SuppressWarnings("unused") + private void setupSelectiveSync() { + + // Get a list of valid notebooks + List notebooks = null; + List tags = null; + List linkedNotebooks = null; + try { + notebooks = syncRunner.localNoteStore.listNotebooks(syncRunner.authToken); + tags = syncRunner.localNoteStore.listTags(syncRunner.authToken); + linkedNotebooks = syncRunner.localNoteStore.listLinkedNotebooks(syncRunner.authToken); + } catch (EDAMUserException e) { + setMessage("EDAMUserException: " +e.getMessage()); + return; + } catch (EDAMSystemException e) { + setMessage("EDAMSystemException: " +e.getMessage()); + return; + } catch (TException e) { + setMessage("EDAMTransactionException: " +e.getMessage()); + return; + } catch (EDAMNotFoundException e) { + setMessage("EDAMNotFoundException: " +e.getMessage()); + return; + } + + // Split up notebooks into synchronized & non-synchronized + List ignoredBooks = new ArrayList(); + List dbIgnoredNotebooks = conn.getSyncTable().getIgnoreRecords("NOTEBOOK"); + + for (int i=notebooks.size()-1; i>=0; i--) { + for (int j=0; j ignoredTags = new ArrayList(); + List dbIgnoredTags = conn.getSyncTable().getIgnoreRecords("TAG"); + + for (int i=tags.size()-1; i>=0; i--) { + for (int j=0; j ignoredLinkedNotebooks = new ArrayList(); + List dbIgnoredLinkedNotebooks = conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK"); + for (int i=linkedNotebooks.size()-1; i>=0; i--) { + String notebookGuid = linkedNotebooks.get(i).getGuid(); + for (int j=0; j oldIgnoreNotebooks = conn.getSyncTable().getIgnoreRecords("NOTEBOOK"); + for (int i=0; i newNotebooks = new ArrayList(); + for (int i=ignore.getIgnoredBookList().count()-1; i>=0; i--) { + String text = ignore.getIgnoredBookList().takeItem(i).text(); + for (int j=0; j oldIgnoreTags = conn.getSyncTable().getIgnoreRecords("TAG"); + for (int i=0; i newTags = new ArrayList(); + for (int i=ignore.getIgnoredTagList().count()-1; i>=0; i--) { + String text = ignore.getIgnoredTagList().takeItem(i).text(); + for (int j=0; j oldIgnoreLinkedNotebooks = conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK"); + for (int i=0; i newLinked = new ArrayList(); + for (int i=ignore.getIgnoredLinkedNotebookList().count()-1; i>=0; i--) { + String text = ignore.getIgnoredLinkedNotebookList().takeItem(i).text(); + for (int j=0; j 0) { + thumbnailRunner.interrupt = true; saveNoteIndexWidth(); saveNoteColumnPositions(); if (syncRunner.addWork("SYNC")) { @@ -4391,14 +5504,40 @@ public class NeverNote extends QMainWindow{ if (currentNote == null) { currentNote = conn.getNoteTable().getNote(currentNoteGuid, false, false, false, false, true); } - listManager.setUnsynchronizedNotes(conn.getNoteTable().getUnsynchronizedGUIDs()); - noteIndexUpdated(false); + listManager.refreshNoteMetadata(); + noteIndexUpdated(true); noteTableView.selectionModel().blockSignals(true); scrollToGuid(currentNoteGuid); noteTableView.selectionModel().blockSignals(false); refreshEvernoteNote(false); scrollToGuid(currentNoteGuid); waitCursor(false); + + // Check to see if there were any shared notebook errors + if (syncRunner.error && syncRunner.errorSharedNotebooks.size() > 0) { + String guid = syncRunner.errorSharedNotebooks.get(0); + String notebookGuid = conn.getLinkedNotebookTable().getLocalNotebookGuid(guid); + String localName = listManager.getNotebookNameByGuid(notebookGuid); + SharedNotebookSyncError syncDialog = new SharedNotebookSyncError(localName); + syncDialog.exec(); + if (syncDialog.okPressed()) { + if (syncDialog.doNothing.isChecked()) { + syncRunner.errorSharedNotebooksIgnored.put(guid, guid); + evernoteSync(); + } + if (syncDialog.deleteNotebook.isChecked()) { + conn.getNoteTable().expungeNotesByNotebook(notebookGuid, true, false); + conn.getNotebookTable().expungeNotebook(notebookGuid, false); + conn.getLinkedNotebookTable().expungeNotebook(guid, false); + conn.getLinkedNotebookTable().expungeNotebook(guid, false); + evernoteSync(); + } + refreshLists(); + return; + } + } + + // Finalize the synchronization if (!syncRunner.error) setMessage(tr("Synchronization Complete")); else @@ -4471,66 +5610,20 @@ public class NeverNote extends QMainWindow{ logger.log(logger.EXTREME, "Index timer activated. Sync running="+syncRunning); if (syncRunning) return; - // Look for any unindexed notes. We only refresh occasionally - // and do one at a time to keep overhead down. - if (!indexDisabled && indexRunner.getWorkQueueSize() == 0) { - List notes = conn.getNoteTable().getNextUnindexed(1); - String unindexedNote = null; - if (notes.size() > 0) - unindexedNote = notes.get(0); - if (unindexedNote != null && Global.keepRunning) { - indexNoteContent(unindexedNote); - } - if (notes.size()>0) { - indexTimer.setInterval(100); - return; - } - List unindexedResources = conn.getNoteTable().noteResourceTable.getNextUnindexed(1); - if (unindexedResources.size() > 0 && indexRunner.getWorkQueueSize() == 0) { - String unindexedResource = unindexedResources.get(0); - if (unindexedResource != null && Global.keepRunning) { - indexNoteResource(unindexedResource); - } - } - if (unindexedResources.size() > 0) { - indexTimer.setInterval(100); - return; - } else { - indexTimer.setInterval(indexTime); - } - if (indexRunning) { - setMessage(tr("Index completed.")); - logger.log(logger.LOW, "Indexing has completed."); - indexRunning = false; - indexTimer.setInterval(indexTime); - } - } - logger.log(logger.EXTREME, "Leaving neverNote index timer"); - } - private synchronized void indexNoteContent(String unindexedNote) { - logger.log(logger.EXTREME, "Entering NeverNote.indexNoteContent()"); - logger.log(logger.MEDIUM, "Unindexed Note found: "+unindexedNote); - indexRunner.setIndexType(indexRunner.CONTENT); - indexRunner.addWork("CONTENT "+unindexedNote); - if (!indexRunning) { - setMessage(tr("Indexing notes.")); - logger.log(logger.LOW, "Beginning to index note contents."); - indexRunning = true; + if (!indexDisabled && indexRunner.idle) { + thumbnailRunner.interrupt = true; + indexRunner.addWork("SCAN"); } - logger.log(logger.EXTREME, "Leaving NeverNote.indexNoteContent()"); + logger.log(logger.EXTREME, "Leaving NixNote index timer"); } - private synchronized void indexNoteResource(String unindexedResource) { - logger.log(logger.EXTREME, "Leaving NeverNote.indexNoteResource()"); - indexRunner.addWork(new String("RESOURCE "+unindexedResource)); - if (!indexRunning) { - setMessage(tr("Indexing notes.")); - indexRunning = true; - } - logger.log(logger.EXTREME, "Leaving NeverNote.indexNoteResource()"); + + @SuppressWarnings("unused") + private void indexStarted() { + setMessage(tr("Indexing notes")); } @SuppressWarnings("unused") - private void indexThreadComplete(String guid) { - logger.log(logger.MEDIUM, "Index complete for "+guid); + private void indexComplete() { + setMessage(tr("Index complete")); } @SuppressWarnings("unused") private synchronized void toggleNoteIndexing() { @@ -4553,47 +5646,64 @@ public class NeverNote extends QMainWindow{ alive = listManager.threadCheck(Global.tagCounterThreadId); if (!alive) { tagDeadCount++; - if (tagDeadCount > MAX) - QMessageBox.information(this, tr("A thread his died."), tr("It appears as the tag counter thread has died. I recommend "+ - "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry.")); + if (tagDeadCount > MAX && !disableTagThreadCheck) { + QMessageBox.information(this, tr("A thread has died."), tr("It appears as the tag counter thread has died. I recommend "+ + "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry.")); + disableTagThreadCheck = true; + } } else tagDeadCount=0; alive = listManager.threadCheck(Global.notebookCounterThreadId); if (!alive) { notebookThreadDeadCount++; - QMessageBox.information(this, tr("A thread his died."), tr("It appears as the notebook counter thread has died. I recommend "+ - "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry.")); + if (notebookThreadDeadCount > MAX && !disableNotebookThreadCheck) { + QMessageBox.information(this, tr("A thread has died."), tr("It appears as the notebook counter thread has died. I recommend "+ + "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry.")); + disableNotebookThreadCheck=true; + } } else notebookThreadDeadCount=0; alive = listManager.threadCheck(Global.trashCounterThreadId); if (!alive) { trashDeadCount++; - QMessageBox.information(this, tr("A thread his died."), ("It appears as the trash counter thread has died. I recommend "+ - "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry.")); + if (trashDeadCount > MAX && !disableTrashThreadCheck) { + QMessageBox.information(this, tr("A thread has died."), ("It appears as the trash counter thread has died. I recommend "+ + "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry.")); + disableTrashThreadCheck = true; + } } else trashDeadCount = 0; alive = listManager.threadCheck(Global.saveThreadId); if (!alive) { saveThreadDeadCount++; - QMessageBox.information(this, tr("A thread his died."), tr("It appears as the note saver thread has died. I recommend "+ - "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry.")); + if (saveThreadDeadCount > MAX && !disableSaveThreadCheck) { + QMessageBox.information(this, tr("A thread has died."), tr("It appears as the note saver thread has died. I recommend "+ + "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry.")); + disableSaveThreadCheck = true; + } } else saveThreadDeadCount=0; if (!syncThread.isAlive()) { syncThreadDeadCount++; - QMessageBox.information(this, tr("A thread his died."), tr("It appears as the synchronization thread has died. I recommend "+ - "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry.")); + if (syncThreadDeadCount > MAX && !disableSyncThreadCheck) { + QMessageBox.information(this, tr("A thread has died."), tr("It appears as the synchronization thread has died. I recommend "+ + "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry.")); + disableSyncThreadCheck = true; + } } else syncThreadDeadCount=0; if (!indexThread.isAlive()) { indexThreadDeadCount++; - QMessageBox.information(this, tr("A thread his died."), tr("It appears as the index thread has died. I recommend "+ - "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry.")); + if (indexThreadDeadCount > MAX && !disableIndexThreadCheck) { + QMessageBox.information(this, tr("A thread has died."), tr("It appears as the index thread has died. I recommend "+ + "checking stopping NixNote, saving the logs for later viewing, and restarting. Sorry.")); + disableIndexThreadCheck = true; + } } else indexThreadDeadCount=0; @@ -4601,8 +5711,9 @@ public class NeverNote extends QMainWindow{ } private void thumbnailTimer() { - if (Global.enableThumbnails()) + if (Global.enableThumbnails() && !syncRunning && indexRunner.idle) { thumbnailRunner.addWork("SCAN"); + } } //************************************************** @@ -4614,15 +5725,20 @@ public class NeverNote extends QMainWindow{ fd.setFileMode(FileMode.AnyFile); fd.setConfirmOverwrite(true); fd.setWindowTitle(tr("Backup Database")); - fd.setFilter(tr("NeverNote Export (*.nnex);;All Files (*.*)")); + fd.setFilter(tr("NixNote Export (*.nnex);;All Files (*.*)")); fd.setAcceptMode(AcceptMode.AcceptSave); - fd.setDirectory(System.getProperty("user.home")); + if (saveLastPath == null || saveLastPath.equals("")) + fd.setDirectory(System.getProperty("user.home")); + else + fd.setDirectory(saveLastPath); if (fd.exec() == 0 || fd.selectedFiles().size() == 0) { return; } waitCursor(true); + saveLastPath = fd.selectedFiles().get(0); + saveLastPath = saveLastPath.substring(0,saveLastPath.lastIndexOf("/")); setMessage(tr("Backing up database")); saveNote(); // conn.backupDatabase(Global.getUpdateSequenceNumber(), Global.getSequenceDate()); @@ -4655,15 +5771,21 @@ public class NeverNote extends QMainWindow{ fd.setFileMode(FileMode.ExistingFile); fd.setConfirmOverwrite(true); fd.setWindowTitle(tr("Restore Database")); - fd.setFilter(tr("NeverNote Export (*.nnex);;All Files (*.*)")); + fd.setFilter(tr("NixNote Export (*.nnex);;All Files (*.*)")); fd.setAcceptMode(AcceptMode.AcceptOpen); - fd.setDirectory(System.getProperty("user.home")); + if (saveLastPath == null || saveLastPath.equals("")) + fd.setDirectory(System.getProperty("user.home")); + else + fd.setDirectory(saveLastPath); if (fd.exec() == 0 || fd.selectedFiles().size() == 0) { return; } waitCursor(true); + saveLastPath = fd.selectedFiles().get(0); + saveLastPath = saveLastPath.substring(0,saveLastPath.lastIndexOf("/")); + setMessage(tr("Restoring database")); ImportData noteReader = new ImportData(conn, true); noteReader.importData(fd.selectedFiles().get(0)); @@ -4687,7 +5809,7 @@ public class NeverNote extends QMainWindow{ fd.setFileMode(FileMode.AnyFile); fd.setConfirmOverwrite(true); fd.setWindowTitle(tr("Backup Database")); - fd.setFilter(tr("NeverNote Export (*.nnex);;All Files (*.*)")); + fd.setFilter(tr("NixNote Export (*.nnex);;All Files (*.*)")); fd.setAcceptMode(AcceptMode.AcceptSave); fd.setDirectory(System.getProperty("user.home")); if (fd.exec() == 0 || fd.selectedFiles().size() == 0) { @@ -4720,16 +5842,19 @@ public class NeverNote extends QMainWindow{ fd.setFileMode(FileMode.ExistingFile); fd.setConfirmOverwrite(true); fd.setWindowTitle(tr("Import Notes")); - fd.setFilter(tr("NeverNote Export (*.nnex);;All Files (*.*)")); + fd.setFilter(tr("NixNote Export (*.nnex);;All Files (*.*)")); fd.setAcceptMode(AcceptMode.AcceptOpen); - fd.setDirectory(System.getProperty("user.home")); + if (saveLastPath == null || saveLastPath.equals("")) + fd.setDirectory(System.getProperty("user.home")); + else + fd.setDirectory(saveLastPath); if (fd.exec() == 0 || fd.selectedFiles().size() == 0) { return; } waitCursor(true); - setMessage("Importing Notes"); + setMessage(tr("Importing Notes")); saveNote(); if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals("")) @@ -4737,6 +5862,7 @@ public class NeverNote extends QMainWindow{ ImportData noteReader = new ImportData(conn, false); String fileName = fd.selectedFiles().get(0); +// saveLastPath.substring(0,fileName.lastIndexOf("/")); if (!fileName.endsWith(".nnex")) fileName = fileName +".nnex"; @@ -4760,7 +5886,7 @@ public class NeverNote extends QMainWindow{ setMessage(tr("Notes have been imported.")); waitCursor(false); - setMessage("Import completed."); + setMessage(tr("Import completed.")); waitCursor(false); @@ -4776,6 +5902,83 @@ public class NeverNote extends QMainWindow{ duplicateNote(currentNoteGuid); } + //************************************************** + //* Action from when a user clicks Copy As URL + //************************************************** + @SuppressWarnings("unused") + private void copyAsUrlClicked() { + QClipboard clipboard = QApplication.clipboard(); + QMimeData mime = new QMimeData(); + String url; + mime.setText(currentNoteGuid); + List urls = new ArrayList(); + + // Start building the URL + User user = Global.getUserInformation(); + + // Check that we have everything we need + if ((user.getShardId().equals("") || user.getId() == 0) && !Global.bypassSynchronizationWarning()) { + SynchronizationRequiredWarning warning = new SynchronizationRequiredWarning(this); + warning.exec(); + if (!warning.neverSynchronize()) + return; + else { + Global.setBypassSynchronizationWarning(true); + user.setShardId("s0"); + user.setId(0); + } + } + + + // Start building a list of URLs based upon the selected notes + noteTableView.showColumn(Global.noteTableGuidPosition); + + List selections = noteTableView.selectionModel().selectedRows(); + if (!Global.isColumnVisible("guid")) + noteTableView.hideColumn(Global.noteTableGuidPosition); + + // Check that the note is either synchronized, or in a local notebook + for (int i=0; i ix = noteTableView.proxyModel.itemData(index); + String selectedGuid = (String)ix.values().toArray()[0]; + + Note n = conn.getNoteTable().getNote(selectedGuid, false, false, false, false, false); + if (n.getUpdateSequenceNum() == 0 && !conn.getNotebookTable().isNotebookLocal(n.getNotebookGuid())) { + QMessageBox.critical(this, tr("Please Synchronize") ,tr("Please either synchronize or move any " + + "new notes to a local notebook.")); + return; + } + } + + // Start building the URLs + for (int i=0; i ix = noteTableView.proxyModel.itemData(index); + String selectedGuid = (String)ix.values().toArray()[0]; + mime.setText(selectedGuid); + + String lid; + String gid; + Note selectedNote = conn.getNoteTable().getNote(selectedGuid, false, false, false, false, false); + if (selectedNote.getUpdateSequenceNum() > 0) { + gid = selectedGuid; + lid = selectedGuid; + } else { + gid = "00000000-0000-0000-0000-000000000000"; + lid = selectedGuid; + } + url = new String("evernote://///view/") + new String(user.getId() + "/" +user.getShardId() +"/" + +gid+"/"+lid +"/"); + urls.add(new QUrl(url)); + } + mime.setUrls(urls); + clipboard.setMimeData(mime); + } //************************************************** @@ -4891,10 +6094,12 @@ public class NeverNote extends QMainWindow{ Note newNote = importer.getNote(); newNote.setNotebookGuid(notebook); newNote.setTitle(dir.at(i)); - listManager.addNote(newNote); + NoteMetadata metadata = new NoteMetadata(); + metadata.setDirty(true); + metadata.setGuid(newNote.getGuid()); + listManager.addNote(newNote, metadata); conn.getNoteTable().addNote(newNote, true); - listManager.getUnsynchronizedNotes().add(newNote.getGuid()); - noteTableView.insertRow(newNote, true, -1); + noteTableView.insertRow(newNote, metadata, true, -1); listManager.updateNoteContent(newNote.getGuid(), importer.getNoteContent()); listManager.countNotebookResults(listManager.getNoteIndex()); importedFiles.add(list.get(i).absoluteFilePath()); @@ -4932,10 +6137,12 @@ public class NeverNote extends QMainWindow{ Note newNote = importer.getNote(); newNote.setNotebookGuid(notebook); newNote.setTitle(dir.at(i)); - listManager.addNote(newNote); + NoteMetadata metadata = new NoteMetadata(); + metadata.setDirty(true); + metadata.setGuid(newNote.getGuid()); + listManager.addNote(newNote, metadata); conn.getNoteTable().addNote(newNote, true); - listManager.getUnsynchronizedNotes().add(newNote.getGuid()); - noteTableView.insertRow(newNote, true, -1); + noteTableView.insertRow(newNote, metadata, true, -1); listManager.updateNoteContent(newNote.getGuid(), importer.getNoteContent()); listManager.countNotebookResults(listManager.getNoteIndex()); dir.remove(dir.at(i)); @@ -5063,7 +6270,7 @@ public class NeverNote extends QMainWindow{ String content = browser.getContent().substring(0,position) + newSegment + browser.getContent().substring(endPos); - browser.getBrowser().setContent(new QByteArray(content));; + browser.setContent(new QByteArray(content));; } position = browser.getContent().indexOf("en-tag=\"en-media\" guid=\""+guid+"\" type=", position+1); @@ -5120,4 +6327,39 @@ public class NeverNote extends QMainWindow{ return true; } + //************************************************* + //* View / Hide source HTML for a note + //************************************************* + public void viewSource() { + browserWindow.showSource(menuBar.viewSource.isChecked()); + } + //************************************************* + // Block the program. This is used for things + // like async web calls. + //************************************************* + @SuppressWarnings("unused") + private void blockApplication(BrowserWindow b) { + // Block all signals + waitCursor(true); + blockSignals(true); + + blockTimer = new QTimer(); + blockTimer.setSingleShot(true); + blockTimer.setInterval(15000); + blockTimer.timeout.connect(this, "unblockApplication()"); + blockingWindow = b; + blockTimer.start(); + } + + @SuppressWarnings("unused") + private void unblockApplication() { + waitCursor(false); + if (blockingWindow != null && new GregorianCalendar().getTimeInMillis() > blockingWindow.unblockTime && blockingWindow.unblockTime != -1) { + QMessageBox.critical(null, tr("No Response from CodeCogs") ,tr("Unable to contact CodeCogs for LaTeX formula.")); + blockingWindow.unblockTime = -1; + blockingWindow.awaitingHttpResponse = false; + } + blockingWindow = null; + blockSignals(false); + } }