OSDN Git Service

Added inter-note links. Added index content controls. Altered Android Unicode test...
authorRandy Baumgarte <randy@fbn.cx>
Fri, 20 May 2011 18:33:08 +0000 (14:33 -0400)
committerRandy Baumgarte <randy@Centauri.(none)>
Tue, 28 Jun 2011 13:21:00 +0000 (09:21 -0400)
14 files changed:
src/cx/fbn/nevernote/Global.java
src/cx/fbn/nevernote/NeverNote.java
src/cx/fbn/nevernote/dialog/AccountDialog.java
src/cx/fbn/nevernote/dialog/PublishNotebook.java
src/cx/fbn/nevernote/dialog/SynchronizationRequiredWarning.java [new file with mode: 0644]
src/cx/fbn/nevernote/gui/BrowserWindow.java
src/cx/fbn/nevernote/gui/ExternalBrowserMenuBar.java
src/cx/fbn/nevernote/gui/MainMenuBar.java
src/cx/fbn/nevernote/gui/NotebookTreeWidget.java
src/cx/fbn/nevernote/gui/TableView.java
src/cx/fbn/nevernote/gui/TrashTreeWidget.java
src/cx/fbn/nevernote/signals/NoteSignal.java
src/cx/fbn/nevernote/sql/DatabaseConnection.java
src/cx/fbn/nevernote/sql/NoteTable.java

