X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=src%2Fcx%2Ffbn%2Fnevernote%2Fgui%2FBrowserWindow.java;h=7510af55252bc462126c9c4af5b844018024e939;hb=c879b569ee06d8d49812b756fdf806f7cc4e213d;hp=3368242df74836cc0b923b7878117bb756f41c27;hpb=8479f389335a5510806321b2ebf61d83e5c7388d;p=neighbornote%2FNeighborNote.git diff --git a/src/cx/fbn/nevernote/gui/BrowserWindow.java b/src/cx/fbn/nevernote/gui/BrowserWindow.java index 3368242..7510af5 100644 --- a/src/cx/fbn/nevernote/gui/BrowserWindow.java +++ b/src/cx/fbn/nevernote/gui/BrowserWindow.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 @@ -36,8 +36,10 @@ import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.StringTokenizer; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.lang3.StringUtils; import com.evernote.edam.limits.Constants; import com.evernote.edam.type.Data; @@ -46,6 +48,7 @@ import com.evernote.edam.type.Notebook; import com.evernote.edam.type.Resource; import com.evernote.edam.type.ResourceAttributes; import com.evernote.edam.type.Tag; +import com.evernote.edam.type.User; import com.swabunga.spell.engine.Configuration; import com.swabunga.spell.engine.SpellDictionary; import com.swabunga.spell.engine.SpellDictionaryHashMap; @@ -55,6 +58,7 @@ import com.swabunga.spell.event.SpellCheckListener; import com.swabunga.spell.event.SpellChecker; import com.swabunga.spell.event.StringWordTokenizer; import com.trolltech.qt.core.QByteArray; +import com.trolltech.qt.core.QCoreApplication; import com.trolltech.qt.core.QDataStream; import com.trolltech.qt.core.QDateTime; import com.trolltech.qt.core.QEvent; @@ -64,7 +68,9 @@ import com.trolltech.qt.core.QFileSystemWatcher; import com.trolltech.qt.core.QIODevice; import com.trolltech.qt.core.QMimeData; import com.trolltech.qt.core.QTextCodec; +import com.trolltech.qt.core.QTimer; import com.trolltech.qt.core.QUrl; +import com.trolltech.qt.core.Qt; import com.trolltech.qt.core.Qt.Key; import com.trolltech.qt.core.Qt.KeyboardModifier; import com.trolltech.qt.core.Qt.KeyboardModifiers; @@ -72,6 +78,7 @@ import com.trolltech.qt.gui.QAction; import com.trolltech.qt.gui.QApplication; import com.trolltech.qt.gui.QCalendarWidget; import com.trolltech.qt.gui.QClipboard; +import com.trolltech.qt.gui.QClipboard.Mode; import com.trolltech.qt.gui.QColor; import com.trolltech.qt.gui.QComboBox; import com.trolltech.qt.gui.QDateEdit; @@ -79,6 +86,7 @@ import com.trolltech.qt.gui.QDesktopServices; import com.trolltech.qt.gui.QFileDialog; import com.trolltech.qt.gui.QFileDialog.AcceptMode; import com.trolltech.qt.gui.QFileDialog.FileMode; +import com.trolltech.qt.gui.QFont; import com.trolltech.qt.gui.QFontDatabase; import com.trolltech.qt.gui.QFormLayout; import com.trolltech.qt.gui.QGridLayout; @@ -92,13 +100,21 @@ import com.trolltech.qt.gui.QLineEdit; import com.trolltech.qt.gui.QListWidgetItem; import com.trolltech.qt.gui.QMatrix; import com.trolltech.qt.gui.QMessageBox; +import com.trolltech.qt.gui.QPalette; +import com.trolltech.qt.gui.QPalette.ColorRole; import com.trolltech.qt.gui.QPushButton; import com.trolltech.qt.gui.QShortcut; +import com.trolltech.qt.gui.QSplitter; +import com.trolltech.qt.gui.QTextEdit; +import com.trolltech.qt.gui.QTextEdit.LineWrapMode; import com.trolltech.qt.gui.QTimeEdit; import com.trolltech.qt.gui.QToolButton; import com.trolltech.qt.gui.QToolButton.ToolButtonPopupMode; import com.trolltech.qt.gui.QVBoxLayout; import com.trolltech.qt.gui.QWidget; +import com.trolltech.qt.network.QNetworkAccessManager; +import com.trolltech.qt.network.QNetworkReply; +import com.trolltech.qt.network.QNetworkReply.NetworkError; import com.trolltech.qt.network.QNetworkRequest; import com.trolltech.qt.webkit.QWebPage; import com.trolltech.qt.webkit.QWebPage.WebAction; @@ -109,17 +125,21 @@ import cx.fbn.nevernote.Global; import cx.fbn.nevernote.dialog.EnCryptDialog; import cx.fbn.nevernote.dialog.EnDecryptDialog; import cx.fbn.nevernote.dialog.GeoDialog; +import cx.fbn.nevernote.dialog.InsertLatexImage; import cx.fbn.nevernote.dialog.InsertLinkDialog; +import cx.fbn.nevernote.dialog.NoteQuickLinkDialog; import cx.fbn.nevernote.dialog.SpellCheck; import cx.fbn.nevernote.dialog.TableDialog; import cx.fbn.nevernote.dialog.TagAssign; import cx.fbn.nevernote.evernote.EnCrypt; +import cx.fbn.nevernote.filters.FilterEditorTags; import cx.fbn.nevernote.signals.NoteResourceSignal; import cx.fbn.nevernote.signals.NoteSignal; import cx.fbn.nevernote.sql.DatabaseConnection; import cx.fbn.nevernote.utilities.ApplicationLogger; import cx.fbn.nevernote.utilities.FileUtils; import cx.fbn.nevernote.utilities.Pair; +import cx.fbn.nevernote.xml.HtmlTagModifier; public class BrowserWindow extends QWidget { @@ -146,17 +166,20 @@ public class BrowserWindow extends QWidget { public final QAction fontSizeAction; private boolean extendedOn; public boolean buttonsVisible; - private final String iconPath = new String("classpath:cx/fbn/nevernote/icons/"); + private final String iconPath; private final ContentView browser; + private final QTextEdit sourceEdit; + private String sourceEditHeader; + Highlighter syntaxHighlighter; private List allTags; private List currentTags; public NoteSignal noteSignal; + public Signal2 evernoteLinkClicked; private List notebookList; private Note currentNote; private String saveNoteTitle; private String saveTagList; private boolean insideList; -// private String selectedText; private final DatabaseConnection conn; private final QCalendarWidget createdCalendarWidget; private final QCalendarWidget alteredCalendarWidget; @@ -222,7 +245,7 @@ public class BrowserWindow extends QWidget { private final ColorMenu fontHilightColorMenu; public final QFileSystemWatcher fileWatcher; public int cursorPosition; - private boolean forceTextPaste = false; + private boolean forceTextPaste; private String selectedFile; private String currentHyperlink; public boolean keepPDFNavigationHidden; @@ -231,8 +254,17 @@ public class BrowserWindow extends QWidget { SpellDictionary userDictionary; SpellChecker spellChecker; SuggestionListener spellListener; - private final HashMap previewPageList; - + private final HashMap previewPageList; + boolean insertHyperlink; + boolean insideTable; + boolean insideEncryption; + public Signal1 blockApplication; + public Signal0 unblockApplication; + public boolean awaitingHttpResponse; + public long unblockTime; + private final QTimer setSourceTimer; + String latexGuid; // This is set if we are editing an existing LaTeX formula. Useful to track guid. + public static class SuggestionListener implements SpellCheckListener { public boolean abortSpellCheck = false; @@ -249,7 +281,8 @@ public class BrowserWindow extends QWidget { errorsFound = true; spellCheckDialog.setWord(event.getInvalidWord()); - List suggestions = event.getSuggestions(); + @SuppressWarnings("unchecked") + List suggestions = event.getSuggestions(); spellCheckDialog.clearSuggestions(); if (!suggestions.isEmpty()) { // spellCheckDialog.setCurrentSuggestion(suggestions.get(0).getWord()); @@ -278,11 +311,17 @@ public class BrowserWindow extends QWidget { public BrowserWindow(DatabaseConnection c) { logger = new ApplicationLogger("browser.log"); logger.log(logger.HIGH, "Setting up browser"); + iconPath = new String("classpath:cx/fbn/nevernote/icons/"); + forceTextPaste = false; + insertHyperlink = true; + insideTable = false; + insideEncryption = false; fileWatcher = new QFileSystemWatcher(); // fileWatcher.fileChanged.connect(this, "fileChanged(String)"); noteSignal = new NoteSignal(); titleLabel = new QLineEdit(); + evernoteLinkClicked = new Signal2(); titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX); urlText = new QLineEdit(); authorText = new QLineEdit(); @@ -295,7 +334,7 @@ public class BrowserWindow extends QWidget { focusLost = new Signal0(); tagEdit = new TagLineEdit(allTags); - tagLabel = new QLabel("Tags:"); + tagLabel = new QLabel(tr("Tags:")); tagEdit.focusLost.connect(this, "modifyTagsTyping()"); createdCalendarWidget = new QCalendarWidget(); @@ -313,7 +352,7 @@ public class BrowserWindow extends QWidget { alteredDate.setCalendarPopup(true); alteredDate.setCalendarWidget(alteredCalendarWidget); alteredTime = new QTimeEdit(); - alteredLabel = new QLabel("Altered:"); + alteredLabel = new QLabel(tr("Altered:")); alteredDate.dateChanged.connect(this, "alteredChanged()"); alteredTime.timeChanged.connect(this, "alteredChanged()"); @@ -362,11 +401,25 @@ public class BrowserWindow extends QWidget { setAcceptDrops(true); browser = new ContentView(this); + browser.page().setLinkDelegationPolicy( QWebPage.LinkDelegationPolicy.DelegateAllLinks); browser.linkClicked.connect(this, "linkClicked(QUrl)"); currentHyperlink = ""; + //Setup the source editor + sourceEdit = new QTextEdit(this); + sourceEdit.setVisible(false); + sourceEdit.setTabChangesFocus(true); + sourceEdit.setLineWrapMode(LineWrapMode.NoWrap); + QFont font = new QFont(); + font.setFamily("Courier"); + font.setFixedPitch(true); + font.setPointSize(10); + sourceEdit.setFont(font); + syntaxHighlighter = new Highlighter(sourceEdit.document()); + sourceEdit.textChanged.connect(this, "sourceEdited()"); + QVBoxLayout v = new QVBoxLayout(); QFormLayout notebookLayout = new QFormLayout(); QGridLayout dateLayout = new QGridLayout(); @@ -532,9 +585,19 @@ public class BrowserWindow extends QWidget { buttonLayout.toggleNumberListVisible.triggered.connect(this, "todoClicked()"); buttonLayout.toggleTodo.triggered.connect(this, "toggleTodoVisible(Boolean)"); + // Setup the source browser); // buttonLayout.addWidget(new QLabel(), 1); - v.addWidget(browser, 1); + QSplitter editSplitter = new QSplitter(this); + editSplitter.addWidget(browser); + editSplitter.setOrientation(Qt.Orientation.Vertical); + editSplitter.addWidget(sourceEdit); + + + +// v.addWidget(browser, 1); +// v.addWidget(sourceEdit); + v.addWidget(editSplitter); setLayout(v); browser.downloadAttachmentRequested.connect(this, @@ -567,6 +630,30 @@ public class BrowserWindow extends QWidget { browser.page().microFocusChanged.connect(this, "microFocusChanged()"); + //Setup colors + + QPalette pal = new QPalette(); + pal.setColor(ColorRole.Text, QColor.black); + titleLabel.setPalette(pal); + authorText.setPalette(pal); + authorLabel.setPalette(pal); + urlLabel.setPalette(pal); + urlText.setPalette(pal); + createdDate.setPalette(pal); + createdTime.setPalette(pal); + alteredDate.setPalette(pal); + alteredTime.setPalette(pal); + subjectDate.setPalette(pal); + subjectTime.setPalette(pal); + tagEdit.setPalette(pal); + notebookBox.setPalette(pal); + + blockApplication = new Signal1(); + unblockApplication = new Signal0(); + + setSourceTimer = new QTimer(); + setSourceTimer.timeout.connect(this, "setSource()"); + logger.log(logger.HIGH, "Browser setup complete"); } @@ -619,7 +706,12 @@ public class BrowserWindow extends QWidget { createdDate.setEnabled(!v); subjectDate.setEnabled(!v); alteredDate.setEnabled(!v); + authorText.setEnabled(!v); + createdTime.setEnabled(!v); + alteredTime.setEnabled(!v); + subjectTime.setEnabled(!v); getBrowser().setEnabled(true); +// getBrowser().setEnabled(!v); } // expose this class to Javascript on the web page @@ -641,7 +733,7 @@ public class BrowserWindow extends QWidget { public void clear() { logger.log(logger.EXTREME, "Entering BrowserWindow.clear()"); setNote(null); - browser.setContent(new QByteArray()); + setContent(new QByteArray()); tagEdit.setText(""); tagEdit.tagCompleter.reset(); urlLabel.setText(tr("Source URL:")); @@ -649,6 +741,11 @@ public class BrowserWindow extends QWidget { logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()"); } + public void setContent(QByteArray data) { + sourceEdit.blockSignals(true); + browser.setContent(data); + setSource(); + } // get/set current note public void setNote(Note n) { currentNote = n; @@ -823,7 +920,27 @@ public class BrowserWindow extends QWidget { @SuppressWarnings("unused") private void linkClicked(QUrl url) { logger.log(logger.EXTREME, "URL Clicked: " +url.toString()); - if (url.toString().substring(0,8).equals("nnres://")) { + if (url.toString().startsWith("latex:")) { + int position = url.toString().lastIndexOf("."); + String guid = url.toString().substring(0,position); + position = guid.lastIndexOf("/"); + guid = guid.substring(position+1); + editLatex(guid); + return; + } + if (url.toString().startsWith("evernote:/view/")) { + StringTokenizer tokens = new StringTokenizer(url.toString().replace("evernote:/view/", ""), "/"); + tokens.nextToken(); + tokens.nextToken(); + String sid = tokens.nextToken(); + String lid = tokens.nextToken(); + + // Emit that we want to switch to a new note + evernoteLinkClicked.emit(sid, lid); + + return; + } + if (url.toString().startsWith("nnres://")) { logger.log(logger.EXTREME, "URL is NN resource"); if (url.toString().endsWith("/vnd.evernote.ink")) { logger.log(logger.EXTREME, "Unable to open ink note"); @@ -982,8 +1099,6 @@ public class BrowserWindow extends QWidget { } QClipboard clipboard = QApplication.clipboard(); QMimeData mime = clipboard.mimeData(); - -// String x = mime.html(); if (mime.hasImage()) { logger.log(logger.EXTREME, "Image paste found"); @@ -995,8 +1110,12 @@ public class BrowserWindow extends QWidget { if (mime.hasUrls()) { logger.log(logger.EXTREME, "URL paste found"); - handleUrls(mime); - browser.setFocus(); + if (mime.text().startsWith("evernote:")) { + handleNoteLink(mime); + } else { + handleUrls(mime); + browser.setFocus(); + } return; } @@ -1022,11 +1141,40 @@ public class BrowserWindow extends QWidget { if (!mime.hasText()) return; String text = mime.text(); - clipboard.setText(text); + clipboard.clear(); + clipboard.setText(text, Mode.Clipboard); browser.page().triggerAction(WebAction.Paste); - QApplication.clipboard().setMimeData(mime); - browser.setFocus(); + // This is done because pasting into an encryption block + // can cause multiple cells (which can't happen). It + // just goes through the table, extracts the data, & + // puts it back as one table cell. + if (insideEncryption) { + String js = new String( "function fixEncryption() { " + +" var selObj = window.getSelection();" + +" var selRange = selObj.getRangeAt(0);" + +" var workingNode = window.getSelection().anchorNode;" + +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { " + +" workingNode = workingNode.parentNode;" + +" } " + +" workingNode.innerHTML = window.jambi.fixEncryptionPaste(workingNode.innerHTML);" + +"} fixEncryption();"); + browser.page().mainFrame().evaluateJavaScript(js); + } + } + + // This basically removes all the table tags and returns just the contents. + // This is called by JavaScript to fix encryption pastes. + public String fixEncryptionPaste(String data) { + data = data.replace("", ""); + data = data.replace("", ""); + data = data.replace("", ""); + data = data.replace("", ""); + data = data.replace("", ""); + data = data.replace("", "
"); + data = data.replace("

", "
"); + + return ""+data+""; } // insert date/time @@ -1200,7 +1348,9 @@ public class BrowserWindow extends QWidget { "document.execCommand('insertHtml', false, '"); String script_end = new String("');"); String todo = new String( - ""); + ""); browser.page().mainFrame().evaluateJavaScript( script_start + todo + script_end); browser.setFocus(); @@ -1248,7 +1398,39 @@ public class BrowserWindow extends QWidget { script_start + buffer.toString() + script_end); } - + + // Insert a Quick hyperlink + public void insertQuickLink() { + logger.log(logger.EXTREME, "Inserting link"); + String text = browser.selectedText(); + if (text.trim().equalsIgnoreCase("")) + return; + + NoteQuickLinkDialog dialog = new NoteQuickLinkDialog(logger, conn, text); + if (dialog.getResults().size() == 0) { + QMessageBox.critical(null, tr("No Matches Found") ,tr("No matching notes found.")); + return; + } + if (dialog.getResults().size() > 1) { + dialog.exec(); + if (!dialog.okPressed) { + logger.log(logger.EXTREME, "Insert link canceled"); + return; + } + } + + User user = Global.getUserInformation(); + String dUrl = new String("evernote:///view/") + new String(user.getId() + "/" +user.getShardId() +"/" + +dialog.getSelectedNote()+"/"+dialog.getSelectedNote() +"/ " +"style=\"color:#69aa35\""); + + String url = ""+text +""; + String script = "document.execCommand('insertHtml', false, '"+url+"');"; + browser.page().mainFrame().evaluateJavaScript(script); + contentChanged(); + } + // Insert a hyperlink public void insertLink() { logger.log(logger.EXTREME, "Inserting link"); @@ -1256,7 +1438,7 @@ public class BrowserWindow extends QWidget { if (text.trim().equalsIgnoreCase("")) return; - InsertLinkDialog dialog = new InsertLinkDialog(); + InsertLinkDialog dialog = new InsertLinkDialog(insertHyperlink); if (currentHyperlink != null && currentHyperlink != "") { dialog.setUrl(currentHyperlink); } @@ -1265,8 +1447,12 @@ public class BrowserWindow extends QWidget { logger.log(logger.EXTREME, "Insert link canceled"); return; } - if (browser.insertLinkAction.text().equalsIgnoreCase("Insert Hyperlink")) { + + // Take care of inserting new links + if (insertHyperlink) { String selectedText = browser.selectedText(); + if (dialog.getUrl().trim().equals("")) + return; logger.log(logger.EXTREME, "Inserting link on text "+selectedText); logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim()); String dUrl = StringUtils.replace(dialog.getUrl().trim(), "'", "\\'"); @@ -1276,24 +1462,205 @@ public class BrowserWindow extends QWidget { String script = "document.execCommand('insertHtml', false, '"+url+"');"; browser.page().mainFrame().evaluateJavaScript(script); return; + } + + // Edit existing links + String js = new String( "function getCursorPos() {" + +"var cursorPos;" + +"if (window.getSelection) {" + +" var selObj = window.getSelection();" + +" var selRange = selObj.getRangeAt(0);" + +" var workingNode = window.getSelection().anchorNode.parentNode;" + +" while(workingNode != null) { " + +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');" + +" workingNode = workingNode.parentNode;" + +" }" + +"}" + +"} getCursorPos();"); + browser.page().mainFrame().evaluateJavaScript(js); + + if (!dialog.getUrl().trim().equals("")) { + contentChanged(); + return; + } + + // Remove URL + js = new String( "function getCursorPos() {" + +"var cursorPos;" + +"if (window.getSelection) {" + +" var selObj = window.getSelection();" + +" var selRange = selObj.getRangeAt(0);" + +" var workingNode = window.getSelection().anchorNode.parentNode;" + +" while(workingNode != null) { " + +" if (workingNode.nodeName.toLowerCase()=='a') { " + +" workingNode.removeAttribute('href');" + +" workingNode.removeAttribute('title');" + +" var text = document.createTextNode(workingNode.innerText);" + +" workingNode.parentNode.insertBefore(text, workingNode);" + +" workingNode.parentNode.removeChild(workingNode);" + +" }" + +" workingNode = workingNode.parentNode;" + +" }" + +"}" + +"} getCursorPos();"); + browser.page().mainFrame().evaluateJavaScript(js); + + contentChanged(); + + + } + + + // Insert a hyperlink + public void insertLatex() { + editLatex(null); + } + public void editLatex(String guid) { + logger.log(logger.EXTREME, "Inserting latex"); + String text = browser.selectedText(); + if (text.trim().equalsIgnoreCase("\n") || text.trim().equalsIgnoreCase("")) { + InsertLatexImage dialog = new InsertLatexImage(); + if (guid != null) { + String formula = conn.getNoteTable().noteResourceTable.getNoteSourceUrl(guid).replace("http://latex.codecogs.com/gif.latex?", ""); + dialog.setFormula(formula); + } + dialog.exec(); + if (!dialog.okPressed()) { + logger.log(logger.EXTREME, "Edit LaTex canceled"); + return; + } + text = dialog.getFormula().trim(); + } + blockApplication.emit(this); + logger.log(logger.EXTREME, "Inserting LaTeX formula:" +text); + latexGuid = guid; + text = StringUtils.replace(text, "'", "\\'"); + String url = "http://latex.codecogs.com/gif.latex?" +text; + logger.log(logger.EXTREME, "Sending request to codecogs --> " + url); + QNetworkAccessManager manager = new QNetworkAccessManager(this); + manager.finished.connect(this, "insertLatexImageReady(QNetworkReply)"); + unblockTime = new GregorianCalendar().getTimeInMillis()+5000; + awaitingHttpResponse = true; + manager.get(new QNetworkRequest(new QUrl(url))); + } + + public void insertLatexImageReady(QNetworkReply reply) { + logger.log(logger.EXTREME, "Response received from CodeCogs"); + if (reply.error() != NetworkError.NoError) + return; + + unblockTime = -1; + if (!awaitingHttpResponse) + return; + + awaitingHttpResponse = false; + QUrl replyUrl = reply.url(); + QByteArray image = reply.readAll(); + reply.close(); + logger.log(logger.EXTREME, "New image size: " +image.size()); + + Resource newRes = null; + QFile tfile; + String path; + if (latexGuid == null) { + logger.log(logger.EXTREME, "Creating temporary gif"); + path = Global.getFileManager().getResDirPath("latex-temp.gif"); + tfile = new QFile(path); + tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly)); + logger.log(logger.EXTREME, "File Open: " +tfile.errorString()); + tfile.write(image); + logger.log(logger.EXTREME, "Bytes writtes: "+tfile.size()); + tfile.close(); + logger.log(logger.EXTREME, "Creating resource"); + int sequence = 0; + if (currentNote.getResources() != null || currentNote.getResources().size() > 0) + sequence = currentNote.getResources().size(); + newRes = createResource(path,sequence ,"image/gif", false); + QImage pix = new QImage(); + pix.loadFromData(image); + newRes.setHeight(new Integer(pix.height()).shortValue()); + newRes.setWidth(new Integer(pix.width()).shortValue()); + logger.log(logger.EXTREME, "Renaming temporary file to " +newRes.getGuid()+".gif"); + path = Global.getFileManager().getResDirPath(newRes.getGuid()+".gif"); + tfile.rename(path); } else { - String js = new String( "function getCursorPos() {" - +"var cursorPos;" - +"if (window.getSelection) {" - +" var selObj = window.getSelection();" - +" var selRange = selObj.getRangeAt(0);" - +" var workingNode = window.getSelection().anchorNode.parentNode;" - +" while(workingNode != null) { " - +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');" - +" workingNode = workingNode.parentNode;" - +" }" - +"}" - +"} getCursorPos();"); - browser.page().mainFrame().evaluateJavaScript(js); - contentChanged(); + newRes = conn.getNoteTable().noteResourceTable.getNoteResource(latexGuid, false); + path = Global.getFileManager().getResDirPath(newRes.getGuid()+".gif"); + tfile = new QFile(path); + tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly)); + tfile.write(image); + tfile.close(); + newRes.getData().setBody(image.toByteArray()); + // Calculate the new hash value + MessageDigest md; + + logger.log(logger.EXTREME, "Generating MD5"); + try { + md = MessageDigest.getInstance("MD5"); + md.update(image.toByteArray()); + byte[] hash = md.digest(); + newRes.getData().setBodyHash(hash); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + QImage pix = new QImage(); + pix.loadFromData(image); + newRes.setHeight(new Integer(pix.height()).shortValue()); + newRes.setWidth(new Integer(pix.width()).shortValue()); + conn.getNoteTable().noteResourceTable.updateNoteResource(newRes, true); + } + + logger.log(logger.EXTREME, "Setting source: " +replyUrl.toString()); + newRes.getAttributes().setSourceURL(replyUrl.toString()); + conn.getNoteTable().noteResourceTable.updateNoteSourceUrl(newRes.getGuid(), replyUrl.toString(), true); + + for(int i=0; i"); + + String script_start = new String("document.execCommand('insertHTML', false, '"); + String script_end = new String("');"); + browser.page().mainFrame().evaluateJavaScript( + script_start + buffer + script_end); + } else { + HtmlTagModifier modifier = new HtmlTagModifier(getContent()); + modifier.modifyLatexTagHash(newRes); + String newContent = modifier.getHtml(); + setContent(new QByteArray(newContent)); + } + + logger.log(logger.EXTREME, "New HTML set\n" +browser.page().currentFrame().toHtml()); + QWebSettings.setMaximumPagesInCache(0); + QWebSettings.setObjectCacheCapacities(0, 0, 0); + + browser.page().mainFrame().setHtml(browser.page().mainFrame().toHtml()); + browser.reload(); + contentChanged(); +// resourceSignal.contentChanged.emit(path); + unblockTime = -1; + unblockApplication.emit(); + return; } + + // Insert a table public void insertTable() { @@ -1332,6 +1699,7 @@ public class BrowserWindow extends QWidget { private void selectionChanged() { browser.encryptAction.setEnabled(true); browser.insertLinkAction.setEnabled(true); + browser.insertQuickLinkAction.setEnabled(true); String scriptStart = "var selection_text = (window.getSelection()).toString();" + "var range = (window.getSelection()).getRangeAt(0);" + "var parent_html = range.commonAncestorContainer.innerHTML;" @@ -1361,6 +1729,7 @@ public class BrowserWindow extends QWidget { browser.encryptAction.setEnabled(enabled); browser.insertLinkAction.setEnabled(enabled); + browser.insertQuickLinkAction.setEnabled(enabled); // selectedText = text; } @@ -1377,7 +1746,6 @@ public class BrowserWindow extends QWidget { plainText = crypt.decrypt(text, Global.passwordRemember.get(i).getFirst(), 64); if (plainText != null) { slot = new String(Long.toString(l)); - Pair passwordPair = new Pair(); Global.passwordSafe.put(slot, Global.passwordRemember.get(i)); removeEncryption(id, plainText, false, slot); return; @@ -1394,7 +1762,7 @@ public class BrowserWindow extends QWidget { } plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64); if (plainText == null) { - QMessageBox.warning(this, "Incorrect Password", "The password entered is not correct"); + QMessageBox.warning(this, tr("Incorrect Password"), tr("The password entered is not correct")); } } Pair passwordPair = new Pair(); @@ -1420,7 +1788,7 @@ public class BrowserWindow extends QWidget { // Modify a note's tags @SuppressWarnings("unused") private void modifyTags() { - TagAssign tagWindow = new TagAssign(allTags, currentTags); + TagAssign tagWindow = new TagAssign(allTags, currentTags, !conn.getNotebookTable().isLinked(currentNote.getNotebookGuid())); tagWindow.exec(); if (tagWindow.okClicked()) { currentTags.clear(); @@ -1496,6 +1864,20 @@ public class BrowserWindow extends QWidget { if (!newTagArray[i].trim().equals("")) newTagList.add(newTagArray[i]); + if (conn.getNotebookTable().isLinked(currentNote.getNotebookGuid())) { + for (int i=newTagList.size()-1; i>=0; i--) { + boolean found = false; + for (int j=0; j()); + FilterEditorTags t = new FilterEditorTags(conn, logger); + setAllTags(t.getValidTags(currentNote)); + } currentNote.setNotebookGuid(notebookList.get(i).getGuid()); changed = true; } @@ -1648,28 +2142,30 @@ public class BrowserWindow extends QWidget { // Check the note title private void checkNoteTitle() { String text = browser.page().currentFrame().toPlainText(); + if (saveNoteTitle == null) + saveNoteTitle = new String(); + text = text.trim(); + int newLine = text.indexOf("\n"); + if (newLine > 0) + text = text.substring(0,newLine); if (saveNoteTitle.trim().equals("") || saveNoteTitle.trim().equals("Untitled Note")) { - int newLine = text.indexOf("\n"); - if (newLine > 0) { - text = text.substring(0, newLine); - if (text.trim().equals("")) - text = tr("Untitled Note"); + if (text.trim().equals("")) + text = tr("Untitled Note"); titleLabel.setText(text); - } else { - if (text.length() > Constants.EDAM_NOTE_TITLE_LEN_MAX) - titleLabel.setText(text.substring(0, Constants.EDAM_NOTE_TITLE_LEN_MAX)); - else { - titleLabel.blockSignals(true); - if (text.trim().equals("")) - titleLabel.setText(tr("Untitled Note")); - else - titleLabel.setText(text); - titleLabel.blockSignals(false); - } + } else { + if (text.length() > Constants.EDAM_NOTE_TITLE_LEN_MAX) + titleLabel.setText(text.substring(0, Constants.EDAM_NOTE_TITLE_LEN_MAX)); + else { + titleLabel.blockSignals(true); + if (text.trim().equals("")) + titleLabel.setText(tr("Untitled Note")); + else + titleLabel.setText(text); + titleLabel.blockSignals(false); } - noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel - .text()); } + if (currentNote != null && titleLabel != null) + noteSignal.titleChanged.emit(currentNote.getGuid(), text); } // Return the note contents so we can email them @@ -1724,7 +2220,6 @@ public class BrowserWindow extends QWidget { buffer.append("\" en-tag=en-media type=\"image/jpeg\"" +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\"" +" guid=\"" +newRes.getGuid() +"\"" -// +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\"" +" onContextMenu=\"window.jambi.imageContextMenu(&." +tfile.fileName() +"&.);\"" + " />"); @@ -1734,6 +2229,41 @@ public class BrowserWindow extends QWidget { return; } + // Handle pasting of a note-to-note link + private void handleNoteLink(QMimeData mime) { + for (int i=0; i"); + url.append(note.getTitle()); + url.append(""); + if (mime.urls().size() > 1) + url.append(" "); + browser.page().mainFrame().evaluateJavaScript( + script_start + url + script_end); + } + } + } + // Handle URLs that are trying to be pasted public void handleUrls(QMimeData mime) { logger.log(logger.EXTREME, "Starting handleUrls"); @@ -1761,10 +2291,9 @@ public class BrowserWindow extends QWidget { handleLocalImageURLPaste(mime, mimeType); return; } - String[] type = mimeType.split("/"); - boolean valid = validAttachment(type[1]); + boolean smallEnough = checkFileAttachmentSize(url); - if (smallEnough && valid + if (smallEnough && url.substring(0, 5).equalsIgnoreCase("file:") && !mimeType.substring(0, 5).equalsIgnoreCase("image")) { handleLocalAttachment(mime, mimeType); @@ -1875,13 +2404,14 @@ public class BrowserWindow extends QWidget { imageURL = file.fileName() + ".png"; } } - + logger.log(logger.EXTREME, "Generating link tags"); buffer.delete(0, buffer.length()); buffer.append(""); + .append("');\" "); + buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >"); buffer.append(""); buffer.append(""); @@ -1893,19 +2423,33 @@ public class BrowserWindow extends QWidget { private Resource createResource(String url, int sequence, String mime, boolean attachment) { logger.log(logger.EXTREME, "Inside create resource"); - QFile resourceFile; + QFile resourceFile; + //These two lines are added to handle odd characters in the name like #. Without it + // toLocalFile() chokes and returns the wrong name. + logger.log(logger.EXTREME, "File URL:" +url); + String whichOS = System.getProperty("os.name"); + if (whichOS.contains("Windows")) + url = url.replace("file:///", ""); + else + url = url.replace("file://", ""); String urlTest = new QUrl(url).toLocalFile(); + logger.log(logger.EXTREME, "File URL toLocalFile():" +urlTest); + urlTest = url; if (!urlTest.equals("")) url = urlTest; - url = url.replace("/", File.separator); - resourceFile = new QFile(url); +// url = url.replace("/", File.separator); + logger.log(logger.EXTREME, "Reading from file to create resource:" +url); + resourceFile = new QFile(url); resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly)); + logger.log(logger.EXTREME, "Error opening file "+url.toString() +": "+resourceFile.errorString()); byte[] fileData = resourceFile.readAll().toByteArray(); resourceFile.close(); + logger.log(logger.EXTREME, "File Length: " +fileData.length); if (fileData.length == 0) return null; MessageDigest md; try { + logger.log(logger.EXTREME, "Generating MD5"); md = MessageDigest.getInstance("MD5"); md.update(fileData); byte[] hash = md.digest(); @@ -1963,6 +2507,7 @@ public class BrowserWindow extends QWidget { r.setAttributes(a); conn.getNoteTable().noteResourceTable.saveNoteResource(r, true); + logger.log(logger.EXTREME, "Resource created"); return r; } catch (NoSuchAlgorithmException e1) { e1.printStackTrace(); @@ -1980,29 +2525,7 @@ public class BrowserWindow extends QWidget { return "attachment.png"; } - // Check if the account supports this type of attachment - private boolean validAttachment(String type) { - if (Global.isPremium()) - return true; - if (type.equalsIgnoreCase("JPG")) - return true; - if (type.equalsIgnoreCase("PNG")) - return true; - if (type.equalsIgnoreCase("GIF")) - return true; - if (type.equalsIgnoreCase("MP3")) - return true; - if (type.equalsIgnoreCase("WAV")) - return true; - if (type.equalsIgnoreCase("AMR")) - return true; - if (type.equalsIgnoreCase("PDF")) - return true; - String error = tr("Non-premium accounts can only attach JPG, PNG, GIF, MP3, WAV, AMR, or PDF files."); - QMessageBox.information(this, tr("Non-Premium Account"), error); - return false; - } // Check the file attachment to be sure it isn't over 25 mb private boolean checkFileAttachmentSize(String url) { @@ -2220,7 +2743,7 @@ public class BrowserWindow extends QWidget { text = text.substring(0,imagePos) +plainText+text.substring(endPos+1); QTextCodec codec = QTextCodec.codecForName("UTF-8"); QByteArray unicode = codec.fromUnicode(text); - browser.setContent(unicode); + setContent(unicode); if (permanent) contentChanged(); } @@ -2280,11 +2803,17 @@ public class BrowserWindow extends QWidget { browser.rotateImageLeft.setEnabled(false); browser.rotateImageRight.setEnabled(false); browser.insertTableAction.setEnabled(true); + browser.deleteTableColumnAction.setEnabled(false); browser.insertTableRowAction.setEnabled(false); + browser.insertTableColumnAction.setEnabled(false); browser.deleteTableRowAction.setEnabled(false); browser.insertLinkAction.setText(tr("Insert Hyperlink")); + insertHyperlink = true; + browser.insertQuickLinkAction.setEnabled(true); currentHyperlink =""; insideList = false; + insideTable = false; + insideEncryption = false; forceTextPaste = false; String js = new String( "function getCursorPos() {" @@ -2295,7 +2824,7 @@ public class BrowserWindow extends QWidget { +" var workingNode = window.getSelection().anchorNode.parentNode;" +" while(workingNode != null) { " // +" window.jambi.printNode(workingNode.nodeName);" - +" if (workingNode.nodeName=='TABLE') { if (workingNode.getAttribute('class').toLowerCase() == 'en-crypt-temp') window.jambi.forceTextPaste(); }" + +" if (workingNode.nodeName=='TABLE') { if (workingNode.getAttribute('class').toLowerCase() == 'en-crypt-temp') window.jambi.insideEncryption(); }" +" if (workingNode.nodeName=='B') window.jambi.boldActive();" +" if (workingNode.nodeName=='I') window.jambi.italicActive();" +" if (workingNode.nodeName=='U') window.jambi.underlineActive();" @@ -2318,6 +2847,10 @@ public class BrowserWindow extends QWidget { System.out.println("Node Vaule: " +n); } + public void insideEncryption() { + insideEncryption = true; + forceTextPaste(); + } //**************************************************************** //* Insert a table row @@ -2347,8 +2880,34 @@ public class BrowserWindow extends QWidget { browser.page().mainFrame().evaluateJavaScript(js); contentChanged(); } + + public void insertTableColumn() { + String js = new String( "function insertTableColumn() {" + +" var selObj = window.getSelection();" + +" var selRange = selObj.getRangeAt(0);" + +" var workingNode = window.getSelection().anchorNode.parentNode;" + +" var current = 0;" + +" while (workingNode.nodeName.toLowerCase() != 'table' && workingNode != null) {" + +" if (workingNode.nodeName.toLowerCase() == 'td') {" + +" var td = workingNode;" + +" while (td.previousSibling != null) { " + +" current = current+1; td = td.previousSibling;" + +" }" + +" }" + +" workingNode = workingNode.parentNode; " + +" }" + +" if (workingNode == null) return;" + +" for (var i=0; i"); + getBrowser().setContent(data); + checkNoteTitle(); + if (currentNote != null && sourceEdit != null) + noteSignal.noteChanged.emit(currentNote.getGuid(), sourceEdit.toPlainText()); + } + + private void setSource() { + String text = getContent(); + sourceEdit.blockSignals(true); + int body = text.indexOf(" 0) { + body = text.indexOf(">",body); + if (body > 0) { + sourceEditHeader =text.substring(0, body+1); + text = text.substring(body+1); + } + } + text = text.replace("", ""); + sourceEdit.setPlainText(text); + sourceEdit.setReadOnly(!getBrowser().page().isContentEditable()); + //syntaxHighlighter.rehighlight(); + sourceEdit.blockSignals(false); + } + + // show/hide view source window + public void showSource(boolean value) { + setSource(); + sourceEdit.setVisible(value); + } + + // Remove HTML tags + private String removeTags(String text) { + StringBuffer buffer = new StringBuffer(text); + boolean inTag = false; + int bodyPosition = text.indexOf("=0; i--) { + if (buffer.charAt(i) == '>') + inTag = true; + if (buffer.charAt(i) == '<') + inTag = false; + if (inTag || buffer.charAt(i) == '<' || i