index b301e4a..0665fab 100644 (file)
@@ -261,6 +261,7 @@ public class Global {
                settings.setValue("created", user.getCreated());\r
                settings.setValue("updated", user.getUpdated());\r
                settings.setValue("deleted", user.getDeleted());\r
+               settings.setValue("shard", user.getShardId());\r
                settings.endGroup();\r
                isPremium();\r
                if (user.getAttributes()!=null)\r
@@ -269,6 +270,38 @@ public class Global {
                        saveUserAccounting(user.getAccounting());\r
 \r
     }\r
+    public static User getUserInformation() {\r
+       User user = new User();\r
+       settings.beginGroup("User");\r
+       user.setId((Integer)settings.value("id", 0));\r
+               String username = (String)settings.value("username", "");\r
+               String email = (String)settings.value("email", "");\r
+               String name = (String)settings.value("name", "");\r
+               String timezone = (String)settings.value("timezone", "");\r
+               Integer privilege = (Integer)settings.value("privilege", "");\r
+\r
+               String date = (String)settings.value("created", "0");\r
+               user.setCreated(new Long(date));\r
+\r
+               date = (String)settings.value("updated", "0");\r
+               user.setUpdated(new Long(date));\r
+               \r
+               date = (String)settings.value("deleted", "0");\r
+               user.setDeleted(new Long(date));\r
+\r
+               String shard = (String)settings.value("shard", "");\r
+       settings.endGroup();\r
+       \r
+       user.setUsername(username);\r
+       user.setEmail(email);\r
+       user.setName(name);\r
+       user.setTimezone(timezone);\r
+       PrivilegeLevel userLevel = PrivilegeLevel.findByValue(privilege);\r
+       user.setPrivilege(userLevel);\r
+       user.setShardId(shard);\r
+       return user;\r
+    }\r
+    \r
     public static void saveUserAttributes(UserAttributes attrib) {\r
        settings.beginGroup("UserAttributes");\r
                settings.setValue("defaultLocationName", attrib.getDefaultLocationName());\r
@@ -1826,6 +1859,31 @@ public class Global {
                settings.endGroup();    \r
     }\r
 \r
+    //*****************************************************************************\r
+    // Control how tag selection behaves (should they be "and" or "or" selections\r
+    //*****************************************************************************\r
+    public static boolean bypassSynchronizationWarning() {\r
+               settings.beginGroup("User");\r
+               try {\r
+                       String value = (String)settings.value("bypassSynchronizationWarning", "false");\r
+                       settings.endGroup();\r
+                       if (value.equals("true"))\r
+                               return true;\r
+                       else\r
+                               return false;\r
+               } catch (java.lang.ClassCastException e) {\r
+                       Boolean value = (Boolean) settings.value("bypassSynchronizationWarning", false);\r
+                       settings.endGroup();\r
+                       return value;\r
+               }\r
+    }\r
+    public static void setBypassSynchronizationWarning(boolean value) {\r
+               settings.beginGroup("User");\r
+               settings.setValue("bypassSynchronizationWarning", value);\r
+               settings.endGroup();    \r
+    }\r
+\r
+    \r
     //***********************\r
     //* Database cache size\r
     //***********************\r
index cf409b4..68db7ea 100644 (file)
@@ -75,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;
@@ -86,12 +87,15 @@ 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;
@@ -153,6 +157,7 @@ import cx.fbn.nevernote.dialog.SavedSearchEdit;
 import cx.fbn.nevernote.dialog.SetIcon;
 import cx.fbn.nevernote.dialog.ShareNotebook;
 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;
@@ -385,7 +390,7 @@ public class NeverNote extends QMainWindow{
                QApplication.setStyle(Global.getStyle());
                if (Global.useStandardPalette())
                        QApplication.setPalette(QApplication.style().standardPalette());
-        setWindowTitle("NeverNote");
+        setWindowTitle(tr("NeverNote"));
 
         mainLeftRightSplitter = new QSplitter();
         setCentralWidget(mainLeftRightSplitter);
@@ -614,6 +619,7 @@ public class NeverNote extends QMainWindow{
                noteTableView.setNoteHistoryAction(menuBar.noteOnlineHistoryAction);
                noteTableView.noteSignal.titleColorChanged.connect(this, "titleColorChanged(Integer)");
                noteTableView.setMergeNotesAction(menuBar.noteMergeAction);
+               noteTableView.setCopyAsUrlAction(menuBar.noteCopyAsUrlAction);
                noteTableView.doubleClicked.connect(this, "listDoubleClick()");
                listManager.trashSignal.countChanged.connect(trashTree, "updateCounts(Integer)");
                
@@ -653,9 +659,9 @@ 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, "closeNeverNote()");
                trayAddNoteAction.triggered.connect(this, "addNote()");
@@ -668,7 +674,7 @@ public class NeverNote extends QMainWindow{
                
                
                trayIcon = new QSystemTrayIcon(this);
-               trayIcon.setToolTip("NeverNote");
+               trayIcon.setToolTip(tr("NeverNote"));
                trayIcon.setContextMenu(trayMenu);
                trayIcon.activated.connect(this, "trayActivated(com.trolltech.qt.gui.QSystemTrayIcon$ActivationReason)");
 
@@ -854,7 +860,7 @@ public class NeverNote extends QMainWindow{
                                QMessageBox.StandardButton.No) == StandardButton.Yes.value()) {
                        ChangeFileEncryption.execute(dbPath, dbName, encryptCipher, null, Global.cipherPassword.toCharArray(), true);
                        Global.setDatabaseUrl(Global.getDatabaseUrl() + ";CIPHER="+encryptCipher);
-                       QMessageBox.information(this, "Encryption Complete", "Encryption is complete");
+                       QMessageBox.information(this, tr("Encryption Complete"), tr("Encryption is complete"));
                }
         } catch (SQLException e) {
                        e.printStackTrace();
@@ -909,7 +915,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()) {
@@ -1152,6 +1158,7 @@ public class NeverNote extends QMainWindow{
        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)");
        }
 
        //**************************************************
@@ -2419,7 +2426,7 @@ public class NeverNote extends QMainWindow{
        private void deleteSavedSearch() {
                logger.log(logger.HIGH, "Entering NeverNote.deleteSavedSearch");
                
-               if (QMessageBox.question(this, "Confirmation", "Delete the selected search?",
+               if (QMessageBox.question(this, tr("Confirmation"), tr("Delete the selected search?"),
                        QMessageBox.StandardButton.Yes, 
                        QMessageBox.StandardButton.No)==StandardButton.No.value()) {
                                                        return;
@@ -2803,7 +2810,7 @@ public class NeverNote extends QMainWindow{
                }
                refreshEvernoteNote(true);
                if (currentNote != null)
-                       loadNoteBrowserInformation(browserWindow);
+                       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.
@@ -2862,74 +2869,74 @@ public class NeverNote extends QMainWindow{
 //     toolBar.addWidget(menuBar);
 //     menuBar.setSizePolicy(Policy.Minimum, Policy.Minimum);
 //     toolBar.addSeparator();
-       prevButton = toolBar.addAction("Previous");
+       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);
@@ -3513,7 +3520,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;
@@ -4094,23 +4109,52 @@ public class NeverNote extends QMainWindow{
     
     
     //***************************************************************
+    @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                    
     //***************************************************************
     //***************************************************************
        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)");
@@ -4272,15 +4316,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) {
+       private void loadNoteBrowserInformation(BrowserWindow browser, String guid, Note note) {
                NoteFormatter   formatter = new NoteFormatter(logger, conn, tempFiles);
-               formatter.setNote(currentNote, Global.pdfPreview());
+               formatter.setNote(note, Global.pdfPreview());
                formatter.setHighlight(listManager.getEnSearch());
                QByteArray js;
-               if (!noteCache.containsKey(currentNoteGuid) || conn.getNoteTable().isThumbnailNeeded(currentNoteGuid)) {
+               if (!noteCache.containsKey(guid) || conn.getNoteTable().isThumbnailNeeded(guid)) {
                        js = new QByteArray();
                        // We need to prepend the note with <HEAD></HEAD> or encoded characters are ugly 
                        js.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");               
@@ -4289,7 +4333,7 @@ public class NeverNote extends QMainWindow{
                        js.append("<style> img { max-width:100%; }</style>");
                        js.append("<style type=\"text/css\">en-spell { text-decoration: none; border-bottom: dotted 1px #cc0000; }</style>");
                        js.append("</head>");
-                       formatter.setNote(currentNote, Global.pdfPreview());
+                       formatter.setNote(note, Global.pdfPreview());
                        js.append(formatter.rebuildNoteHTML());
                        js.append("</HTML>");
                        js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml.dtd'>", "");
@@ -4299,7 +4343,7 @@ public class NeverNote extends QMainWindow{
 //                     browser.getBrowser().setContent(new QByteArray(StringEscapeUtils.unescapeHtml(js.toString())));
 //             } else
                        browser.getBrowser().setContent(js);
-                       noteCache.put(currentNoteGuid, js.toString());
+                       noteCache.put(guid, js.toString());
 
                        if (formatter.resourceError)
                                resourceErrorMessage();
@@ -4313,21 +4357,21 @@ public class NeverNote extends QMainWindow{
                        readOnly = formatter.readOnly;
                        inkNote = formatter.inkNote;
                        if (readOnly)
-                               readOnlyCache.put(currentNoteGuid, true);
+                               readOnlyCache.put(guid, true);
                        if (inkNote)
-                               inkNoteCache.put(currentNoteGuid, true);
+                               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);
-                       if (readOnlyCache.containsKey(currentNoteGuid))
+                       if (readOnlyCache.containsKey(guid))
                                        readOnly = true;
-                       if (inkNoteCache.containsKey(currentNoteGuid))
+                       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
@@ -4338,10 +4382,10 @@ public class NeverNote extends QMainWindow{
                tagButton.setEnabled(!readOnly);
                menuBar.noteDelete.setEnabled(!readOnly);
                menuBar.noteTags.setEnabled(!readOnly);
-               browser.setNote(currentNote);
+               browser.setNote(note);
                
-               if (currentNote != null && currentNote.getNotebookGuid() != null && 
-                               conn.getNotebookTable().isLinked(currentNote.getNotebookGuid())) {
+               if (note != null && note.getNotebookGuid() != null && 
+                               conn.getNotebookTable().isLinked(note.getNotebookGuid())) {
                        deleteButton.setEnabled(false);
                        menuBar.notebookDeleteAction.setEnabled(false);
                } else {
@@ -4361,32 +4405,32 @@ public class NeverNote extends QMainWindow{
                                nbooks.add(listManager.getNotebookIndex().get(i));
                }
                
-               browser.setTitle(currentNote.getTitle());
-               browser.setTag(getTagNamesForNote(currentNote));
-               browser.setAuthor(currentNote.getAttributes().getAuthor());
+               browser.setTitle(note.getTitle());
+               browser.setTag(getTagNamesForNote(note));
+               browser.setAuthor(note.getAttributes().getAuthor());
 
-               browser.setAltered(currentNote.getUpdated());
-               browser.setCreation(currentNote.getCreated());
-               if (currentNote.getAttributes().getSubjectDate() > 0)
-                       browser.setSubjectDate(currentNote.getAttributes().getSubjectDate());
+               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.setSubjectDate(note.getCreated());
+               browser.setUrl(note.getAttributes().getSourceURL());
                
                FilterEditorTags tagFilter = new FilterEditorTags(conn, logger);
-               List<Tag> tagList = tagFilter.getValidTags(currentNote);
+               List<Tag> tagList = tagFilter.getValidTags(note);
                browser.setAllTags(tagList);
                
-               browser.setCurrentTags(currentNote.getTagNames());
+               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(currentNote, listManager.getNotebookIndex()));
+               browser.setNotebookList(notebookFilter.getValidNotebooks(note, listManager.getNotebookIndex()));
 
                waitCursor(false);
                logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNote");
@@ -4699,9 +4743,8 @@ public class NeverNote extends QMainWindow{
     // it from the cache.
     @SuppressWarnings("unused")
        private void invalidateNoteCache(String guid, String content) {
-       String v = noteCache.remove(guid);
-//             if (guid.equals(currentNoteGuid) && !noteDirty)
-                       refreshEvernoteNote(true);
+       noteCache.remove(guid);
+               refreshEvernoteNote(true);
     }
     // Signal received that a note guid has changed
     @SuppressWarnings("unused")
@@ -4993,11 +5036,11 @@ 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 Nevernote 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));
                }
@@ -5074,7 +5117,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());
@@ -5707,7 +5750,7 @@ public class NeverNote extends QMainWindow{
                
                
        waitCursor(true);
-       setMessage("Importing Notes");
+       setMessage(tr("Importing Notes"));
        saveNote();
        
                if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals("")) 
@@ -5739,7 +5782,7 @@ public class NeverNote extends QMainWindow{
        setMessage(tr("Notes have been imported."));
        waitCursor(false);
        
-       setMessage("Import completed.");
+       setMessage(tr("Import completed."));
  
 
        waitCursor(false);
@@ -5755,6 +5798,66 @@ 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<QUrl> urls = new ArrayList<QUrl>();
+               
+               // 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<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
+       if (!Global.isColumnVisible("guid"))
+               noteTableView.hideColumn(Global.noteTableGuidPosition);
+       
+       for (int i=0; i<selections.size(); i++) {
+               QModelIndex index;
+                       int row = selections.get(i).row();
+               index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
+               SortedMap<Integer, Object> 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);
+       }
        
        
        //**************************************************
index b89d8ae..bca5931 100644 (file)
@@ -57,9 +57,9 @@ public class AccountDialog extends QDialog {
                setLayout(grid);\r
                QLabel premium;\r
                if (Global.isPremium())\r
-                       premium = new QLabel("Premium");\r
+                       premium = new QLabel(tr("Premium"));\r
                else\r
-                       premium = new QLabel("Free");\r
+                       premium = new QLabel(tr("Free"));\r
                \r
                String userName = Global.username;\r
                \r
@@ -72,15 +72,15 @@ public class AccountDialog extends QDialog {
                        pct = uploadAmt*100 / uploadLimit;\r
                else\r
                        pct = new Long(0);\r
-               String unit = " Bytes";\r
+               String unit = tr(" Bytes");\r
                \r
                if (uploadAmt > 0) {\r
                        uploadAmt = uploadAmt/1024;\r
-                       unit = " KB";\r
+                       unit = tr(" KB");\r
                }\r
                if (uploadAmt >= 1024) {\r
                        uploadAmt = uploadAmt / 1024;\r
-                       unit = " MB";\r
+                       unit = tr(" MB");\r
                }\r
                if (uploadLimit > 0)\r
                        uploadLimit = uploadLimit/1024/1024;\r
@@ -95,15 +95,15 @@ public class AccountDialog extends QDialog {
                QGroupBox limitGroup = new QGroupBox(tr("Account:"));\r
 \r
                QGridLayout textGrid = new QGridLayout();\r
-               textGrid.addWidget(new QLabel("User Name:"),1,1);\r
+               textGrid.addWidget(new QLabel(tr("User Name:")),1,1);\r
                textGrid.addWidget(new QLabel(userName), 1,2);\r
-               textGrid.addWidget(new QLabel("Account Type:"), 2,1);\r
+               textGrid.addWidget(new QLabel(tr("Account Type:")), 2,1);\r
                textGrid.addWidget(premium, 2, 2);\r
-               textGrid.addWidget(new QLabel("Limit:"), 3,1);\r
+               textGrid.addWidget(new QLabel(tr("Limit:")), 3,1);\r
                textGrid.addWidget(new QLabel(uploadLimit.toString() +" MB"),3,2);\r
-               textGrid.addWidget(new QLabel("Uploaded In This Period:"), 4,1);\r
+               textGrid.addWidget(new QLabel(tr("Uploaded In This Period:")), 4,1);\r
                textGrid.addWidget(new QLabel(uploadAmt.toString()+unit +" ("+pct+"%)"),4,2);\r
-               textGrid.addWidget(new QLabel("Current Cycle Ends:"), 5,1);\r
+               textGrid.addWidget(new QLabel(tr("Current Cycle Ends:")), 5,1);\r
                textGrid.addWidget(new QLabel(endDate.toString()),5,2);\r
                limitGroup.setLayout(textGrid);\r
 \r
index 547fddd..30979f1 100644 (file)
@@ -72,7 +72,7 @@ public class PublishNotebook extends QDialog {
                \r
                QVBoxLayout textEditLayout = new QVBoxLayout();\r
                textEditLayout.addWidget(new QLabel(tr("Notebook: ") +n.getName()));\r
-               textEditLayout.addWidget(new QLabel("Public URL"));\r
+               textEditLayout.addWidget(new QLabel(tr("Public URL")));\r
                textEditLayout.addLayout(urlLayout);\r
                textEditLayout.addWidget(new QLabel(tr("Description")));\r
                description = new QTextEdit();\r
@@ -81,13 +81,13 @@ public class PublishNotebook extends QDialog {
                sortedBy = new QComboBox(this);\r
                sortOrder = new QComboBox(this);\r
                QHBoxLayout orderLayout = new QHBoxLayout();\r
-               orderLayout.addWidget(new QLabel("Sort By"));\r
+               orderLayout.addWidget(new QLabel(tr("Sort By")));\r
                Qt.Alignment right = new Qt.Alignment();\r
                right.set(Qt.AlignmentFlag.AlignRight);\r
                orderLayout.setAlignment(right);\r
                orderLayout.addWidget(sortedBy);\r
                orderLayout.addSpacing(50);\r
-               orderLayout.addWidget(new QLabel("Sort Order"));\r
+               orderLayout.addWidget(new QLabel(tr("Sort Order")));\r
                orderLayout.addWidget(sortOrder);\r
                \r
                sortedBy.addItem(tr("Date Created"), NoteSortOrder.CREATED);\r
diff --git a/src/cx/fbn/nevernote/dialog/SynchronizationRequiredWarning.java b/src/cx/fbn/nevernote/dialog/SynchronizationRequiredWarning.java
new file mode 100644 (file)
index 0000000..21dc95a
--- /dev/null
@@ -0,0 +1,83 @@
+/*\r
+ * This file is part of NeverNote \r
+ * Copyright 2009 Randy Baumgarte\r
+ * \r
+ * This file may be licensed under the terms of of the\r
+ * GNU General Public License Version 2 (the ``GPL'').\r
+ *\r
+ * Software distributed under the License is distributed\r
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either\r
+ * express or implied. See the GPL for the specific language\r
+ * governing rights and limitations.\r
+ *\r
+ * You should have received a copy of the GPL along with this\r
+ * program. If not, go to http://www.gnu.org/licenses/gpl.html\r
+ * or write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+ *\r
+*/\r
+\r
+\r
+\r
+//**********************************************\r
+//**********************************************\r
+//* This dialog will prompt a user to synchronize\r
+//* With Evernote if some information is missing.  \r
+//* This should not need to be called under normal\r
+//* circumstances.\r
+//**********************************************\r
+//**********************************************\r
+package cx.fbn.nevernote.dialog;\r
+\r
+import com.trolltech.qt.gui.QCheckBox;\r
+import com.trolltech.qt.gui.QDialog;\r
+import com.trolltech.qt.gui.QHBoxLayout;\r
+import com.trolltech.qt.gui.QIcon;\r
+import com.trolltech.qt.gui.QLabel;\r
+import com.trolltech.qt.gui.QPushButton;\r
+import com.trolltech.qt.gui.QTextBrowser;\r
+import com.trolltech.qt.gui.QVBoxLayout;\r
+import com.trolltech.qt.gui.QWidget;\r
+\r
+public class SynchronizationRequiredWarning extends QDialog {\r
+       \r
+       private final QCheckBox neverSynchronize;\r
+       private final QPushButton               okButton;\r
+       \r
+       public SynchronizationRequiredWarning(QWidget parent) { \r
+               setWindowTitle(tr("Synchronization Required"));\r
+           String iconPath = new String("classpath:cx/fbn/nevernote/icons/");\r
+           setWindowIcon(new QIcon(new QIcon(iconPath+"synchronize.png")));\r
+               neverSynchronize = new QCheckBox(tr("I never want to synchronize with Evernote so quit bothering me."));\r
+               okButton = new QPushButton(tr("Ok"));\r
+               QTextBrowser warning = new QTextBrowser();\r
+               warning.setText(tr("Please synchronize with Evernote before proceeding.\n\n" +\r
+                               "In order to use this feature you need to synchronize with Evernote.  After synchronizing" +\r
+                               " the necessary information will be saved so you won't need to do it again.  \n\n"\r
+                               +"If you don't wish to use Evernote's then please check the option at the bottom."));\r
+               \r
+               QVBoxLayout mainLayout = new QVBoxLayout();\r
+               mainLayout.addWidget(warning);\r
+               mainLayout.addWidget(neverSynchronize);\r
+               mainLayout.addWidget(neverSynchronize);\r
+               QHBoxLayout okLayout = new QHBoxLayout();\r
+               okButton.clicked.connect(this, "okClicked()");\r
+               okLayout.addWidget(new QLabel(""));\r
+               okLayout.addWidget(okButton);\r
+               okLayout.addWidget(new QLabel(""));\r
+               okLayout.setStretch(0, 10);\r
+               okLayout.setStretch(2, 10);\r
+               \r
+               mainLayout.addLayout(okLayout);\r
+               setLayout(mainLayout);\r
+       }\r
+       \r
+       public boolean neverSynchronize() {\r
+               return neverSynchronize.isChecked();\r
+       }\r
+\r
+       @SuppressWarnings("unused")\r
+       private void okClicked() {\r
+               close();\r
+       }\r
+}\r
index f47dd85..69a0d5b 100644 (file)
@@ -36,6 +36,7 @@ import java.util.GregorianCalendar;
 import java.util.HashMap;\r
 import java.util.List;\r
 import java.util.Locale;\r
+import java.util.StringTokenizer;\r
 \r
 import org.apache.commons.lang.StringUtils;\r
 \r
@@ -162,6 +163,7 @@ public class BrowserWindow extends QWidget {
        private List<Tag> allTags;\r
        private List<String> currentTags;\r
        public NoteSignal noteSignal;\r
+       public Signal2<String,String> evernoteLinkClicked;\r
        private List<Notebook> notebookList;\r
        private Note currentNote;\r
        private String saveNoteTitle;\r
@@ -302,6 +304,7 @@ public class BrowserWindow extends QWidget {
 //             fileWatcher.fileChanged.connect(this, "fileChanged(String)");\r
                noteSignal = new NoteSignal();\r
                titleLabel = new QLineEdit();\r
+               evernoteLinkClicked = new Signal2<String,String>();\r
                titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX);\r
                urlText = new QLineEdit();\r
                authorText = new QLineEdit();\r
@@ -314,7 +317,7 @@ public class BrowserWindow extends QWidget {
                focusLost = new Signal0();\r
 \r
                tagEdit = new TagLineEdit(allTags);\r
-               tagLabel = new QLabel("Tags:");\r
+               tagLabel = new QLabel(tr("Tags:"));\r
                tagEdit.focusLost.connect(this, "modifyTagsTyping()");\r
 \r
                createdCalendarWidget = new QCalendarWidget();\r
@@ -332,7 +335,7 @@ public class BrowserWindow extends QWidget {
                alteredDate.setCalendarPopup(true);\r
                alteredDate.setCalendarWidget(alteredCalendarWidget);\r
                alteredTime = new QTimeEdit();\r
-               alteredLabel = new QLabel("Altered:");\r
+               alteredLabel = new QLabel(tr("Altered:"));\r
                alteredDate.dateChanged.connect(this, "alteredChanged()");\r
                alteredTime.timeChanged.connect(this, "alteredChanged()");\r
 \r
@@ -876,6 +879,18 @@ public class BrowserWindow extends QWidget {
                        editLatex(guid);\r
                        return;\r
                }\r
+               if (url.toString().startsWith("evernote:/view/")) {\r
+                       StringTokenizer tokens = new StringTokenizer(url.toString().replace("evernote:/view/", ""), "/");\r
+                       tokens.nextToken();\r
+                       tokens.nextToken();\r
+                       String sid = tokens.nextToken();\r
+                       String lid = tokens.nextToken();\r
+                       \r
+                       // Emit that we want to switch to a new note\r
+                       evernoteLinkClicked.emit(sid, lid);\r
+\r
+                       return;\r
+               }\r
                if (url.toString().startsWith("nnres://")) {\r
                        logger.log(logger.EXTREME, "URL is NN resource");\r
                        if (url.toString().endsWith("/vnd.evernote.ink")) {\r
@@ -1048,8 +1063,12 @@ public class BrowserWindow extends QWidget {
 \r
                if (mime.hasUrls()) {\r
                        logger.log(logger.EXTREME, "URL paste found");\r
-                       handleUrls(mime);\r
-                       browser.setFocus();\r
+                       if (!mime.text().startsWith("evernote:")) {\r
+                               handleNoteLink(mime);\r
+                       } else {\r
+                               handleUrls(mime);\r
+                               browser.setFocus();\r
+                       }\r
                        return;\r
                }\r
                \r
@@ -1662,7 +1681,7 @@ public class BrowserWindow extends QWidget {
                        }\r
                        plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);\r
                        if (plainText == null) {\r
-                               QMessageBox.warning(this, "Incorrect Password", "The password entered is not correct");\r
+                               QMessageBox.warning(this, tr("Incorrect Password"), tr("The password entered is not correct"));\r
                        }\r
                }\r
                Pair<String,String> passwordPair = new Pair<String,String>();\r
@@ -2113,6 +2132,41 @@ public class BrowserWindow extends QWidget {
                return;\r
        }\r
 \r
+       // Handle pasting of a note-to-note link\r
+       private void handleNoteLink(QMimeData mime) {\r
+               for (int i=0; i<mime.urls().size(); i++) {\r
+                       StringTokenizer tokens = new StringTokenizer(mime.urls().get(i).toString().replace("evernote:///view/", ""), "/");\r
+                       tokens.nextToken();\r
+                       tokens.nextToken();\r
+                       String sid = tokens.nextToken();\r
+                       String lid = tokens.nextToken();\r
+                       \r
+                       if (!sid.equals(currentNote.getGuid()) && !lid.equals(currentNote.getGuid())) {\r
+                               \r
+                               Note note = conn.getNoteTable().getNote(sid, false, false, false, false, false);\r
+                               if (note == null)\r
+                                       note = conn.getNoteTable().getNote(lid, false, false, false, false, false);\r
+               \r
+                               if (note == null)\r
+                                       return;\r
+\r
+                               // If we've gotten this far, we have a bunch of values.  We need to build the link.\r
+                               StringBuffer url = new StringBuffer(100);\r
+                               String script_start = new String(\r
+                                       "document.execCommand('insertHtml', false, '");\r
+                               String script_end = new String("');");\r
+       \r
+                               url.append("<a href=\""+mime.urls().get(i).toString() +"\" style=\"color:#69aa35\">");\r
+                               url.append(note.getTitle());\r
+                               url.append("</a>");\r
+                               if (mime.urls().size() > 1)\r
+                                       url.append("&nbsp;");\r
+                               browser.page().mainFrame().evaluateJavaScript(\r
+                                               script_start + url + script_end);\r
+                       }\r
+               }\r
+       }\r
+       \r
        // Handle URLs that are trying to be pasted\r
        public void handleUrls(QMimeData mime) {\r
                logger.log(logger.EXTREME, "Starting handleUrls");\r
@@ -3216,12 +3270,12 @@ public class BrowserWindow extends QWidget {
 \r
                } catch (FileNotFoundException e) {\r
                        QMessageBox.critical(this, tr("Spell Check Error"), \r
-                                       tr("Dictionary "+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+\r
-                                               ".dic was not found."));\r
+                                       tr("Dictionary ")+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+\r
+                                               tr(".dic was not found."));\r
                } catch (IOException e) {\r
                        QMessageBox.critical(this, tr("Spell Check Error"), \r
-                                       tr("Dictionary "+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+\r
-                                               ".dic is invalid."));\r
+                                       tr("Dictionary ")+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+\r
+                                               tr(".dic is invalid."));\r
                }\r
 \r
        }\r
index 13d330e..933fb63 100644 (file)
@@ -75,12 +75,12 @@ public class ExternalBrowserMenuBar extends QMenuBar {
                \r
                \r
                printAction = new QAction(tr("Print"), this);\r
-               printAction.setToolTip("Print the current note");\r
+               printAction.setToolTip(tr("Print the current note"));\r
                printAction.triggered.connect(parent, "printNote()");\r
                setupShortcut(printAction, "File_Print");\r
                \r
                emailAction = new QAction(tr("Email"), this);\r
-               emailAction.setToolTip("Email the current note");\r
+               emailAction.setToolTip(tr("Email the current note"));\r
                emailAction.triggered.connect(parent, "emailNote()");\r
                setupShortcut(emailAction, "File_Email");\r
                \r
@@ -210,7 +210,7 @@ public class ExternalBrowserMenuBar extends QMenuBar {
                \r
                \r
                spellCheckAction = new QAction(tr("Spell Check"), this);\r
-               spellCheckAction.setToolTip("Check for spelling errors");\r
+               spellCheckAction.setToolTip(tr("Check for spelling errors"));\r
                spellCheckAction.triggered.connect(parent.getBrowserWindow(), "spellCheckClicked()");\r
                setupShortcut(spellCheckAction, "Tools_Spell_Check");\r
                \r
index 93ded16..5eca7f0 100644 (file)
@@ -54,6 +54,7 @@ public class MainMenuBar extends QMenuBar {
        public QAction                  noteMergeAction;                        // Merge notes\r
        public QAction                  noteExportAction;                       // Export notes\r
        public QAction                  noteImportAction;                       // Import notes\r
+       public QAction                  noteCopyAsUrlAction;            // Copy the note as a URL\r
        \r
        public QAction                  editFind;                                       // find text in the current note\r
        public QAction                  editUndo;                                       // Undo last change\r
@@ -152,54 +153,54 @@ public class MainMenuBar extends QMenuBar {
                \r
                \r
                fullReindexAction = new QAction(tr("Reindex Database"), this);\r
-               fullReindexAction.setToolTip("Reindex all notes");\r
+               fullReindexAction.setToolTip(tr("Reindex all notes"));\r
                fullReindexAction.triggered.connect(parent, "fullReindex()");\r
                setupShortcut(fullReindexAction, "Tools_Reindex_Database");\r
                                \r
                printAction = new QAction(tr("Print"), this);\r
-               printAction.setToolTip("Print the current note");\r
+               printAction.setToolTip(tr("Print the current note"));\r
                printAction.triggered.connect(parent, "printNote()");\r
                setupShortcut(printAction, "File_Print");\r
                \r
                emailAction = new QAction(tr("Email"), this);\r
-               emailAction.setToolTip("Email the current note");\r
+               emailAction.setToolTip(tr("Email the current note"));\r
                emailAction.triggered.connect(parent, "emailNote()");\r
                setupShortcut(emailAction, "File_Email");\r
                \r
                backupAction = new QAction(tr("Backup Database"), this);\r
-               backupAction.setToolTip("Backup the current database");\r
+               backupAction.setToolTip(tr("Backup the current database"));\r
                backupAction.triggered.connect(parent, "databaseBackup()");\r
                setupShortcut(backupAction, "File_Backup");\r
 \r
                restoreAction = new QAction(tr("Restore Database"), this);\r
-               restoreAction.setToolTip("Restore the database from a backup");\r
+               restoreAction.setToolTip(tr("Restore the database from a backup"));\r
                restoreAction.triggered.connect(parent, "databaseRestore()");\r
                setupShortcut(restoreAction, "File_Restore");\r
                        \r
                emptyTrashAction = new QAction(tr("Empty Trash"), this);\r
-               emptyTrashAction.setToolTip("Empty the trash folder");\r
+               emptyTrashAction.setToolTip(tr("Empty the trash folder"));\r
                emptyTrashAction.triggered.connect(parent, "emptyTrash()");\r
                setupShortcut(emptyTrashAction, "File_Empty_Trash");\r
                \r
                noteRestoreAction = new QAction(tr("Restore"), this);\r
-               noteRestoreAction.setToolTip("Restore a deleted file from the trash");\r
+               noteRestoreAction.setToolTip(tr("Restore a deleted file from the trash"));\r
                noteRestoreAction.triggered.connect(parent, "restoreNote()");\r
                noteRestoreAction.setVisible(false);\r
                setupShortcut(noteRestoreAction, "File_Note_Restore");\r
                                \r
                settingsAction = new QAction(tr("Preferences"), this);\r
-               settingsAction.setToolTip("Program settings");\r
+               settingsAction.setToolTip(tr("Program settings"));\r
                settingsAction.triggered.connect(parent, "settings()");\r
                setupShortcut(settingsAction, "Edit_Preferences");\r
                \r
                exitAction = new QAction(tr("Exit"), this);\r
-               exitAction.setToolTip("Close the program");\r
+               exitAction.setToolTip(tr("Close the program"));\r
                exitAction.triggered.connect(parent, "closeNeverNote()");\r
                exitAction.setShortcut("Ctrl+Q");\r
                setupShortcut(exitAction, "File_Exit");\r
                \r
                noteAttributes = new QAction(tr("Extended Information"), this);\r
-               noteAttributes.setToolTip("Show/Hide extended note attributes");\r
+               noteAttributes.setToolTip(tr("Show/Hide extended note attributes"));\r
                noteAttributes.triggered.connect(parent, "toggleNoteInformation()");\r
                noteAttributes.setShortcut("F8");\r
                setupShortcut(noteAttributes, "View_Extended_Information");\r
@@ -224,6 +225,11 @@ public class MainMenuBar extends QMenuBar {
                noteExportAction.triggered.connect(parent, "exportNotes()");\r
                setupShortcut(noteExportAction, "File_Note_Export");\r
                \r
+               noteCopyAsUrlAction = new QAction(tr("Copy as URL"), this);\r
+               noteCopyAsUrlAction.setToolTip(tr("Copy as URL"));\r
+               noteCopyAsUrlAction.triggered.connect(parent, "copyAsUrlClicked()");\r
+               setupShortcut(noteCopyAsUrlAction, "Note_Copy_As_Url");\r
+               \r
                noteImportAction = new QAction(tr("Import Notes"), this);\r
                noteImportAction.setToolTip(tr("Import notes"));\r
                noteImportAction.triggered.connect(parent, "importNotes()");\r
@@ -233,7 +239,6 @@ public class MainMenuBar extends QMenuBar {
                noteAdd.setToolTip(tr("Add a new note"));\r
                noteAdd.triggered.connect(parent, "addNote()");\r
                setupShortcut(noteAdd, "File_Note_Add");\r
-               //noteAdd.setShortcut("Ctrl+N");\r
                \r
                noteTags = new QAction(tr("Modify Tags"), this);\r
                noteTags.setToolTip(tr("Change the tags assigned to this note"));\r
@@ -274,6 +279,7 @@ public class MainMenuBar extends QMenuBar {
                editCopy.triggered.connect(parent.browserWindow, "copyClicked()");\r
                setupShortcut(editCopy, "Edit_Copy");\r
                //editCopy.setShortcut("Ctrl+C");\r
+\r
                \r
                editPaste = new QAction(tr("Paste"), this);\r
                editPaste.setToolTip(tr("Paste"));\r
@@ -286,80 +292,80 @@ public class MainMenuBar extends QMenuBar {
                setupShortcut(editPasteWithoutFormat, "Edit_Paste_Without_Formatting");\r
                \r
                hideNoteList = new QAction(tr("Show Note List"), this);\r
-               hideNoteList.setToolTip("Show/Hide Note List");\r
+               hideNoteList.setToolTip(tr("Show/Hide Note List"));\r
                hideNoteList.triggered.connect(parent, "toggleNoteListWindow()");\r
                hideNoteList.setCheckable(true);\r
                hideNoteList.setChecked(true);\r
                setupShortcut(hideNoteList, "View_Show_Note_List");\r
                \r
                hideTags = new QAction(tr("Show Tags"), this);\r
-               hideTags.setToolTip("Show/Hide Tags");\r
+               hideTags.setToolTip(tr("Show/Hide Tags"));\r
                hideTags.triggered.connect(parent, "toggleTagWindow()");\r
                hideTags.setCheckable(true);\r
                hideTags.setChecked(true);\r
                setupShortcut(hideTags, "View_Show_Tags");\r
                        \r
                hideNotebooks = new QAction(tr("Show Notebooks"), this);\r
-               hideNotebooks.setToolTip("Show/Hide Notebooks");\r
+               hideNotebooks.setToolTip(tr("Show/Hide Notebooks"));\r
                hideNotebooks.triggered.connect(parent, "toggleNotebookWindow()");\r
                hideNotebooks.setCheckable(true);\r
                hideNotebooks.setChecked(true);\r
                setupShortcut(hideNotebooks, "View_Show_Notebooks");\r
                \r
                hideZoom = new QAction(tr("Show Zoom"), this);\r
-               hideZoom.setToolTip("Show/Hide Zoom");\r
+               hideZoom.setToolTip(tr("Show/Hide Zoom"));\r
                hideZoom.triggered.connect(parent, "toggleZoomWindow()");\r
                hideZoom.setCheckable(true);\r
                hideZoom.setChecked(true);\r
                setupShortcut(hideZoom, "View_Show_Zoom");\r
                \r
                hideQuota = new QAction(tr("Show Quota Bar"), this);\r
-               hideQuota.setToolTip("Show/Hide Quota");\r
+               hideQuota.setToolTip(tr("Show/Hide Quota"));\r
                hideQuota.triggered.connect(parent, "toggleQuotaWindow()");\r
                hideQuota.setCheckable(true);\r
                hideQuota.setChecked(true);\r
                setupShortcut(hideQuota, "View_Show_Quota");\r
                \r
                hideSearch = new QAction(tr("Show Search Box"), this);\r
-               hideSearch.setToolTip("Show/Hide Search Box");\r
+               hideSearch.setToolTip(tr("Show/Hide Search Box"));\r
                hideSearch.triggered.connect(parent, "toggleSearchWindow()");\r
                hideSearch.setCheckable(true);\r
                hideSearch.setChecked(true);\r
                setupShortcut(hideSearch, "View_Show_Search");\r
 \r
                wideListView = new QAction(tr("Wide List View"), this);\r
-               wideListView.setToolTip("Wide List Viwe");\r
+               wideListView.setToolTip(tr("Wide List View"));\r
                wideListView.setCheckable(true);\r
                wideListView.changed.connect(parent, "wideListView()");\r
                setupShortcut(wideListView, "View_Wide_List");\r
                \r
                narrowListView = new QAction(tr("Narrow List View"), this);\r
-               narrowListView.setToolTip("Narrow List View");\r
+               narrowListView.setToolTip(tr("Narrow List View"));\r
                narrowListView.setCheckable(true);\r
                narrowListView.changed.connect(parent, "narrowListView()");\r
                setupShortcut(narrowListView, "View_Narrow_List");\r
                \r
                thumbnailView = new QAction(tr("Preview"), this);\r
-               thumbnailView.setToolTip("Preview Notes");\r
+               thumbnailView.setToolTip(tr("Preview Notes"));\r
                thumbnailView.triggered.connect(parent, "thumbnailView()");\r
                setupShortcut(thumbnailView, "View_Thumbnail");\r
                \r
                hideSavedSearches = new QAction(tr("Show Saved Searches"), this);\r
-               hideSavedSearches.setToolTip("Show/Hide Saved Searches");\r
+               hideSavedSearches.setToolTip(tr("Show/Hide Saved Searches"));\r
                hideSavedSearches.triggered.connect(parent, "toggleSavedSearchWindow()");\r
                hideSavedSearches.setCheckable(true);\r
                hideSavedSearches.setChecked(true);\r
                setupShortcut(hideSavedSearches, "View_Show_SavedSearches");\r
                \r
                hideAttributes = new QAction(tr("Show Attribute Searches"), this);\r
-               hideAttributes.setToolTip("Show/Hide Attribute Searches");\r
+               hideAttributes.setToolTip(tr("Show/Hide Attribute Searches"));\r
                hideAttributes.triggered.connect(parent, "toggleAttributesWindow()");\r
                hideAttributes.setCheckable(true);\r
                hideAttributes.setChecked(true);\r
                setupShortcut(hideAttributes, "View_Show_Attribute_Searches");\r
 \r
                hideTrash = new QAction(tr("Show Trash"), this);\r
-               hideTrash.setToolTip("Show/Hide Trash Tree");\r
+               hideTrash.setToolTip(tr("Show/Hide Trash Tree"));\r
                hideTrash.triggered.connect(parent, "toggleTrashWindow()");\r
                hideTrash.setCheckable(true);\r
                hideTrash.setChecked(true);\r
@@ -367,7 +373,7 @@ public class MainMenuBar extends QMenuBar {
                \r
 \r
                showEditorBar = new QAction(tr("Show Editor Button Bar"), this);\r
-               showEditorBar.setToolTip("Show/Hide Editor Button Bar");\r
+               showEditorBar.setToolTip(tr("Show/Hide Editor Button Bar"));\r
                showEditorBar.triggered.connect(parent, "toggleEditorButtonBar()");\r
                showEditorBar.setCheckable(true);\r
                showEditorBar.setChecked(true);\r
@@ -375,7 +381,7 @@ public class MainMenuBar extends QMenuBar {
                \r
 \r
                hideLeftSide = new QAction(tr("Hide Left Side Panels"), this);\r
-               hideLeftSide.setToolTip("Hide The Entire Left Side");\r
+               hideLeftSide.setToolTip(tr("Hide The Entire Left Side"));\r
                hideLeftSide.triggered.connect(parent, "toggleLeftSide()");\r
                hideLeftSide.setCheckable(true);\r
                hideLeftSide.setChecked(false);\r
@@ -509,7 +515,6 @@ public class MainMenuBar extends QMenuBar {
                \r
                tagAddAction = new QAction(tr("Add"),this);\r
                tagAddAction.triggered.connect(parent, "addTag()");\r
-               //tagAddAction.setShortcut("Ctrl+Shift+T");\r
                setupShortcut(tagAddAction, "File_Tag_Add");\r
                \r
                tagEditAction = new QAction(tr("Edit"), this);\r
@@ -593,7 +598,7 @@ public class MainMenuBar extends QMenuBar {
                \r
                \r
                disableIndexing = new QAction(tr("Disable Note Indexing"), this);\r
-               disableIndexing.setToolTip("Manually Stop Note Indexing");\r
+               disableIndexing.setToolTip(tr("Manually Stop Note Indexing"));\r
                disableIndexing.triggered.connect(parent, "toggleNoteIndexing()");\r
                disableIndexing.setCheckable(true);\r
                disableIndexing.setChecked(false);\r
@@ -601,17 +606,17 @@ public class MainMenuBar extends QMenuBar {
                \r
                \r
                folderImportAction = new QAction(tr("Automatic Folder Importing"), this);\r
-               folderImportAction.setToolTip("Import Files Automatically");\r
+               folderImportAction.setToolTip(tr("Import Files Automatically"));\r
                folderImportAction.triggered.connect(parent, "folderImport()");\r
                setupShortcut(folderImportAction, "Tools_Folder_Import");\r
                \r
                spellCheckAction = new QAction(tr("Spell Check"), this);\r
-               spellCheckAction.setToolTip("Check for spelling errors");\r
+               spellCheckAction.setToolTip(tr("Check for spelling errors"));\r
                spellCheckAction.triggered.connect(parent.browserWindow, "spellCheckClicked()");\r
                setupShortcut(spellCheckAction, "Tools_Spell_Check");\r
 \r
                encryptDatabaseAction = new QAction(tr("Encrypt Database"), this);\r
-               encryptDatabaseAction.setToolTip("Encrypt the database upon shutdown");\r
+               encryptDatabaseAction.setToolTip(tr("Encrypt the database upon shutdown"));\r
                encryptDatabaseAction.triggered.connect(parent, "doDatabaseEncrypt()");\r
                setupShortcut(encryptDatabaseAction, "Tools_Database_Encrypt");\r
                if (Global.cipherPassword != null && Global.cipherPassword != "") {\r
@@ -620,22 +625,22 @@ public class MainMenuBar extends QMenuBar {
                }\r
                \r
                loggerAction = new QAction(tr("Logs"), this);\r
-               loggerAction.setToolTip("Show the detailed application log");\r
+               loggerAction.setToolTip(tr("Show the detailed application log"));\r
                loggerAction.triggered.connect(parent, "logger()");\r
                setupShortcut(loggerAction, "About_Log");\r
                                \r
                releaseAction = new QAction(tr("Release Notes"), this);\r
-               releaseAction.setToolTip("Release notes");\r
+               releaseAction.setToolTip(tr("Release notes"));\r
                releaseAction.triggered.connect(parent, "releaseNotes()");      \r
                setupShortcut(releaseAction, "About_Release_Notes");\r
                \r
                checkForUpdates = new QAction(tr("Check For Updates"), this);\r
-               checkForUpdates.setToolTip("Check for newer versions");\r
+               checkForUpdates.setToolTip(tr("Check for newer versions"));\r
                checkForUpdates.triggered.connect(parent, "checkForUpdates()"); \r
                setupShortcut(checkForUpdates, "Help_Check_For_Updates");\r
                \r
                aboutAction = new QAction(tr("About"), this);\r
-               aboutAction.setToolTip("About NeverNote");\r
+               aboutAction.setToolTip(tr("About NeverNote"));\r
                aboutAction.triggered.connect(parent, "about()"); \r
                setupShortcut(aboutAction, "About_About");\r
                \r
@@ -720,6 +725,7 @@ public class MainMenuBar extends QMenuBar {
                noteAttributes.setCheckable(true);\r
                noteMenu.addAction(noteAdd);\r
                noteMenu.addAction(noteDelete);\r
+               //noteMenu.addAction(noteCopyAsUrlAction);\r
                noteMenu.addAction(noteReindex);\r
                noteMenu.addSeparator();\r
                noteMenu.addAction(noteTags);\r
index 2e82288..2002719 100644 (file)
@@ -98,7 +98,7 @@ public class NotebookTreeWidget extends QTreeWidget {
                this.db = db;\r
 //             setProperty("hideTree", true);\r
                List<String> labels = new ArrayList<String>();\r
-               labels.add("Notebooks");\r
+               labels.add(tr("Notebooks"));\r
                labels.add("");\r
                setAcceptDrops(true);\r
                setDragEnabled(true);\r
@@ -239,7 +239,7 @@ public class NotebookTreeWidget extends QTreeWidget {
                \r
                child = new NTreeWidgetItem();\r
                child.setIcon(0, allIcon);\r
-               child.setText(0, "All Notebooks");\r
+               child.setText(0, tr("All Notebooks"));\r
                child.setText(2, "");\r
                child.setTextAlignment(1, ra.value());\r
                insertTopLevelItem(0,child);\r
index 71ce21f..fb9eff0 100644 (file)
@@ -67,6 +67,7 @@ public class TableView extends QTableView {
     private QAction    noteTitleColorGray;\r
     private QAction    noteTitleColorCyan;\r
     private QAction    noteTitleColorMagenta;\r
+    private QAction copyAsUrlAction;\r
 \r
 \r
     \r
@@ -323,6 +324,10 @@ public class TableView extends QTableView {
                mergeNotesAction = a;\r
        }\r
        \r
+       public void setCopyAsUrlAction(QAction a) {\r
+               copyAsUrlAction = a;\r
+       }\r
+       \r
        public void setNoteHistoryAction(QAction a) {\r
                noteHistoryAction = a;\r
        }\r
@@ -366,6 +371,8 @@ public class TableView extends QTableView {
                menu.addAction(deleteAction);\r
                menu.addSeparator();\r
                menu.addAction(duplicateAction);\r
+               menu.addAction(copyAsUrlAction);\r
+               menu.addSeparator();\r
                menu.addAction(noteHistoryAction);\r
                menu.addAction(mergeNotesAction);\r
                \r
@@ -537,4 +544,6 @@ public class TableView extends QTableView {
                        \r
                setColumnHidden(Global.noteTableThumbnailPosition, !toggle);\r
        }\r
+\r
+       \r
 }\r
index 7eb81d1..eda60ca 100644 (file)
@@ -83,7 +83,7 @@ public class TrashTreeWidget extends QTreeWidget {
        public void load() {\r
         trashItem = new QTreeWidgetItem();\r
         trashItem.setIcon(0, trashIcon);\r
-        trashItem.setText(0, "Trash");\r
+        trashItem.setText(0, tr("Trash"));\r
         Qt.Alignment ra = new Qt.Alignment(Qt.AlignmentFlag.AlignRight);\r
         trashItem.setTextAlignment(1, ra.value());\r
         List<String> headers = new ArrayList<String>();\r
index 9f14403..90434a9 100644 (file)
@@ -25,6 +25,8 @@ import com.trolltech.qt.QSignalEmitter;
 import com.trolltech.qt.core.QByteArray;\r
 import com.trolltech.qt.core.QDateTime;\r
 \r
+import cx.fbn.nevernote.gui.BrowserWindow;\r
+\r
 \r
 public class NoteSignal extends QSignalEmitter {\r
        public Signal2<String, List<String>>            tagsChanged = new Signal2<String, List<String>>(); \r
@@ -46,6 +48,7 @@ public class NoteSignal extends QSignalEmitter {
        public Signal2<Note, Boolean>           noteDownloaded = new Signal2<Note, Boolean>();\r
        public Signal2<String, String>          noteSaveRunnerError = new Signal2<String, String>();\r
        public Signal3<String,QByteArray,Integer>               thumbnailPageReady = new Signal3<String,QByteArray,Integer>();\r
+       public Signal3<BrowserWindow,String,String>     browserLinkClicked = new Signal3<BrowserWindow,String,String>();\r
 }\r
 \r
 \r
index 0502657..d89ac43 100644 (file)
@@ -222,6 +222,10 @@ public class DatabaseConnection {
                        if (dbTableExists("NoteResources"))
                                executeSql("Drop table NoteResources;");
                }
+               if (!dbTableColumnExists("NOTE", "ORIGINAL_GUID")) {
+                       executeSql("alter table note add column ORIGINAL_GUID VarChar");
+                       executeSql("create index NOTE_ORIGINAL_GUID_INDEX on note (original_guid, guid);");
+               }
 
                
        }
@@ -356,4 +360,19 @@ public class DatabaseConnection {
         else
                return false;
        }
+       
+       //****************************************************************
+       //* Check if a row in a table exists
+       //****************************************************************
+       public boolean dbTableColumnExists(String tableName, String columnName) {
+        NSqlQuery query = new NSqlQuery(getConnection());
+        query.prepare("select TABLE_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME=:name and COLUMN_NAME=:column");
+        query.bindValue(":name", tableName.toUpperCase());
+        query.bindValue(":column", columnName);
+        query.exec();
+        if (query.next())
+               return true;
+        else
+               return false;
+       }
 }
index 5ccfb8f..97c4a8e 100644 (file)
@@ -319,12 +319,31 @@ public class NoteTable {
                // convert the &lt; character to < it will mess up the XML parsing.  So, to get around this\r
                // I am "bit stuffing" the &lt; to &&lt; so StringEscapeUtils doesn't unescape it.  After\r
                // I'm done I convert it back.\r
+               StringBuffer buffer = new StringBuffer(unicode);\r
                if (Global.enableHTMLEntitiesFix && unicode.indexOf("&#") > 0) {\r
                        unicode = query.valueString(16);\r
-                       unicode = unicode.replace("&lt;", "&_lt;");\r
-                       unicode = codec.fromUnicode(StringEscapeUtils.unescapeHtml(unicode)).toString();\r
-                       unicode = unicode.replace("&_lt;", "&lt;");\r
-               }\r
+                       //System.out.println(unicode);\r
+                       //unicode = unicode.replace("&lt;", "&_lt;");\r
+                       //unicode = codec.fromUnicode(StringEscapeUtils.unescapeHtml(unicode)).toString();\r
+                       //unicode = unicode.replace("&_lt;", "&lt;");\r
+                       //System.out.println("************************");\r
+                       int j=1;\r
+                       for (int i=buffer.indexOf("&#"); i != -1 && buffer.indexOf("&#", i)>0; i=buffer.indexOf("&#",i+1)) {\r
+                               j = buffer.indexOf(";",i)+1;\r
+                               if (i<j) {\r
+                                       String entity = buffer.substring(i,j).toString();\r
+                                       int len = entity.length()-1;\r
+                                       String tempEntity = entity.substring(2, len);\r
+                                       try {\r
+                                               Integer.parseInt(tempEntity);\r
+                                               entity = codec.fromUnicode(StringEscapeUtils.unescapeHtml(entity)).toString();\r
+                                               buffer.delete(i, j);\r
+                                               buffer.insert(i, entity);\r
+                                       } catch (Exception e){ }\r
+                                       \r
+                               }\r
+                       } \r
+               } \r
                        \r
                n.setContent(unicode);\r
 //                     n.setContent(query.valueString(16).toString());\r
@@ -675,8 +694,9 @@ public class NoteTable {
         NSqlQuery query = new NSqlQuery(db.getConnection());\r
         NSqlQuery resQuery = new NSqlQuery(db.getResourceConnection());\r
         NSqlQuery wordQuery = new NSqlQuery(db.getIndexConnection());\r
-               query.prepare("Update Note set guid=:newGuid where guid=:oldGuid");\r
+               query.prepare("Update Note set guid=:newGuid, original_guid=:original_guid where guid=:oldGuid");\r
 \r
+               query.bindValue(":original_guid", oldGuid);\r
                query.bindValue(":newGuid", newGuid);\r
                query.bindValue(":oldGuid", oldGuid);\r
 \r
@@ -715,10 +735,15 @@ public class NoteTable {
        // Update a note\r
        public void updateNote(Note n, boolean isNew) {\r
                int titleColor = getNoteTitleColor(n.getGuid());\r
+               String originalGuid = findAlternateGuid(n.getGuid());\r
                expungeNote(n.getGuid(), true, false);\r
                addNote(n, false);\r
                if (titleColor != -1)\r
                        setNoteTitleColor(n.getGuid(), titleColor);\r
+               if (originalGuid != null) {\r
+                       updateNoteGuid(n.getGuid(), originalGuid);\r
+                       updateNoteGuid(originalGuid, n.getGuid());\r
+               }\r
        }\r
        // Does a note exist?\r
        public boolean exists(String guid) {\r
@@ -1375,6 +1400,41 @@ public class NoteTable {
                return 0;       \r
        }\r
 \r
+       //***********************************************************************************\r
+       public String findAlternateGuid(String guid) {\r
+               boolean check;\r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               check = query.prepare("select guid from note where original_guid=:guid");\r
+               query.bindValue(":guid", guid);\r
+               check = query.exec();\r
+               if (!check) \r
+                       logger.log(logger.EXTREME, "Note SQL findAlternateguid query failed: " +query.lastError().toString());\r
+               \r
+               if (query.next()) {\r
+                       return query.valueString(0); \r
+               }\r
+\r
+               return null;    \r
+       }\r
+       \r
+       //* Check if a note guid exists\r
+       public boolean guidExists(String guid) {\r
+               boolean check;\r
+        NSqlQuery query = new NSqlQuery(db.getConnection());\r
+                                       \r
+               check = query.prepare("select guid from note where guid=:guid");\r
+               query.bindValue(":guid", guid);\r
+               check = query.exec();\r
+               if (!check) \r
+                       logger.log(logger.EXTREME, "Note SQL guidExists query failed: " +query.lastError().toString());\r
+               \r
+               if (query.next()) {\r
+                       return true; \r
+               }\r
+\r
+               return false;                   \r
+       }\r
        \r
        // Update a note content's hash.  This happens if a resource is edited outside of NN\r
        public void updateResourceContentHash(String guid, String oldHash, String newHash) {\r