/*
* This file is part of NixNote
* Copyright 2009 Randy Baumgarte
*
* This file may be licensed under the terms of of the
* GNU General Public License Version 2 (the ``GPL'').
*
* Software distributed under the License is distributed
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the GPL for the specific language
* governing rights and limitations.
*
* You should have received a copy of the GPL along with this
* program. If not, go to http://www.gnu.org/licenses/gpl.html
* or write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
package cx.fbn.nevernote.gui;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.FileNameMap;
import java.net.URI;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import com.evernote.edam.limits.Constants;
import com.evernote.edam.type.Data;
import com.evernote.edam.type.Note;
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;
import com.swabunga.spell.engine.Word;
import com.swabunga.spell.event.SpellCheckEvent;
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;
import com.trolltech.qt.core.QEvent.Type;
import com.trolltech.qt.core.QFile;
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;
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;
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;
import com.trolltech.qt.gui.QHBoxLayout;
import com.trolltech.qt.gui.QIcon;
import com.trolltech.qt.gui.QImage;
import com.trolltech.qt.gui.QKeyEvent;
import com.trolltech.qt.gui.QKeySequence;
import com.trolltech.qt.gui.QLabel;
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;
import com.trolltech.qt.webkit.QWebSettings;
import com.trolltech.qt.webkit.QWebView;
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 {
public final QLineEdit titleLabel;
private final QLineEdit urlText;
private final QLabel authorLabel;
private final QLineEdit authorText;
private final QComboBox geoBox;
public final TagLineEdit tagEdit;
public final QLabel tagLabel;
private final QPushButton urlLabel;
private final QLabel alteredLabel;
private final QDateEdit alteredDate;
private final QTimeEdit alteredTime;
private final QDateEdit createdDate;
private final QTimeEdit createdTime;
private final QLabel subjectLabel;
private final QDateEdit subjectDate;
private final QTimeEdit subjectTime;
public final QComboBox notebookBox;
private final QLabel notebookLabel;
private final QLabel createdLabel;
public final QComboBox fontSize;
public final QAction fontSizeAction;
private boolean extendedOn;
public boolean buttonsVisible;
private final String iconPath;
public final ContentView browser;
private final QTextEdit sourceEdit;
private String sourceEditHeader;
Highlighter syntaxHighlighter;
private List<Tag> allTags;
private List<String> currentTags;
public NoteSignal noteSignal;
public Signal2<String,String> evernoteLinkClicked;
private List<Notebook> notebookList;
private Note currentNote;
private String saveNoteTitle;
private String saveTagList;
private boolean insideList;
private final DatabaseConnection conn;
private final QCalendarWidget createdCalendarWidget;
private final QCalendarWidget alteredCalendarWidget;
private final QCalendarWidget subjectCalendarWidget;
public final QPushButton undoButton;
public final QAction undoAction;
public final QPushButton redoButton;
public final QAction redoAction;
public final QPushButton cutButton;
public final QAction cutAction;
public final QPushButton copyButton;
public final QAction copyAction;
public final QPushButton pasteButton;
public final QAction pasteAction;
public final QPushButton boldButton;
public final QAction boldAction;
public final QPushButton underlineButton;
public final QAction underlineAction;
public final QPushButton italicButton;
public final QAction italicAction;
public final Signal0 focusLost;
public final NoteResourceSignal resourceSignal;
public QPushButton rightAlignButton;
public final QAction rightAlignAction;
public QPushButton leftAlignButton;
public final QAction leftAlignAction;
public QPushButton centerAlignButton;
public final QAction centerAlignAction;
public final QPushButton strikethroughButton;
public final QAction strikethroughAction;
public final QPushButton hlineButton;
public final QAction hlineAction;
public final QPushButton indentButton;
public final QAction indentAction;
public final QPushButton outdentButton;
public final QAction outdentAction;
public final QPushButton bulletListButton;
public final QAction bulletListAction;
public final QPushButton numberListButton;
public final QAction numberListAction;
public final QPushButton spellCheckButton;
public final QAction spellCheckAction;
public final QPushButton todoButton;
public final QAction todoAction;
public final QShortcut focusTitleShortcut;
public final QShortcut focusTagShortcut;
public final QShortcut focusNoteShortcut;
public final QShortcut focusUrlShortcut;
public final QShortcut focusAuthorShortcut;
public EditorButtonBar buttonLayout;
public final QComboBox fontList;
public final QAction fontListAction;
public final QToolButton fontColor;
public final QAction fontColorAction;
private final ColorMenu fontColorMenu;
public final QToolButton fontHilight;
public final QAction fontHilightAction;
private final ColorMenu fontHilightColorMenu;
public final QFileSystemWatcher fileWatcher;
public int cursorPosition;
private boolean forceTextPaste;
private String selectedFile;
private String currentHyperlink;
public boolean keepPDFNavigationHidden;
private final ApplicationLogger logger;
SpellDictionary dictionary;
SpellDictionary userDictionary;
SpellChecker spellChecker;
SuggestionListener spellListener;
private final HashMap<String,Integer> previewPageList;
boolean insertHyperlink;
boolean insideTable;
boolean insideEncryption;
public Signal1<BrowserWindow> 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;
public boolean errorsFound = false;
private final SpellCheck spellCheckDialog;
private final BrowserWindow parent;
public SuggestionListener(BrowserWindow parent, SpellChecker checker) {
this.parent = parent;
spellCheckDialog = new SpellCheck(checker);
}
public void spellingError(SpellCheckEvent event) {
errorsFound = true;
spellCheckDialog.setWord(event.getInvalidWord());
@SuppressWarnings("unchecked")
List<Word> suggestions = event.getSuggestions();
spellCheckDialog.clearSuggestions();
if (!suggestions.isEmpty()) {
// spellCheckDialog.setCurrentSuggestion(suggestions.get(0).getWord());
for (int i=0; i<suggestions.size(); i++) {
spellCheckDialog.addSuggestion(suggestions.get(i).getWord());
}
spellCheckDialog.setSelectedSuggestion(0);
}
spellCheckDialog.exec();
if (spellCheckDialog.cancelPressed()) {
abortSpellCheck = true;
event.cancel();
return;
}
if (spellCheckDialog.replacePressed()) {
QClipboard clipboard = QApplication.clipboard();
clipboard.setText(spellCheckDialog.getReplacementWord());
parent.pasteClicked();
}
event.cancel();
}
}
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<String,String>();
titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX);
urlText = new QLineEdit();
authorText = new QLineEdit();
geoBox = new QComboBox();
urlLabel = new QPushButton();
urlLabel.clicked.connect(this, "sourceUrlClicked()");
authorLabel = new QLabel();
conn = c;
focusLost = new Signal0();
tagEdit = new TagLineEdit(allTags);
tagLabel = new QLabel(tr("Tags:"));
tagEdit.focusLost.connect(this, "modifyTagsTyping()");
createdCalendarWidget = new QCalendarWidget();
createdDate = new QDateEdit();
createdDate.setDisplayFormat(Global.getDateFormat());
createdDate.setCalendarPopup(true);
createdDate.setCalendarWidget(createdCalendarWidget);
createdTime = new QTimeEdit();
createdDate.dateChanged.connect(this, "createdChanged()");
createdTime.timeChanged.connect(this, "createdChanged()");
alteredCalendarWidget = new QCalendarWidget();
alteredDate = new QDateEdit();
alteredDate.setDisplayFormat(Global.getDateFormat());
alteredDate.setCalendarPopup(true);
alteredDate.setCalendarWidget(alteredCalendarWidget);
alteredTime = new QTimeEdit();
alteredLabel = new QLabel(tr("Altered:"));
alteredDate.dateChanged.connect(this, "alteredChanged()");
alteredTime.timeChanged.connect(this, "alteredChanged()");
subjectCalendarWidget = new QCalendarWidget();
subjectDate = new QDateEdit();
subjectDate.setDisplayFormat(Global.getDateFormat());
subjectDate.setCalendarPopup(true);
subjectDate.setCalendarWidget(subjectCalendarWidget);
subjectTime = new QTimeEdit();
subjectLabel = new QLabel(tr("Subject Date:"));
subjectDate.dateChanged.connect(this, "subjectDateTimeChanged()");
subjectTime.timeChanged.connect(this, "subjectDateTimeChanged()");
authorText.textChanged.connect(this, "authorChanged()");
urlText.textChanged.connect(this, "sourceUrlChanged()");
notebookBox = new QComboBox();
notebookLabel = new QLabel(tr("Notebook"));
createdLabel = new QLabel(tr("Created:"));
// selectedText = new String();
urlLabel.setVisible(false);
urlText.setVisible(false);
authorLabel.setVisible(false);
geoBox.setVisible(false);
geoBox.addItem(new QIcon(iconPath+"globe.png"), "");
geoBox.addItem(new String(tr("Set")));
geoBox.addItem(new String(tr("Clear")));
geoBox.addItem(new String(tr("View On Map")));
geoBox.activated.connect(this, "geoBoxChanged()");
authorText.setVisible(false);
createdDate.setVisible(false);
alteredLabel.setVisible(false);
//notebookBox.setVisible(false);
notebookLabel.setVisible(false);
createdLabel.setVisible(false);
createdTime.setVisible(false);
alteredDate.setVisible(false);
alteredTime.setVisible(false);
subjectLabel.setVisible(false);
subjectDate.setVisible(false);
subjectTime.setVisible(false);
extendedOn = false;
buttonsVisible = true;
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();
titleLabel.setReadOnly(false);
titleLabel.editingFinished.connect(this, "titleEdited()");
browser.page().contentsChanged.connect(this, "contentChanged()");
browser.page().selectionChanged.connect(this, "selectionChanged()");
browser.page().mainFrame().javaScriptWindowObjectCleared.connect(this,
"exposeToJavascript()");
notebookBox.activated.connect(this, "notebookChanged()");
resourceSignal = new NoteResourceSignal();
QHBoxLayout tagLayout = new QHBoxLayout();
v.addWidget(titleLabel, 0);
notebookLayout.addRow(notebookLabel, notebookBox);
tagLayout.addLayout(notebookLayout, 0);
tagLayout.stretch(4);
tagLayout.addWidget(tagLabel, 0);
tagLayout.addWidget(tagEdit, 1);
v.addLayout(tagLayout);
QHBoxLayout urlLayout = new QHBoxLayout();
urlLayout.addWidget(urlLabel, 0);
urlLayout.addWidget(urlText, 0);
v.addLayout(urlLayout);
QHBoxLayout authorLayout = new QHBoxLayout();
authorLayout.addWidget(authorLabel, 0);
authorLayout.addWidget(authorText, 0);
authorLayout.addWidget(geoBox);
v.addLayout(authorLayout);
dateLayout.addWidget(createdLabel, 0, 0);
dateLayout.addWidget(createdDate, 0, 1);
dateLayout.addWidget(createdTime, 0, 2);
dateLayout.setColumnStretch(9, 100);
dateLayout.addWidget(alteredLabel, 0, 3);
dateLayout.addWidget(alteredDate, 0, 4);
dateLayout.addWidget(alteredTime, 0, 5);
dateLayout.addWidget(subjectLabel, 0, 6);
dateLayout.addWidget(subjectDate, 0, 7);
dateLayout.addWidget(subjectTime, 0, 8);
v.addLayout(dateLayout, 0);
undoButton = newEditorButton("undo", tr("Undo Change"));
redoButton = newEditorButton("redo", tr("Redo Change"));
cutButton = newEditorButton("cut", tr("Cut"));
copyButton = newEditorButton("copy", tr("Copy"));
pasteButton = newEditorButton("paste", tr("Paste"));
boldButton = newEditorButton("bold", tr("Bold"));
underlineButton = newEditorButton("underline", tr("Underline"));
italicButton = newEditorButton("italic", tr("Italic"));
rightAlignButton = newEditorButton("justifyRight", tr("Right Align"));
leftAlignButton = newEditorButton("justifyLeft", tr("Left Align"));
centerAlignButton = newEditorButton("justifyCenter", tr("Center Align"));
strikethroughButton = newEditorButton("strikethrough", tr("Strikethrough"));
hlineButton = newEditorButton("hline", tr("Insert Horizontal Line"));
indentButton = newEditorButton("indent", tr("Shift Right"));
outdentButton = newEditorButton("outdent", tr("Shift Left"));
bulletListButton = newEditorButton("bulletList", tr("Bullet List"));
numberListButton = newEditorButton("numberList", tr("Number List"));
spellCheckButton = newEditorButton("spellCheck", tr("Spell Check"));
todoButton = newEditorButton("todo", tr("To-do"));
buttonLayout = new EditorButtonBar();
v.addWidget(buttonLayout);
undoAction = buttonLayout.addWidget(undoButton);
buttonLayout.toggleUndoVisible.triggered.connect(this, "toggleUndoVisible(Boolean)");
redoAction = buttonLayout.addWidget(redoButton);
buttonLayout.toggleRedoVisible.triggered.connect(this, "toggleRedoVisible(Boolean)");
buttonLayout.addWidget(newSeparator());
cutAction = buttonLayout.addWidget(cutButton);
buttonLayout.toggleCutVisible.triggered.connect(this, "toggleCutVisible(Boolean)");
copyAction = buttonLayout.addWidget(copyButton);
buttonLayout.toggleCopyVisible.triggered.connect(this, "toggleCopyVisible(Boolean)");
pasteAction = buttonLayout.addWidget(pasteButton);
buttonLayout.togglePasteVisible.triggered.connect(this, "togglePasteVisible(Boolean)");
buttonLayout.addWidget(newSeparator());
boldAction = buttonLayout.addWidget(boldButton);
buttonLayout.toggleBoldVisible.triggered.connect(this, "toggleBoldVisible(Boolean)");
italicAction = buttonLayout.addWidget(italicButton);
buttonLayout.toggleItalicVisible.triggered.connect(this, "toggleItalicVisible(Boolean)");
underlineAction = buttonLayout.addWidget(underlineButton);
buttonLayout.toggleUnderlineVisible.triggered.connect(this, "toggleUnderlineVisible(Boolean)");
strikethroughAction = buttonLayout.addWidget(strikethroughButton);
buttonLayout.toggleStrikethroughVisible.triggered.connect(this, "toggleStrikethroughVisible(Boolean)");
buttonLayout.addWidget(newSeparator());
leftAlignAction = buttonLayout.addWidget(leftAlignButton);
buttonLayout.toggleLeftAlignVisible.triggered.connect(this, "toggleLeftAlignVisible(Boolean)");
centerAlignAction = buttonLayout.addWidget(centerAlignButton);
buttonLayout.toggleCenterAlignVisible.triggered.connect(this, "toggleCenterAlignVisible(Boolean)");
rightAlignAction = buttonLayout.addWidget(rightAlignButton);
buttonLayout.toggleRightAlignVisible.triggered.connect(this, "toggleRightAlignVisible(Boolean)");
buttonLayout.addWidget(newSeparator());
hlineAction = buttonLayout.addWidget(hlineButton);
buttonLayout.toggleHLineVisible.triggered.connect(this, "toggleHLineVisible(Boolean)");
indentAction = buttonLayout.addWidget(indentButton);
buttonLayout.toggleIndentVisible.triggered.connect(this, "toggleIndentVisible(Boolean)");
outdentAction = buttonLayout.addWidget(outdentButton);
buttonLayout.toggleOutdentVisible.triggered.connect(this, "toggleOutdentVisible(Boolean)");
bulletListAction = buttonLayout.addWidget(bulletListButton);
buttonLayout.toggleBulletListVisible.triggered.connect(this, "toggleBulletListVisible(Boolean)");
numberListAction = buttonLayout.addWidget(numberListButton);
buttonLayout.toggleNumberListVisible.triggered.connect(this, "toggleNumberListVisible(Boolean)");
// Setup the font & font size combo boxes
buttonLayout.addWidget(newSeparator());
fontList = new QComboBox();
fontSize = new QComboBox();
fontList.setToolTip("Font");
fontSize.setToolTip("Font Size");
fontList.activated.connect(this, "fontChanged(String)");
fontSize.activated.connect(this, "fontSizeChanged(String)");
fontListAction = buttonLayout.addWidget(fontList);
buttonLayout.toggleFontVisible.triggered.connect(this, "toggleFontListVisible(Boolean)");
fontSizeAction = buttonLayout.addWidget(fontSize);
buttonLayout.toggleFontSizeVisible.triggered.connect(this, "toggleFontSizeVisible(Boolean)");
QFontDatabase fonts = new QFontDatabase();
List<String> fontFamilies = fonts.families();
for (int i = 0; i < fontFamilies.size(); i++) {
fontList.addItem(fontFamilies.get(i));
if (i == 0) {
loadFontSize(fontFamilies.get(i));
}
}
// buttonLayout.addWidget(newSeparator(), 0);
fontColor = newToolButton("fontColor", tr("Font Color"));
fontColorMenu = new ColorMenu(this);
fontColor.setMenu(fontColorMenu.getMenu());
fontColor.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
fontColor.setAutoRaise(false);
fontColorMenu.getMenu().triggered.connect(this, "fontColorClicked()");
fontColorAction = buttonLayout.addWidget(fontColor);
buttonLayout.toggleFontColorVisible.triggered.connect(this, "toggleFontColorVisible(Boolean)");
fontHilight = newToolButton("fontHilight", tr("Font Hilight Color"));
fontHilight.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
fontHilight.setAutoRaise(false);
fontHilightColorMenu = new ColorMenu(this);
fontHilightColorMenu.setDefault(QColor.yellow);
fontHilight.setMenu(fontHilightColorMenu.getMenu());
fontHilightColorMenu.getMenu().triggered.connect(this, "fontHilightClicked()");
fontHilightAction = buttonLayout.addWidget(fontHilight);
fontHilightColorMenu.setDefault(QColor.yellow);
buttonLayout.toggleFontHilight.triggered.connect(this, "toggleFontHilightVisible(Boolean)");
spellCheckAction = buttonLayout.addWidget(spellCheckButton);
buttonLayout.toggleNumberListVisible.triggered.connect(this, "spellCheckClicked()");
buttonLayout.toggleSpellCheck.triggered.connect(this, "toggleSpellCheckVisible(Boolean)");
todoAction = buttonLayout.addWidget(todoButton);
buttonLayout.toggleNumberListVisible.triggered.connect(this, "todoClicked()");
buttonLayout.toggleTodo.triggered.connect(this, "toggleTodoVisible(Boolean)");
// Setup the source browser);
// buttonLayout.addWidget(new QLabel(), 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,
"downloadAttachment(QNetworkRequest)");
browser.downloadImageRequested.connect(this,
"downloadImage(QNetworkRequest)");
setTabOrder(notebookBox, tagEdit);
setTabOrder(tagEdit, browser);
focusNoteShortcut = new QShortcut(this);
setupShortcut(focusNoteShortcut, "Focus_Note");
focusNoteShortcut.activated.connect(this, "focusNote()");
focusTitleShortcut = new QShortcut(this);
setupShortcut(focusTitleShortcut, "Focus_Title");
focusTitleShortcut.activated.connect(this, "focusTitle()");
focusTagShortcut = new QShortcut(this);
setupShortcut(focusTagShortcut, "Focus_Tag");
focusTagShortcut.activated.connect(this, "focusTag()");
focusAuthorShortcut = new QShortcut(this);
setupShortcut(focusAuthorShortcut, "Focus_Author");
focusAuthorShortcut.activated.connect(this, "focusAuthor()");
focusUrlShortcut = new QShortcut(this);
setupShortcut(focusUrlShortcut, "Focus_Url");
focusUrlShortcut.activated.connect(this, "focusUrl()");
browser.page().mainFrame().setTextSizeMultiplier(Global.getTextSizeMultiplier());
browser.page().mainFrame().setZoomFactor(Global.getZoomFactor());
previewPageList = new HashMap<String,Integer>();
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<BrowserWindow>();
unblockApplication = new Signal0();
setSourceTimer = new QTimer();
setSourceTimer.timeout.connect(this, "setSource()");
logger.log(logger.HIGH, "Browser setup complete");
}
private void setupShortcut(QShortcut action, String text) {
if (!Global.shortcutKeys.containsAction(text))
return;
action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
}
// Getter for the QWebView
public QWebView getBrowser() {
return browser;
}
// Block signals while loading data or things are flagged as dirty by
// mistake
public void loadingData(boolean val) {
logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val);
notebookBox.blockSignals(val);
browser.page().blockSignals(val);
browser.page().mainFrame().blockSignals(val);
titleLabel.blockSignals(val);
alteredDate.blockSignals(val);
alteredTime.blockSignals(val);
createdTime.blockSignals(val);
createdDate.blockSignals(val);
subjectDate.blockSignals(val);
subjectTime.blockSignals(val);
urlText.blockSignals(val);
authorText.blockSignals(val);
if (!val)
exposeToJavascript();
logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val);
}
// Enable/disable
public void setReadOnly(boolean v) {
setEnabled(true);
titleLabel.setEnabled(!v);
notebookBox.setEnabled(!v);
tagEdit.setEnabled(!v);
authorLabel.setEnabled(!v);
geoBox.setEnabled(!v);
urlText.setEnabled(!v);
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().page().setContentEditable(!v);
// getBrowser().setEnabled(!v);
}
// expose this class to Javascript on the web page
private void exposeToJavascript() {
browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this);
}
// Custom event queue
@Override
public boolean event(QEvent e) {
if (e.type().equals(QEvent.Type.FocusOut)) {
logger.log(logger.EXTREME, "Focus lost");
focusLost.emit();
}
return super.event(e);
}
// clear out browser
public void clear() {
logger.log(logger.EXTREME, "Entering BrowserWindow.clear()");
setNote(null);
setContent(new QByteArray());
tagEdit.setText("");
tagEdit.tagCompleter.reset();
urlLabel.setText(tr("Source URL:"));
titleLabel.setText("");
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;
if (n == null)
n = new Note();
saveNoteTitle = n.getTitle();
}
public Note getNote() {
return currentNote;
}
// New Editor Button
private QPushButton newEditorButton(String name, String toolTip) {
QPushButton button = new QPushButton();
// QIcon icon = new QIcon(iconPath + name + ".gif");
QIcon icon = new QIcon(iconPath + name + ".png");
button.setIcon(icon);
button.setToolTip(toolTip);
button.clicked.connect(this, name + "Clicked()");
return button;
}
// New Editor Button
private QToolButton newToolButton(String name, String toolTip) {
QToolButton button = new QToolButton();
// QIcon icon = new QIcon(iconPath + name + ".gif");
QIcon icon = new QIcon(iconPath + name + ".png");
button.setIcon(icon);
button.setToolTip(toolTip);
button.clicked.connect(this, name + "Clicked()");
return button;
}
// New Separator
private QLabel newSeparator() {
return new QLabel(" ");
}
// Set the title in the window
public void setTitle(String t) {
titleLabel.setText(t);
saveNoteTitle = t;
checkNoteTitle();
}
// Return the current text title
public String getTitle() {
return titleLabel.text();
}
// Set the tag name string
public void setTag(String t) {
saveTagList = t;
tagEdit.setText(t);
tagEdit.tagCompleter.reset();
}
// Set the source URL
public void setUrl(String t) {
urlLabel.setText(tr("Source URL:\t"));
urlText.setText(t);
}
// The user want's to launch a web browser on the source of the URL
public void sourceUrlClicked() {
// Make sure we have a valid URL
if (urlText.text().trim().equals(""))
return;
String url = urlText.text();
if (!url.toLowerCase().startsWith(tr("http://")))
url = tr("http://") +url;
if (!QDesktopServices.openUrl(new QUrl(url))) {
logger.log(logger.LOW, "Error opening file :" +url);
}
}
public void setAuthor(String t) {
authorLabel.setText(tr("Author:\t"));
authorText.setText(t);
}
// Set the creation date
public void setCreation(long date) {
QDateTime dt = new QDateTime();
dt.setTime_t((int) (date / 1000));
createdDate.setDateTime(dt);
createdTime.setDateTime(dt);
createdDate.setDisplayFormat(Global.getDateFormat());
createdTime.setDisplayFormat(Global.getTimeFormat());
}
// Set the creation date
public void setAltered(long date) {
QDateTime dt = new QDateTime();
dt.setTime_t((int) (date / 1000));
alteredDate.setDateTime(dt);
alteredTime.setDateTime(dt);
alteredDate.setDisplayFormat(Global.getDateFormat());
alteredTime.setDisplayFormat(Global.getTimeFormat());
}
// Set the subject date
public void setSubjectDate(long date) {
QDateTime dt = new QDateTime();
dt.setTime_t((int) (date / 1000));
subjectDate.setDateTime(dt);
subjectTime.setDateTime(dt);
subjectDate.setDisplayFormat(Global.getDateFormat());
subjectTime.setDisplayFormat(Global.getTimeFormat());
}
// Toggle the extended attribute information
public void toggleInformation() {
if (extendedOn) {
extendedOn = false;
} else {
extendedOn = true;
}
urlLabel.setVisible(extendedOn);
urlText.setVisible(extendedOn);
authorText.setVisible(extendedOn);
geoBox.setVisible(extendedOn);
authorLabel.setVisible(extendedOn);
createdDate.setVisible(extendedOn);
createdTime.setVisible(extendedOn);
createdLabel.setVisible(extendedOn);
alteredLabel.setVisible(extendedOn);
alteredDate.setVisible(extendedOn);
alteredTime.setVisible(extendedOn);
//notebookBox.setVisible(extendedOn);
notebookLabel.setVisible(extendedOn);
subjectLabel.setVisible(extendedOn);
subjectDate.setVisible(extendedOn);
subjectTime.setVisible(extendedOn);
}
public void hideButtons() {
undoButton.parentWidget().setVisible(false);
buttonsVisible = false;
}
// Is the extended view on?
public boolean isExtended() {
return extendedOn;
}
// Listener for when a link is clicked
@SuppressWarnings("unused")
private void openFile() {
logger.log(logger.EXTREME, "Starting openFile()");
File fileHandle = new File(selectedFile);
URI fileURL = fileHandle.toURI();
String localURL = fileURL.toString();
QUrl url = new QUrl(localURL);
QFile file = new QFile(selectedFile);
logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName());
fileWatcher.addPath(file.fileName());
if (!QDesktopServices.openUrl(url)) {
logger.log(logger.LOW, "Error opening file :" +url);
}
}
// Listener for when a link is clicked
@SuppressWarnings("unused")
private void linkClicked(QUrl url) {
logger.log(logger.EXTREME, "URL Clicked: " +url.toString());
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");
QMessageBox.information(this, tr("Unable Open"), tr("This is an ink note.\n"+
"Ink notes are not supported since Evernote has not\n published any specifications on them\n" +
"and I'm too lazy to figure them out by myself."));
return;
}
String fullName = url.toString().substring(8);
int index = fullName.indexOf(".");
String guid = "";
String type = "";
if (index >-1) {
type = fullName.substring(index+1);
guid = fullName.substring(0,index);
}
index = guid.indexOf(Global.attachmentNameDelimeter);
if (index > -1) {
guid = guid.substring(0,index);
}
List<Resource> resList = currentNote.getResources();
Resource res = null;
for (int i=0; i<resList.size(); i++) {
if (resList.get(i).getGuid().equals(guid)) {
res = resList.get(i);
i=resList.size();
}
}
if (res == null) {
String resGuid = Global.resourceMap.get(guid);
if (resGuid != null)
res = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, true);
}
if (res != null) {
String fileName;
if (res.getAttributes() != null &&
res.getAttributes().getFileName() != null &&
!res.getAttributes().getFileName().trim().equals(""))
fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();
else
fileName = res.getGuid()+"."+type;
QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
QFile.OpenMode mode = new QFile.OpenMode();
mode.set(QFile.OpenModeFlag.WriteOnly);
boolean openResult = file.open(mode);
logger.log(logger.EXTREME, "File opened:" +openResult);
QDataStream out = new QDataStream(file);
Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);
QByteArray binData = new QByteArray(resBinary.getData().getBody());
resBinary = null;
logger.log(logger.EXTREME, "Writing resource");
out.writeBytes(binData.toByteArray());
file.close();
String whichOS = System.getProperty("os.name");
if (whichOS.contains("Windows"))
url.setUrl("file:///"+file.fileName());
else
url.setUrl("file://"+file.fileName());
// fileWatcher.removePath(file.fileName());
logger.log(logger.EXTREME, "Adding file watcher " +file.fileName());
fileWatcher.addPath(file.fileName());
// If we can't open it, then prompt the user to save it.
if (!QDesktopServices.openUrl(url)) {
logger.log(logger.EXTREME, "We can't handle this. Where do we put it?");
QFileDialog dialog = new QFileDialog();
dialog.show();
if (dialog.exec()!=0) {
List<String> fileNames = dialog.selectedFiles(); //gets all selected filenames
if (fileNames.size() == 0)
return;
String sf = fileNames.get(0);
QFile saveFile = new QFile(sf);
mode.set(QFile.OpenModeFlag.WriteOnly);
saveFile.open(mode);
QDataStream saveOut = new QDataStream(saveFile);
saveOut.writeBytes(binData.toByteArray());
saveFile.close();
return;
}
}
}
return;
}
logger.log(logger.EXTREME, "Launching URL");
QDesktopServices.openUrl(url);
}
// Listener for when BOLD is clicked
@SuppressWarnings("unused")
private void undoClicked() {
browser.page().triggerAction(WebAction.Undo);
browser.setFocus();
}
// Listener for when BOLD is clicked
@SuppressWarnings("unused")
private void redoClicked() {
browser.page().triggerAction(WebAction.Redo);
browser.setFocus();
}
// Listener for when BOLD is clicked
@SuppressWarnings("unused")
private void boldClicked() {
browser.page().triggerAction(WebAction.ToggleBold);
microFocusChanged();
browser.setFocus();
}
// Listener for when Italics is clicked
@SuppressWarnings("unused")
private void italicClicked() {
browser.page().triggerAction(WebAction.ToggleItalic);
microFocusChanged();
browser.setFocus();
}
// Listener for when UNDERLINE is clicked
@SuppressWarnings("unused")
private void underlineClicked() {
browser.page().triggerAction(WebAction.ToggleUnderline);
microFocusChanged();
browser.setFocus();
}
// Listener for when Strikethrough is clicked
@SuppressWarnings("unused")
private void strikethroughClicked() {
browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('strikeThrough', false, '');");
browser.setFocus();
}
// Listener for when cut is clicked
@SuppressWarnings("unused")
private void cutClicked() {
browser.page().triggerAction(WebAction.Cut);
browser.setFocus();
}
// Listener when COPY is clicked
@SuppressWarnings("unused")
private void copyClicked() {
browser.page().triggerAction(WebAction.Copy);
browser.setFocus();
}
// Listener when PASTE is clicked
public void pasteClicked() {
logger.log(logger.EXTREME, "Paste Clicked");
if (forceTextPaste) {
pasteWithoutFormattingClicked();
return;
}
QClipboard clipboard = QApplication.clipboard();
QMimeData mime = clipboard.mimeData();
if (mime.hasImage()) {
logger.log(logger.EXTREME, "Image paste found");
browser.setFocus();
insertImage(mime);
browser.setFocus();
return;
}
if (mime.hasUrls()) {
logger.log(logger.EXTREME, "URL paste found");
if (mime.text().startsWith("evernote:")) {
handleNoteLink(mime);
} else {
handleUrls(mime);
browser.setFocus();
}
return;
}
String text = mime.html();
if (text.contains("en-tag") && mime.hasHtml()) {
logger.log(logger.EXTREME, "Intra-note paste found");
text = fixInternotePaste(text);
mime.setHtml(text);
clipboard.setMimeData(mime);
}
logger.log(logger.EXTREME, "Final paste choice encountered");
browser.page().triggerAction(WebAction.Paste);
browser.setFocus();
}
// Paste text without formatting
private void pasteWithoutFormattingClicked() {
logger.log(logger.EXTREME, "Paste without format clipped");
QClipboard clipboard = QApplication.clipboard();
QMimeData mime = clipboard.mimeData();
if (!mime.hasText())
return;
String text = mime.text();
clipboard.clear();
clipboard.setText(text, Mode.Clipboard);
browser.page().triggerAction(WebAction.Paste);
// 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("<tbody>", "");
data = data.replace("</tbody>", "");
data = data.replace("<tr>", "");
data = data.replace("</tr>", "");
data = data.replace("<td>", "");
data = data.replace("</td>", "<br>");
data = data.replace("<br><br>", "<br>");
return "<tbody><tr><td>"+data+"</td></tr></tbody>";
}
// insert date/time
@SuppressWarnings("unused")
private void insertDateTime() {
String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
String dateTimeFormat = new String(fmt);
SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
Calendar cal = Calendar.getInstance();
browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");
browser.setFocus();
}
// Listener when Left is clicked
@SuppressWarnings("unused")
private void justifyLeftClicked() {
browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('JustifyLeft', false, '');");
browser.setFocus();
}
// Listener when Center is clicked
@SuppressWarnings("unused")
private void justifyCenterClicked() {
browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('JustifyCenter', false, '');");
browser.setFocus();
}
// Listener when Left is clicked
@SuppressWarnings("unused")
private void justifyRightClicked() {
browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('JustifyRight', false, '');");
browser.setFocus();
}
// Listener when HLINE is clicked
@SuppressWarnings("unused")
private void hlineClicked() {
browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('insertHorizontalRule', false, '');");
browser.setFocus();
}
// Listener when outdent is clicked
private void outdentClicked() {
browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('outdent', false, '');");
browser.setFocus();
}
// Listener when a bullet list is clicked
@SuppressWarnings("unused")
private void bulletListClicked() {
browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('InsertUnorderedList', false, '');");
browser.setFocus();
}
// Listener when a bullet list is clicked
@SuppressWarnings("unused")
private void numberListClicked() {
browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('InsertOrderedList', false, '');");
browser.setFocus();
}
// Listener when indent is clicked
private void indentClicked() {
browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('indent', false, '');");
browser.setFocus();
}
// Listener when the font name is changed
@SuppressWarnings("unused")
private void fontChanged(String font) {
browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('fontName',false,'" + font + "');");
browser.setFocus();
}
// Listener when a font size is changed
@SuppressWarnings("unused")
private void fontSizeChanged(String font) {
String text = browser.selectedText();
if (text.trim().equalsIgnoreCase(""))
return;
String selectedText = browser.selectedText();
String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";
String script = "document.execCommand('insertHtml', false, '"+url+"');";
browser.page().mainFrame().evaluateJavaScript(script);
/* browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('fontSize',false,'"
+ font + "');");
*/
browser.setFocus();
}
// Load the font combo box based upon the font selected
private void loadFontSize(String name) {
QFontDatabase db = new QFontDatabase();
fontSize.clear();
List<Integer> points = db.pointSizes(name);
for (int i=0; i<points.size(); i++) {
fontSize.addItem(points.get(i).toString());
}
/*
fontSize.addItem("x-small");
fontSize.addItem("small");
fontSize.addItem("medium");
fontSize.addItem("large");
fontSize.addItem("x-large");
fontSize.addItem("xx-large");
fontSize.addItem("xxx-large");
*/
}
// Listener when a font size is changed
@SuppressWarnings("unused")
private void fontColorClicked() {
// QColorDialog dialog = new QColorDialog();
// QColor color = QColorDialog.getColor();
QColor color = fontColorMenu.getColor();
if (color.isValid())
browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('foreColor',false,'" + color.name()
+ "');");
browser.setFocus();
}
// Listener for when a background color change is requested
@SuppressWarnings("unused")
private void fontHilightClicked() {
// QColorDialog dialog = new QColorDialog();
// QColor color = QColorDialog.getColor();
QColor color = fontHilightColorMenu.getColor();
if (color.isValid())
browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('backColor',false,'" + color.name()
+ "');");
browser.setFocus();
}
// Listener for when a background color change is requested
@SuppressWarnings("unused")
private void superscriptClicked() {
browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('superscript');");
browser.setFocus();
}
// Listener for when a background color change is requested
@SuppressWarnings("unused")
private void subscriptClicked() {
browser.page().mainFrame().evaluateJavaScript(
"document.execCommand('subscript');");
browser.setFocus();
}
// Insert a to-do checkbox
@SuppressWarnings("unused")
private void todoClicked() {
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String script_start = new String(
"document.execCommand('insertHtml', false, '");
String script_end = new String("');");
String todo = new String(
"<input TYPE=\"CHECKBOX\" value=\"false\" " +
"onMouseOver=\"style.cursor=\\'hand\\'\" " +
"onClick=\"value=checked; window.jambi.contentChanged(); \" />");
browser.page().mainFrame().evaluateJavaScript(
script_start + todo + script_end);
browser.setFocus();
}
// Encrypt the selected text
@SuppressWarnings("unused")
private void encryptText() {
String text = browser.selectedText();
if (text.trim().equalsIgnoreCase(""))
return;
text = new String(text.replaceAll("\n", "<br/>"));
EnCryptDialog dialog = new EnCryptDialog();
dialog.exec();
if (!dialog.okPressed()) {
return;
}
EnCrypt crypt = new EnCrypt();
String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);
String decrypted = crypt.decrypt(encrypted, dialog.getPassword().trim(), 64);
if (encrypted.trim().equals("")) {
QMessageBox.information(this, tr("Error"), tr("Error Encrypting String"));
return;
}
StringBuffer buffer = new StringBuffer(encrypted.length() + 100);
buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""
+ dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");
buffer.append("contentEditable=\"false\" alt=\"");
buffer.append(encrypted);
buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png") +"\""));
Global.cryptCounter++;
buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");
buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");
buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString()
+"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&apos;")+"\\');\"");
buffer.append("style=\"display:block\" />");
String script_start = new String(
"document.execCommand('insertHtml', false, '");
String script_end = new String("');");
browser.page().mainFrame().evaluateJavaScript(
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 = "<a title=\"" +dUrl
+"\" href=" +dUrl
+" >"+text +"</a>";
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");
String text = browser.selectedText();
if (text.trim().equalsIgnoreCase(""))
return;
InsertLinkDialog dialog = new InsertLinkDialog(insertHyperlink);
if (currentHyperlink != null && currentHyperlink != "") {
dialog.setUrl(currentHyperlink);
}
dialog.exec();
if (!dialog.okPressed()) {
logger.log(logger.EXTREME, "Insert link canceled");
return;
}
// 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(), "'", "\\'");
String url = "<a href=\"" +dUrl
+"\" title=" +dUrl
+" >"+selectedText +"</a>";
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 {
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<currentNote.getResourcesSize(); i++) {
if (currentNote.getResources().get(i).getGuid().equals(newRes.getGuid())) {
currentNote.getResources().remove(i);
i=currentNote.getResourcesSize();
}
}
currentNote.getResources().add(newRes);
// do the actual insert into the note. We only do this on new formulas.
if (latexGuid == null) {
StringBuffer buffer = new StringBuffer(100);
String formula = replyUrl.toString().toLowerCase().replace("http://latex.codecogs.com/gif.latex?", "");
buffer.append("<a href=\"latex://"+path.replace("\\", "/")+"\" title=\""+formula+"\""
+"><img src=\"");
buffer.append(path.replace("\\", "/"));
buffer.append("\" en-tag=\"en-latex\" type=\"image/gif\""
+" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
+" guid=\"" +newRes.getGuid() +"\""
+ " /></a>");
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() {
TableDialog dialog = new TableDialog();
dialog.exec();
if (!dialog.okPressed()) {
return;
}
int cols = dialog.getCols();
int rows = dialog.getRows();
int width = dialog.getWidth();
boolean percent = dialog.isPercent();
String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();
if (percent)
newHTML = newHTML +"%";
newHTML = newHTML + "\"><tbody>";
for (int i=0; i<rows; i++) {
newHTML = newHTML +"<tr>";
for (int j=0; j<cols; j++) {
newHTML = newHTML +"<td> </td>";
}
newHTML = newHTML +"</tr>";
}
newHTML = newHTML+"</tbody></table>";
String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";
browser.page().mainFrame().evaluateJavaScript(script);
}
// Text content changed
@SuppressWarnings("unused")
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;"
+ "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"
+ "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"
+ "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"
+ "var start = parent_html.indexOf(first_text);"
+ "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"
+ "var value = parent_html.substring(start,end);"
+ "window.jambi.saveSelectedText(value);" ;
browser.page().mainFrame().evaluateJavaScript(scriptStart);
}
public void saveSelectedText(String text) {
boolean enabled = true;
if (text.trim().length() == 0)
enabled=false;
if (text.indexOf("en-tag=\"en-crypt\"") >= 0)
enabled=false;
if (text.indexOf("<img en-tag=\"en-media\"") >= 0)
enabled=false;
if (text.indexOf("<a en-tag=\"en-media\"") >= 0)
enabled=false;
if (text.indexOf("<input ") >= 0)
enabled=false;
browser.encryptAction.setEnabled(enabled);
browser.insertLinkAction.setEnabled(enabled);
browser.insertQuickLinkAction.setEnabled(enabled);
// selectedText = text;
}
// Decrypt clicked text
public void decryptText(String id, String text, String hint) {
EnCrypt crypt = new EnCrypt();
String plainText = null;
Calendar currentTime = new GregorianCalendar();
Long l = new Long(currentTime.getTimeInMillis());
String slot = new String(Long.toString(l));
// First, try to decrypt with any keys we already have
for (int i=0; i<Global.passwordRemember.size(); i++) {
plainText = crypt.decrypt(text, Global.passwordRemember.get(i).getFirst(), 64);
if (plainText != null) {
slot = new String(Long.toString(l));
Global.passwordSafe.put(slot, Global.passwordRemember.get(i));
removeEncryption(id, plainText, false, slot);
return;
}
}
EnDecryptDialog dialog = new EnDecryptDialog();
dialog.setHint(hint);
while (plainText == null || !dialog.okPressed()) {
dialog.exec();
if (!dialog.okPressed()) {
return;
}
plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);
if (plainText == null) {
QMessageBox.warning(this, tr("Incorrect Password"), tr("The password entered is not correct"));
}
}
Pair<String,String> passwordPair = new Pair<String,String>();
passwordPair.setFirst(dialog.getPassword());
passwordPair.setSecond(dialog.getHint());
Global.passwordSafe.put(slot, passwordPair);
// removeEncryption(id, plainText.replaceAll("\n", "<br/>"), dialog.permanentlyDecrypt(), slot);
removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);
if (dialog.rememberPassword()) {
Pair<String, String> pair = new Pair<String,String>();
pair.setFirst(dialog.getPassword());
pair.setSecond(dialog.getHint());
Global.passwordRemember.add(pair);
}
}
// Get the editor tag line
public TagLineEdit getTagLine() {
return tagEdit;
}
// Modify a note's tags
@SuppressWarnings("unused")
private void modifyTags() {
TagAssign tagWindow = new TagAssign(allTags, currentTags, !conn.getNotebookTable().isLinked(currentNote.getNotebookGuid()));
tagWindow.exec();
if (tagWindow.okClicked()) {
currentTags.clear();
StringBuffer tagDisplay = new StringBuffer();
List<QListWidgetItem> newTags = tagWindow.getTagList()
.selectedItems();
for (int i = 0; i < newTags.size(); i++) {
currentTags.add(newTags.get(i).text());
tagDisplay.append(newTags.get(i).text());
if (i < newTags.size() - 1) {
tagDisplay.append(Global.tagDelimeter + " ");
}
}
tagEdit.setText(tagDisplay.toString());
noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
}
}
// Tag line has been modified by typing text
@SuppressWarnings("unused")
private void modifyTagsTyping() {
String completionText = "";
if (tagEdit.currentCompleterSelection != null && !tagEdit.currentCompleterSelection.equals("")) {
completionText = tagEdit.currentCompleterSelection;
tagEdit.currentCompleterSelection = "";
}
if (tagEdit.text().equalsIgnoreCase(saveTagList))
return;
// We know something has changed...
String oldTagArray[] = saveTagList.split(Global.tagDelimeter);
String newTagArray[];
if (!completionText.equals("")) {
String before = tagEdit.text().substring(0,tagEdit.cursorPosition());
int lastDelimiter = before.lastIndexOf(Global.tagDelimeter);
if (lastDelimiter > 0)
before = before.substring(0,before.lastIndexOf(Global.tagDelimeter));
else
before = "";
String after = tagEdit.text().substring(tagEdit.cursorPosition());
newTagArray = (before+Global.tagDelimeter+completionText+Global.tagDelimeter+after).split(Global.tagDelimeter);
}
else {
newTagArray = tagEdit.text().split(Global.tagDelimeter);
}
// Remove any traling or leading blanks
for (int i=0; i<newTagArray.length; i++)
newTagArray[i] = newTagArray[i].trim().replaceAll("^\\s+", "");;
// Remove any potential duplicates from the new list
for (int i=0; i<newTagArray.length; i++) {
boolean foundOnce = false;
for (int j=0; j<newTagArray.length; j++) {
if (newTagArray[j].equalsIgnoreCase(newTagArray[i])) {
if (!foundOnce) {
foundOnce = true;
} else
newTagArray[j] = "";
}
}
}
List<String> newTagList = new ArrayList<String>();
List<String> oldTagList = new ArrayList<String>();
for (int i = 0; i < oldTagArray.length; i++)
if (!oldTagArray[i].trim().equals(""))
oldTagList.add(oldTagArray[i]);
for (int i = 0; i < newTagArray.length; i++)
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<allTags.size(); j++) {
if (allTags.get(j).getName().equalsIgnoreCase(newTagList.get(i))) {
found = true;
j=allTags.size();
}
}
if (!found)
newTagList.remove(i);
}
}
// Let's cleanup the appearance of the tag list
Collections.sort(newTagList);
String newDisplay = "";
for (int i=0; i<newTagList.size(); i++) {
newDisplay = newDisplay+newTagList.get(i);
if (i<newTagList.size()-1)
newDisplay = newDisplay+Global.tagDelimeter +" ";
}
tagEdit.blockSignals(true);
tagEdit.setText(newDisplay);
tagEdit.blockSignals(false);
// We now have lists of the new & old. Remove duplicates. If all
// are removed from both then nothing has really changed
for (int i = newTagList.size() - 1; i >= 0; i--) {
String nTag = newTagList.get(i);
for (int j = oldTagList.size() - 1; j >= 0; j--) {
String oTag = oldTagList.get(j);
if (oTag.equalsIgnoreCase(nTag)) {
oldTagList.remove(j);
newTagList.remove(i);
j = -1;
}
}
}
if (oldTagList.size() != 0 || newTagList.size() != 0) {
currentTags.clear();
newTagArray = tagEdit.text().split(Global.tagDelimeter);
for (int i = 0; i < newTagArray.length; i++)
if (!newTagArray[i].trim().equals(""))
currentTags.add(newTagArray[i].trim());
noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
}
}
// Tab button was pressed
public void tabPressed() {
if (insideEncryption)
return;
if (!insideList && !insideTable) {
String script_start = new String(
"document.execCommand('insertHtml', false, ' ');");
browser.page().mainFrame().evaluateJavaScript(script_start);
return;
}
if (insideList) {
indentClicked();
}
if (insideTable) {
String js = new String( "function getCursorPosition() { "
+" var selObj = window.getSelection();"
+" var selRange = selObj.getRangeAt(0);"
+" var workingNode = window.getSelection().anchorNode;"
+" var rowCount = 0;"
+" var colCount = 0;"
+" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
+" if (workingNode.nodeName.toLowerCase()=='tr') {"
+" rowCount = rowCount+1;"
+" }"
+" if (workingNode.nodeName.toLowerCase() == 'td') {"
+" colCount = colCount+1;"
+" }"
+" if (workingNode.previousSibling != null)"
+" workingNode = workingNode.previousSibling;"
+" else "
+" workingNode = workingNode.parentNode;"
+" }"
+" var nodes = workingNode.getElementsByTagName('tr');"
+" var tableRows = nodes.length;"
+" nodes = nodes[0].getElementsByTagName('td');"
+" var tableColumns = nodes.length;"
+" window.jambi.setTableCursorPositionTab(rowCount, colCount, tableRows, tableColumns);"
+"} getCursorPosition();");
browser.page().mainFrame().evaluateJavaScript(js);
}
}
// If a user presses tab from within a table
public void setTableCursorPositionTab(int currentRow, int currentCol, int tableRows, int tableColumns) {
if (tableRows == currentRow && currentCol == tableColumns) {
insertTableRow();
}
KeyboardModifiers modifiers = new KeyboardModifiers(KeyboardModifier.NoModifier);
QKeyEvent right = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Right.value(), modifiers);
QKeyEvent end = new QKeyEvent(Type.KeyPress, Qt.Key.Key_End.value(), modifiers);
QKeyEvent end2 = new QKeyEvent(Type.KeyPress, Qt.Key.Key_End.value(), modifiers);
getBrowser().focusWidget();
QCoreApplication.postEvent(getBrowser(), end);
QCoreApplication.postEvent(getBrowser(), right);
QCoreApplication.postEvent(getBrowser(), end2);
}
public void backtabPressed() {
if (insideEncryption)
return;
if (insideList)
outdentClicked();
if (insideTable) {
String js = new String( "function getCursorPosition() { "
+" var selObj = window.getSelection();"
+" var selRange = selObj.getRangeAt(0);"
+" var workingNode = window.getSelection().anchorNode;"
+" var rowCount = 0;"
+" var colCount = 0;"
+" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
+" if (workingNode.nodeName.toLowerCase()=='tr') {"
+" rowCount = rowCount+1;"
+" }"
+" if (workingNode.nodeName.toLowerCase() == 'td') {"
+" colCount = colCount+1;"
+" }"
+" if (workingNode.previousSibling != null)"
+" workingNode = workingNode.previousSibling;"
+" else "
+" workingNode = workingNode.parentNode;"
+" }"
+" var nodes = workingNode.getElementsByTagName('tr');"
+" var tableRows = nodes.length;"
+" nodes = nodes[0].getElementsByTagName('td');"
+" var tableColumns = nodes.length;"
+" window.jambi.setTableCursorPositionBackTab(rowCount, colCount, tableRows, tableColumns);"
+"} getCursorPosition();");
browser.page().mainFrame().evaluateJavaScript(js);
}
}
// If a user presses backtab from within a table
public void setTableCursorPositionBackTab(int currentRow, int currentCol, int tableRows, int tableColumns) {
if (currentRow == 1 && currentCol == 1) {
return;
}
KeyboardModifiers modifiers = new KeyboardModifiers(KeyboardModifier.NoModifier);
QKeyEvent left = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Left.value(), modifiers);
QKeyEvent home = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Home.value(), modifiers);
getBrowser().focusWidget();
QCoreApplication.postEvent(getBrowser(), home);
QCoreApplication.postEvent(getBrowser(), left);
}
public void setInsideList() {
insideList = true;
}
// The title has been edited
@SuppressWarnings("unused")
private void titleEdited() {
// If we don't have a good note, or if the current title
// matches the old title then we don't need to do anything
if (currentNote == null)
return;
if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))
return;
// If we have a real change, we need to save it.
String text = titleLabel.text().trim();
if (text.equals(""))
text = tr("Untitled Note");
noteSignal.titleChanged.emit(currentNote.getGuid(), text);
currentNote.setTitle(text);
saveNoteTitle = text;
checkNoteTitle();
}
// Set the list of note tags
public void setAllTags(List<Tag> l) {
allTags = l;
tagEdit.setTagList(l);
}
// Setter for the current tags
public void setCurrentTags(List<String> s) {
currentTags = s;
}
// Save the list of notebooks
public void setNotebookList(List<Notebook> n) {
notebookList = n;
loadNotebookList();
}
// Load the notebook list and select the current notebook
private void loadNotebookList() {
if (notebookBox.count() != 0)
notebookBox.clear();
if (notebookList == null)
return;
for (int i = 0; i < notebookList.size(); i++) {
notebookBox.addItem(notebookList.get(i).getName());
if (currentNote != null) {
if (currentNote.getNotebookGuid().equals(
notebookList.get(i).getGuid())) {
notebookBox.setCurrentIndex(i);
}
}
}
}
// Set the notebook for a note
public void setNotebook(String notebook) {
currentNote.setNotebookGuid(notebook);
loadNotebookList();
}
// Get the contents of the editor
public String getContent() {
return browser.page().currentFrame().toHtml();
}
// The note contents have changed
public void contentChanged() {
String content = getContent();
// This puts in a 1/2 second delay
// before updating the source editor.
// It improves response when someone is doing
// frequent updates on a large note.
// If the source editor isn't visible, then there
// is no point to doing any of this.
if (sourceEdit.isVisible()) {
setSourceTimer.stop();
setSourceTimer.setInterval(500);
setSourceTimer.setSingleShot(true);
setSourceTimer.start();
}
checkNoteTitle();
noteSignal.noteChanged.emit(currentNote.getGuid(), content);
}
// The notebook selection has changed
@SuppressWarnings("unused")
private void notebookChanged() {
boolean changed = false;
String n = notebookBox.currentText();
for (int i = 0; i < notebookList.size(); i++) {
if (n.equals(notebookList.get(i).getName())) {
if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {
String guid = conn.getNotebookTable().findNotebookByName(n);
if (conn.getNotebookTable().isLinked(guid)) {
tagEdit.setText("");
noteSignal.tagsChanged.emit(currentNote.getGuid(), new ArrayList<String>());
FilterEditorTags t = new FilterEditorTags(conn, logger);
setAllTags(t.getValidTags(currentNote));
}
currentNote.setNotebookGuid(notebookList.get(i).getGuid());
changed = true;
}
i = notebookList.size();
}
}
// If the notebook changed, signal the update
if (changed)
noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote
.getNotebookGuid());
}
// Check the note title
private void checkNoteTitle() {
String text = browser.page().currentFrame().toPlainText();
if (saveNoteTitle == null)
saveNoteTitle = new String();
text = text.trim();
if (!saveNoteTitle.trim().equals("") && !saveNoteTitle.trim().equals("Untitled Note"))
text = saveNoteTitle.trim();
int newLine = text.indexOf("\n");
if (newLine > 0)
text = text.substring(0,newLine);
if (saveNoteTitle.trim().equals("") || saveNoteTitle.trim().equals("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);
}
}
if (currentNote != null && titleLabel != null && !currentNote.getTitle().equals(text))
noteSignal.titleChanged.emit(currentNote.getGuid(), text);
}
// Return the note contents so we can email them
public String getContentsToEmail() {
return browser.page().currentFrame().toPlainText().trim();
/*
* int body = browser.page().currentFrame().toHtml().indexOf("<body>");
* String temp = browser.page().currentFrame().toHtml(); if (body == -1)
* temp = "<html><body><b>Test</b></body></html>"; else temp =
* "<html>"+temp.substring(body); return temp; // return
* urlEncode(browser.page().currentFrame().toHtml());
*/
}
// Insert an image into the editor
private void insertImage(QMimeData mime) {
logger.log(logger.EXTREME, "Entering insertImage");
QImage img = (QImage) mime.imageData();
String script_start = new String(
"document.execCommand('insertHTML', false, '");
String script_end = new String("');");
long now = new Date().getTime();
String path = Global.getFileManager().getResDirPath(
(new Long(now).toString()) + ".jpg");
// This block is just a hack to make sure we wait at least 1ms so we
// don't
// have collisions on image names
long i = new Date().getTime();
while (now == i)
i = new Date().getTime();
// Open the file & write the data
QFile tfile = new QFile(path);
tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
if (!img.save(tfile)) {
tfile.close();
return;
}
tfile.close();
Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);
if (newRes == null)
return;
currentNote.getResources().add(newRes);
// do the actual insert into the note
StringBuffer buffer = new StringBuffer(100);
buffer.append("<img src=\"");
buffer.append(tfile.fileName());
buffer.append("\" en-tag=en-media type=\"image/jpeg\""
+" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
+" guid=\"" +newRes.getGuid() +"\""
+" onContextMenu=\"window.jambi.imageContextMenu(&." +tfile.fileName() +"&.);\""
+ " />");
browser.page().mainFrame().evaluateJavaScript(
script_start + buffer + script_end);
return;
}
// Handle pasting of a note-to-note link
private void handleNoteLink(QMimeData mime) {
for (int i=0; i<mime.urls().size(); i++) {
StringTokenizer tokens = new StringTokenizer(mime.urls().get(i).toString().replace("evernote:///view/", ""), "/");
tokens.nextToken();
tokens.nextToken();
String sid = tokens.nextToken();
String lid = tokens.nextToken();
if (!sid.equals(currentNote.getGuid()) && !lid.equals(currentNote.getGuid())) {
Note note = conn.getNoteTable().getNote(sid, false, false, false, false, false);
if (note == null)
note = conn.getNoteTable().getNote(lid, false, false, false, false, false);
if (note == null)
return;
// If we've gotten this far, we have a bunch of values. We need to build the link.
StringBuffer url = new StringBuffer(100);
String script_start = new String(
"document.execCommand('insertHtml', false, '");
String script_end = new String("');");
url.append("<a href=\""+mime.urls().get(i).toString() +"\" style=\"color:#69aa35\">");
url.append(note.getTitle());
url.append("</a>");
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");
FileNameMap fileNameMap = URLConnection.getFileNameMap();
List<QUrl> urlList = mime.urls();
String url = new String();
String script_start = new String(
"document.execCommand('createLink', false, '");
String script_end = new String("');");
for (int i = 0; i < urlList.size(); i++) {
url = urlList.get(i).toString();
// Find out what type of file we have
String mimeType = fileNameMap.getContentTypeFor(url);
// If null returned, we need to guess at the file type
if (mimeType == null)
mimeType = "application/"
+ url.substring(url.lastIndexOf(".") + 1);
// Check if we have an image or some other type of file
if (url.substring(0, 5).equalsIgnoreCase("file:")
&& mimeType.substring(0, 5).equalsIgnoreCase("image")) {
handleLocalImageURLPaste(mime, mimeType);
return;
}
boolean smallEnough = checkFileAttachmentSize(url);
if (smallEnough
&& url.substring(0, 5).equalsIgnoreCase("file:")
&& !mimeType.substring(0, 5).equalsIgnoreCase("image")) {
handleLocalAttachment(mime, mimeType);
return;
}
browser.page().mainFrame().evaluateJavaScript(
script_start + url + script_end);
}
return;
}
// If a URL being pasted is an image URL, then attach the image
private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {
List<QUrl> urlList = mime.urls();
String url = new String();
String script_start_image = new String(
"document.execCommand('insertHtml', false, '");
String script_end = new String("');");
StringBuffer buffer;
// Copy the image over into the resource directory and create a new resource
// record for each url pasted
for (int i = 0; i < urlList.size(); i++) {
url = urlList.get(i).toString();
Resource newRes = createResource(url, i, mimeType, false);
if (newRes == null)
return;
currentNote.getResources().add(newRes);
buffer = new StringBuffer(100);
// Open the file & write the data
String fileName = Global.getFileManager().getResDirPath(newRes.getGuid());
QFile tfile = new QFile(fileName);
tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
tfile.write(newRes.getData().getBody());
tfile.close();
buffer.append(script_start_image);
buffer.append("<img src=\"" + FileUtils.toForwardSlashedPath(fileName));
// if (mimeType.equalsIgnoreCase("image/jpg"))
// mimeType = "image/jpeg";
buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""
+" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
+" guid=\"" +newRes.getGuid() +"\""
+" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
+ " />");
buffer.append(script_end);
browser.page().mainFrame().evaluateJavaScript(buffer.toString());
}
return;
}
// If a URL being pasted is a local file URL, then attach the file
private void handleLocalAttachment(QMimeData mime, String mimeType) {
logger.log(logger.EXTREME, "Attaching local file");
List<QUrl> urlList = mime.urls();
String script_start = new String(
"document.execCommand('insertHtml', false, '");
String script_end = new String("');");
StringBuffer buffer;
String[] type = mimeType.split("/");
String icon = findIcon(type[1]);
if (icon.equals("attachment.png"))
icon = findIcon(type[0]);
buffer = new StringBuffer(100);
for (int i = 0; i < urlList.size(); i++) {
String url = urlList.get(i).toString();
// Start building the HTML
if (icon.equals("attachment.png"))
icon = findIcon(url.substring(url.lastIndexOf(".")+1));
String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));
logger.log(logger.EXTREME, "Creating resource ");
Resource newRes = createResource(url, i, mimeType, true);
if (newRes == null)
return;
logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());
currentNote.getResources().add(newRes);
String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();
// If we have a PDF, we need to setup the preview.
if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {
logger.log(logger.EXTREME, "Setting up PDF preview");
if (newRes.getAttributes() != null &&
newRes.getAttributes().getFileName() != null &&
!newRes.getAttributes().getFileName().trim().equals(""))
fileName = newRes.getGuid()+Global.attachmentNameDelimeter+
newRes.getAttributes().getFileName();
else
fileName = newRes.getGuid()+".pdf";
QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
QFile.OpenMode mode = new QFile.OpenMode();
mode.set(QFile.OpenModeFlag.WriteOnly);
file.open(mode);
QDataStream out = new QDataStream(file);
// Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);
QByteArray binData = new QByteArray(newRes.getData().getBody());
// resBinary = null;
out.writeBytes(binData.toByteArray());
file.close();
PDFPreview pdfPreview = new PDFPreview();
if (pdfPreview.setupPreview(Global.getFileManager().getResDirPath(fileName), "pdf",0)) {
imageURL = file.fileName() + ".png";
}
}
logger.log(logger.EXTREME, "Generating link tags");
buffer.delete(0, buffer.length());
buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");
buffer.append(" onContextMenu=\"window.jambi.imageContextMenu('")
.append(Global.getFileManager().getResDirPath(fileName))
.append("');\" ");
buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");
buffer.append("<img src=\"" + imageURL + "\" title=\"" +newRes.getAttributes().getFileName());
buffer.append("\"></img>");
buffer.append("</a>");
browser.page().mainFrame().evaluateJavaScript(
script_start + buffer.toString() + script_end);
}
return;
}
private Resource createResource(String url, int sequence, String mime, boolean attachment) {
logger.log(logger.EXTREME, "Inside create resource");
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);
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();
Resource r = new Resource();
Calendar time = new GregorianCalendar();
long prevTime = time.getTimeInMillis();
while (prevTime == time.getTimeInMillis()) {
time = new GregorianCalendar();
}
r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());
r.setNoteGuid(currentNote.getGuid());
r.setMime(mime);
r.setActive(true);
r.setUpdateSequenceNum(0);
r.setWidth((short) 0);
r.setHeight((short) 0);
r.setDuration((short) 0);
Data d = new Data();
d.setBody(fileData);
d.setBodyIsSet(true);
d.setBodyHash(hash);
d.setBodyHashIsSet(true);
r.setData(d);
d.setSize(fileData.length);
int fileNamePos = url.lastIndexOf(File.separator);
if (fileNamePos == -1)
fileNamePos = url.lastIndexOf("/");
String fileName = url.substring(fileNamePos+1);
ResourceAttributes a = new ResourceAttributes();
a.setAltitude(0);
a.setAltitudeIsSet(false);
a.setLongitude(0);
a.setLongitudeIsSet(false);
a.setLatitude(0);
a.setLatitudeIsSet(false);
a.setCameraMake("");
a.setCameraMakeIsSet(false);
a.setCameraModel("");
a.setCameraModelIsSet(false);
a.setAttachment(attachment);
a.setAttachmentIsSet(true);
a.setClientWillIndex(false);
a.setClientWillIndexIsSet(true);
a.setRecoType("");
a.setRecoTypeIsSet(false);
a.setSourceURL(url);
a.setSourceURLIsSet(true);
a.setTimestamp(0);
a.setTimestampIsSet(false);
a.setFileName(fileName);
a.setFileNameIsSet(true);
r.setAttributes(a);
conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
logger.log(logger.EXTREME, "Resource created");
return r;
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
}
return null;
}
// find the appropriate icon for an attachment
private String findIcon(String appl) {
appl = appl.toLowerCase();
File f = Global.getFileManager().getImageDirFile(appl + ".png");
if (f.exists())
return appl+".png";
return "attachment.png";
}
// Check the file attachment to be sure it isn't over 25 mb
private boolean checkFileAttachmentSize(String url) {
String fileName = url.substring(8);
QFile resourceFile = new QFile(fileName);
resourceFile.open(new QIODevice.OpenMode(
QIODevice.OpenModeFlag.ReadOnly));
long size = resourceFile.size();
resourceFile.close();
size = size / 1024 / 1024;
if (size < 50 && Global.isPremium())
return true;
if (size < 25)
return true;
String error = tr("A file attachment may not exceed 25MB.");
QMessageBox.information(this, tr("Attachment Size"), error);
return false;
}
@SuppressWarnings("unused")
private void createdChanged() {
QDateTime dt = new QDateTime();
dt.setDate(createdDate.date());
dt.setTime(createdTime.time());
noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);
}
@SuppressWarnings("unused")
private void alteredChanged() {
QDateTime dt = new QDateTime();
dt.setDate(alteredDate.date());
dt.setTime(alteredTime.time());
noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);
}
@SuppressWarnings("unused")
private void subjectDateTimeChanged() {
QDateTime dt = new QDateTime();
dt.setDate(subjectDate.date());
dt.setTime(subjectTime.time());
noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);
}
@SuppressWarnings("unused")
private void sourceUrlChanged() {
noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());
}
@SuppressWarnings("unused")
private void authorChanged() {
noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());
}
@SuppressWarnings("unused")
private void geoBoxChanged() {
int index = geoBox.currentIndex();
geoBox.setCurrentIndex(0);
if (index == 1) {
GeoDialog box = new GeoDialog();
box.setLongitude(currentNote.getAttributes().getLongitude());
box.setLatitude(currentNote.getAttributes().getLatitude());
box.setAltitude(currentNote.getAttributes().getAltitude());
box.exec();
if (!box.okPressed())
return;
double alt = box.getAltitude();
double lat = box.getLatitude();
double lon = box.getLongitude();
if (alt != currentNote.getAttributes().getAltitude() ||
lon != currentNote.getAttributes().getLongitude() ||
lat != currentNote.getAttributes().getLatitude()) {
noteSignal.geoChanged.emit(currentNote.getGuid(), lon, lat, alt);
currentNote.getAttributes().setAltitude(alt);
currentNote.getAttributes().setLongitude(lon);
currentNote.getAttributes().setLatitude(lat);
}
}
if (index == 2) {
noteSignal.geoChanged.emit(currentNote.getGuid(), 0.0, 0.0, 0.0);
currentNote.getAttributes().setAltitude(0.0);
currentNote.getAttributes().setLongitude(0.0);
currentNote.getAttributes().setLatitude(0.0);
}
if (index == 3 || index == 0) {
QDesktopServices.openUrl(new QUrl("http://maps.google.com/maps?z=6&q="+currentNote.getAttributes().getLatitude() +"," +currentNote.getAttributes().getLongitude()));
}
}
// ************************************************************
// * User chose to save an attachment. Pares out the request *
// * into a guid & file. Save the result. *
// ************************************************************
public void downloadAttachment(QNetworkRequest request) {
String guid;
QFileDialog fd = new QFileDialog(this);
fd.setFileMode(FileMode.AnyFile);
fd.setConfirmOverwrite(true);
fd.setWindowTitle(tr("Save File"));
fd.setAcceptMode(AcceptMode.AcceptSave);
fd.setDirectory(System.getProperty("user.home"));
String name = request.url().toString();
int pos = name.lastIndexOf(Global.attachmentNameDelimeter);
if (pos > -1) {
guid = name.substring(0, pos).replace("nnres://", "");
name = name.substring(pos +Global.attachmentNameDelimeter.length());
fd.selectFile(name);
pos = name.lastIndexOf('.');
if (pos > -1) {
String mimeType = "(*." + name.substring(pos + 1)
+ ");; All Files (*)";
fd.setFilter(tr(mimeType));
}
} else {
guid = name;
}
// Strip URL prefix and base dir
guid = guid.replace("nnres://", "")
.replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
guid = guid.replace("file://", "").replace("/", "")
.replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
pos = guid.lastIndexOf('.');
if (pos > 0)
guid = guid.substring(0,pos);
if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
name = name.replace('\\', '/');
Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
QFile saveFile = new QFile(fd.selectedFiles().get(0));
QFile.OpenMode mode = new QFile.OpenMode();
mode.set(QFile.OpenModeFlag.WriteOnly);
saveFile.open(mode);
QDataStream saveOut = new QDataStream(saveFile);
QByteArray binData = new QByteArray(resBinary.getData().getBody());
saveOut.writeBytes(binData.toByteArray());
saveFile.close();
}
}
// ************************************************************
// * User chose to save an attachment. Pares out the request *
// * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!
// ************************************************************
public void downloadImage(QNetworkRequest request) {
QFileDialog fd = new QFileDialog(this);
fd.setFileMode(FileMode.AnyFile);
fd.setConfirmOverwrite(true);
fd.setWindowTitle(tr("Save File"));
fd.setAcceptMode(AcceptMode.AcceptSave);
fd.setDirectory(System.getProperty("user.home"));
String name = request.url().toString();
name = name.replace("nnres://", "");
String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
name = name.replace(dPath, "");
int pos = name.lastIndexOf('.');
String guid = name;
if (pos > -1) {
String mimeType = "(*." + name.substring(pos + 1)
+ ");; All Files (*)";
fd.setFilter(tr(mimeType));
guid = guid.substring(0,pos);
}
pos = name.lastIndexOf(Global.attachmentNameDelimeter);
if (pos > -1) {
guid = name.substring(0, pos);
fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));
}
if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
String fileName = fd.selectedFiles().get(0);
QFile saveFile = new QFile(fileName);
QFile.OpenMode mode = new QFile.OpenMode();
mode.set(QFile.OpenModeFlag.WriteOnly);
saveFile.open(mode);
QDataStream saveOut = new QDataStream(saveFile);
QByteArray binData = new QByteArray(resBinary.getData().getBody());
saveOut.writeBytes(binData.toByteArray());
saveFile.close();
}
}
// *************************************************************
// * decrypt any hidden text. We could do an XML parse, but
// * it is quicker here just to scan for an <img tag & do the fix
// * the manual way
// *************************************************************
private void removeEncryption(String id, String plainText, boolean permanent, String slot) {
if (!permanent) {
plainText = " <table class=\"en-crypt-temp\" slot=\""
+slot
+"\""
+"border=1 width=100%><tbody><tr><td>"
+plainText+"</td></tr></tbody></table>";
}
String html = browser.page().mainFrame().toHtml();
String text = html;
int imagePos = html.indexOf("<img");
int endPos;
for ( ;imagePos>0; ) {
// Find the end tag
endPos = text.indexOf(">", imagePos);
String tag = text.substring(imagePos-1,endPos);
if (tag.indexOf("id=\""+id+"\"") > -1) {
text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);
QTextCodec codec = QTextCodec.codecForName("UTF-8");
QByteArray unicode = codec.fromUnicode(text);
setContent(unicode);
if (permanent)
contentChanged();
}
imagePos = text.indexOf("<img", imagePos+1);
}
}
//****************************************************************
//* Focus shortcuts
//****************************************************************
@SuppressWarnings("unused")
private void focusTitle() {
titleLabel.setFocus();
}
@SuppressWarnings("unused")
private void focusTag() {
tagEdit.setFocus();
}
@SuppressWarnings("unused")
private void focusNote() {
browser.setFocus();
}
@SuppressWarnings("unused")
private void focusAuthor() {
authorLabel.setFocus();
}
@SuppressWarnings("unused")
private void focusUrl() {
urlLabel.setFocus();
}
//*****************************************************************
//* Set the document background color
//*****************************************************************
public void setBackgroundColor(String color) {
String js = "function changeBackground(color) {"
+"document.body.style.background = color;"
+"}"
+"changeBackground('" +color+"');";
browser.page().mainFrame().evaluateJavaScript(js);
contentChanged();
}
//****************************************************************
//* MicroFocus changed
//****************************************************************
private void microFocusChanged() {
boldButton.setDown(false);
italicButton.setDown(false);
underlineButton.setDown(false);
browser.openAction.setEnabled(false);
browser.downloadAttachment.setEnabled(false);
browser.downloadImage.setEnabled(false);
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() {"
+"var cursorPos;"
+"if (window.getSelection) {"
+" var selObj = window.getSelection();"
+" var selRange = selObj.getRangeAt(0);"
+" 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.insideEncryption(); }"
+" if (workingNode.nodeName=='B') window.jambi.boldActive();"
+" if (workingNode.nodeName=='I') window.jambi.italicActive();"
+" if (workingNode.nodeName=='U') window.jambi.underlineActive();"
+" if (workingNode.nodeName=='UL') window.jambi.setInsideList();"
+" if (workingNode.nodeName=='OL') window.jambi.setInsideList();"
+" if (workingNode.nodeName=='LI') window.jambi.setInsideList();"
+" if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"
+" if (workingNode.nodeName=='A') {for(var x = 0; x < workingNode.attributes.length; x++ ) {if (workingNode.attributes[x].nodeName.toLowerCase() == 'href') window.jambi.setInsideLink(workingNode.attributes[x].nodeValue);}}"
+" if (workingNode.nodeName=='SPAN') {"
+" if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"
+" }"
+" workingNode = workingNode.parentNode;"
+" }"
+"}"
+"} getCursorPos();");
browser.page().mainFrame().evaluateJavaScript(js);
}
public void printNode(String n) {
System.out.println("Node Vaule: " +n);
}
public void insideEncryption() {
insideEncryption = true;
forceTextPaste();
}
//****************************************************************
//* Insert a table row
//****************************************************************
public void insertTableRow() {
String js = new String( "function insertTableRow() {"
+" var selObj = window.getSelection();"
+" var selRange = selObj.getRangeAt(0);"
+" var workingNode = window.getSelection().anchorNode.parentNode;"
+" var cellCount = 0;"
+" while(workingNode != null) { "
+" if (workingNode.nodeName.toLowerCase()=='tr') {"
+" row = document.createElement('TR');"
+" var nodes = workingNode.getElementsByTagName('td');"
+" for (j=0; j<nodes.length; j=j+1) {"
+" cell = document.createElement('TD');"
+" cell.innerHTML=' ';"
+" row.appendChild(cell);"
+" }"
+" workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"
+" return;"
+" }"
+" workingNode = workingNode.parentNode;"
+" }"
+"} insertTableRow();");
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<workingNode.rows.length; i++) { "
+" var cell = workingNode.rows[i].insertCell(current+1); "
+" cell.innerHTML = ' '; "
+" }"
+"} insertTableColumn();");
browser.page().mainFrame().evaluateJavaScript(js);
contentChanged();
}
//****************************************************************
//* Delete a table row
//****************************************************************
public void deleteTableRow() {
String js = new String( "function deleteTableRow() {"
+" var selObj = window.getSelection();"
+" var selRange = selObj.getRangeAt(0);"
+" var workingNode = window.getSelection().anchorNode.parentNode;"
+" var cellCount = 0;"
+" while(workingNode != null) { "
+" if (workingNode.nodeName.toLowerCase()=='tr') {"
+" workingNode.parentNode.removeChild(workingNode);"
+" return;"
+" }"
+" workingNode = workingNode.parentNode;"
+" }"
+"} deleteTableRow();");
browser.page().mainFrame().evaluateJavaScript(js);
contentChanged();
}
public void deleteTableColumn() {
String js = new String( "function deleteTableColumn() {"
+" 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<workingNode.rows.length; i++) { "
+" workingNode.rows[i].deleteCell(current); "
+" }"
+"} deleteTableColumn();");
browser.page().mainFrame().evaluateJavaScript(js);
contentChanged();
}
public void setInsideTable() {
browser.insertTableRowAction.setEnabled(true);
browser.insertTableColumnAction.setEnabled(true);
browser.deleteTableRowAction.setEnabled(true);
browser.deleteTableColumnAction.setEnabled(true);
browser.insertTableAction.setEnabled(false);
browser.encryptAction.setEnabled(false);
insideTable = true;
}
public void setInsideLink(String link) {
browser.insertLinkAction.setText(tr("Edit Hyperlink"));
currentHyperlink = link;
insertHyperlink = false;
}
public void italicActive() {
italicButton.setDown(true);
}
public void boldActive() {
boldButton.setDown(true);
}
public void underlineActive() {
underlineButton.setDown(true);
}
public void forceTextPaste() {
forceTextPaste = true;
}
public void imageContextMenu(String f) {
browser.downloadImage.setEnabled(true);
browser.rotateImageRight.setEnabled(true);
browser.rotateImageLeft.setEnabled(true);
browser.openAction.setEnabled(true);
selectedFile = f;
}
public void rotateImageRight() {
QWebSettings.setMaximumPagesInCache(0);
QWebSettings.setObjectCacheCapacities(0, 0, 0);
QImage image = new QImage(selectedFile);
QMatrix matrix = new QMatrix();
matrix.rotate( 90.0 );
image = image.transformed(matrix);
image.save(selectedFile);
QWebSettings.setMaximumPagesInCache(0);
QWebSettings.setObjectCacheCapacities(0, 0, 0);
browser.setHtml(browser.page().mainFrame().toHtml());
browser.reload();
contentChanged();
resourceSignal.contentChanged.emit(selectedFile);
}
public void rotateImageLeft() {
QImage image = new QImage(selectedFile);
QMatrix matrix = new QMatrix();
matrix.rotate( -90.0 );
image = image.transformed(matrix);
image.save(selectedFile);
browser.setHtml(browser.page().mainFrame().toHtml());
browser.reload();
contentChanged();
resourceSignal.contentChanged.emit(selectedFile);
}
public void resourceContextMenu(String f) {
browser.downloadAttachment.setEnabled(true);
browser.openAction.setEnabled(true);
selectedFile = f;
}
public void latexContextMenu(String f) {
browser.downloadImage.setEnabled(true);
browser.rotateImageRight.setEnabled(true);
browser.rotateImageLeft.setEnabled(true);
browser.openAction.setEnabled(true);
selectedFile = f;
}
//****************************************************************
//* Apply CSS style to specified word
//****************************************************************
/* public void applyStyleToWords(String word, String style) {
QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");
script.open(OpenModeFlag.ReadOnly);
String s = script.readAll().toString();
String js = new String(s +" findit('"+word+"', '"+style+"');");
browser.page().mainFrame().evaluateJavaScript(js);
System.out.println(getContent());
}
*/
//****************************************************************
//* Someone tried to paste a resource between notes, so we need *
//* to do some special handling. *
//****************************************************************
private String fixInternotePaste(String text) {
logger.log(logger.EXTREME, "Fixing internote paste");
String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");
return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");
}
private String fixInternotePasteSearch(String text, String type, String locTag) {
// First, let's fix the images.
int startPos = text.indexOf(type);
int endPos;
for (; startPos>=0;) {
endPos = text.indexOf(">", startPos+1);
String segment = text.substring(startPos, endPos);
if (segment.indexOf("en-tag") > -1) {
String newSegment = segment;
int guidStartPos = segment.indexOf("guid=\"");
int guidEndPos = segment.indexOf("\"", guidStartPos+7);
String guid = segment.substring(guidStartPos+6,guidEndPos);
int mimeStartPos = segment.indexOf("type");
int mimeEndPos = segment.indexOf("\"", mimeStartPos+7);
String mime = segment.substring(mimeStartPos+6,mimeEndPos);
int srcStartPos = segment.indexOf("src");
int srcEndPos = segment.indexOf("\"", srcStartPos+6);
String src = segment.substring(srcStartPos+5,srcEndPos);
Calendar currentTime = new GregorianCalendar();
Long l = new Long(currentTime.getTimeInMillis());
long prevTime = l;
while (l==prevTime) {
currentTime = new GregorianCalendar();
l= new Long(currentTime.getTimeInMillis());
}
Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
// if r==null, then the image doesn't exist (it was probably cut out of another note, so
// we need to recereate it
if (r==null) {
r = createResource(src, 1, mime, false);
if (r==null)
return "";
}
String randint = new String(Long.toString(l));
String extension = null;
if (r.getMime()!= null) {
extension = r.getMime().toLowerCase();
if (extension.indexOf("/")>-1)
extension = extension.substring(extension.indexOf("/")+1);
}
String newFile = randint;
if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")
if (!locTag.startsWith("src"))
newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();
r.setNoteGuid(currentNote.getGuid());
r.setGuid(randint);
conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
QFile f = new QFile(Global.getFileManager().getResDirPath(newFile));
QByteArray bin = new QByteArray(r.getData().getBody());
f.open(QFile.OpenModeFlag.WriteOnly);
f.write(bin);
f.close();
newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);
currentNote.getResources().add(r);
int startSrcPos = newSegment.indexOf(locTag);
int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);
String source;
if (locTag.startsWith("src")) {
source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
newSegment = newSegment.replace(source,
FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath(newFile)));
} else {
source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
newSegment = newSegment.replace(source, newFile);
}
text = text.substring(0,startPos) + newSegment + text.substring(endPos);
}
startPos = text.indexOf(type, startPos+1);
}
return text;
}
public void nextPage(String file) {
logger.log(logger.EXTREME, "Starting nextPage()");
Integer pageNumber;
if (previewPageList.containsKey(file))
pageNumber = previewPageList.get(file)+1;
else
pageNumber = 2;
previewPageList.remove(file);
previewPageList.put(file, pageNumber);
PDFPreview pdfPreview = new PDFPreview();
boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
if (goodPreview) {
// String html = getContent();
QWebSettings.setMaximumPagesInCache(0);
QWebSettings.setObjectCacheCapacities(0, 0, 0);
// browser.setContent(new QByteArray());
browser.setHtml(browser.page().mainFrame().toHtml());
browser.reload();
// browser.setContent(new QByteArray(html));
// browser.triggerPageAction(WebAction.Reload);
// pdfMouseOver(selectedFile);
}
}
public void previousPage(String file) {
logger.log(logger.EXTREME, "Starting previousPage()");
Integer pageNumber;
if (previewPageList.containsKey(file))
pageNumber = previewPageList.get(file)-1;
else
pageNumber = 1;
previewPageList.remove(file);
previewPageList.put(file, pageNumber);
PDFPreview pdfPreview = new PDFPreview();
boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
if (goodPreview) {
// String html = getContent();
QWebSettings.setMaximumPagesInCache(0);
QWebSettings.setObjectCacheCapacities(0, 0, 0);
browser.setHtml(browser.page().mainFrame().toHtml());
browser.reload();
// browser.setContent(new QByteArray(html));
// browser.triggerPageAction(WebAction.Reload);
}
}
/* public void pdfMouseOver(String name) {
int pageNumber;
if (previewPageList.containsKey(selectedFile))
pageNumber = previewPageList.get(selectedFile)+1;
else
pageNumber = 1;
if (pageNumber <= 1)
browser.previousPageAction.setEnabled(false);
else
browser.previousPageAction.setEnabled(true);
PDFPreview pdf = new PDFPreview();
int totalPages = pdf.getPageCount(name);
if (previewPageList.containsKey(selectedFile))
pageNumber = previewPageList.get(selectedFile)+1;
else
pageNumber = 1;
if (totalPages > pageNumber)
browser.nextPageAction.setEnabled(true);
else
browser.nextPageAction.setEnabled(false);
}
public void pdfMouseOut() {
// browser.nextPageAction.setVisible(false);
// browser.previousPageAction.setVisible(false);
}
*/
@SuppressWarnings("unused")
private void toggleUndoVisible(Boolean toggle) {
undoAction.setVisible(toggle);
Global.saveEditorButtonsVisible("undo", toggle);
}
@SuppressWarnings("unused")
private void toggleRedoVisible(Boolean toggle) {
redoAction.setVisible(toggle);
Global.saveEditorButtonsVisible("redo", toggle);
}
@SuppressWarnings("unused")
private void toggleCutVisible(Boolean toggle) {
cutAction.setVisible(toggle);
Global.saveEditorButtonsVisible("cut", toggle);
}
@SuppressWarnings("unused")
private void toggleCopyVisible(Boolean toggle) {
copyAction.setVisible(toggle);
Global.saveEditorButtonsVisible("copy", toggle);
}
@SuppressWarnings("unused")
private void togglePasteVisible(Boolean toggle) {
pasteAction.setVisible(toggle);
Global.saveEditorButtonsVisible("paste", toggle);
}
@SuppressWarnings("unused")
private void toggleBoldVisible(Boolean toggle) {
boldAction.setVisible(toggle);
Global.saveEditorButtonsVisible("bold", toggle);
}
@SuppressWarnings("unused")
private void toggleItalicVisible(Boolean toggle) {
italicAction.setVisible(toggle);
Global.saveEditorButtonsVisible("italic", toggle);
}
@SuppressWarnings("unused")
private void toggleUnderlineVisible(Boolean toggle) {
underlineAction.setVisible(toggle);
Global.saveEditorButtonsVisible("underline", toggle);
}
@SuppressWarnings("unused")
private void toggleStrikethroughVisible(Boolean toggle) {
strikethroughAction.setVisible(toggle);
Global.saveEditorButtonsVisible("strikethrough", toggle);
}
@SuppressWarnings("unused")
private void toggleLeftAlignVisible(Boolean toggle) {
leftAlignAction.setVisible(toggle);
Global.saveEditorButtonsVisible("alignLeft", toggle);
}
@SuppressWarnings("unused")
private void toggleRightAlignVisible(Boolean toggle) {
rightAlignAction.setVisible(toggle);
Global.saveEditorButtonsVisible("alignRight", toggle);
}
@SuppressWarnings("unused")
private void toggleCenterAlignVisible(Boolean toggle) {
centerAlignAction.setVisible(toggle);
Global.saveEditorButtonsVisible("alignCenter", toggle);
}
@SuppressWarnings("unused")
private void toggleHLineVisible(Boolean toggle) {
hlineAction.setVisible(toggle);
Global.saveEditorButtonsVisible("hline", toggle);
}
@SuppressWarnings("unused")
private void toggleIndentVisible(Boolean toggle) {
indentAction.setVisible(toggle);
Global.saveEditorButtonsVisible("indent", toggle);
}
@SuppressWarnings("unused")
private void toggleTodoVisible(Boolean toggle) {
todoAction.setVisible(toggle);
Global.saveEditorButtonsVisible("todo", toggle);
}
@SuppressWarnings("unused")
private void toggleOutdentVisible(Boolean toggle) {
outdentAction.setVisible(toggle);
Global.saveEditorButtonsVisible("outdent", toggle);
}
@SuppressWarnings("unused")
private void toggleBulletListVisible(Boolean toggle) {
bulletListAction.setVisible(toggle);
Global.saveEditorButtonsVisible("bulletList", toggle);
}
@SuppressWarnings("unused")
private void toggleNumberListVisible(Boolean toggle) {
numberListAction.setVisible(toggle);
Global.saveEditorButtonsVisible("numberList", toggle);
}
@SuppressWarnings("unused")
private void toggleFontListVisible(Boolean toggle) {
fontListAction.setVisible(toggle);
Global.saveEditorButtonsVisible("font", toggle);
}
@SuppressWarnings("unused")
private void toggleFontColorVisible(Boolean toggle) {
fontColorAction.setVisible(toggle);
Global.saveEditorButtonsVisible("fontColor", toggle);
}
@SuppressWarnings("unused")
private void toggleFontSizeVisible(Boolean toggle) {
fontSizeAction.setVisible(toggle);
Global.saveEditorButtonsVisible("fontSize", toggle);
}
@SuppressWarnings("unused")
private void toggleFontHilightVisible(Boolean toggle) {
fontHilightAction.setVisible(toggle);
Global.saveEditorButtonsVisible("fontHilight", toggle);
}
@SuppressWarnings("unused")
private void toggleSpellCheckVisible(Boolean toggle) {
spellCheckAction.setVisible(toggle);
Global.saveEditorButtonsVisible("spellCheck", toggle);
}
private void setupDictionary() {
File wordList = new File(Global.getFileManager().getSpellDirPath()+Locale.getDefault()+".dic");
try {
dictionary = new SpellDictionaryHashMap(wordList);
spellChecker = new SpellChecker(dictionary);
File userWordList;
userWordList = new File(Global.getFileManager().getSpellDirPathUser()+"user.dic");
// Get the local user spell dictionary
try {
userDictionary = new SpellDictionaryHashMap(userWordList);
} catch (FileNotFoundException e) {
userWordList.createNewFile();
userDictionary = new SpellDictionaryHashMap(userWordList);
} catch (IOException e) {
userWordList.createNewFile();
userDictionary = new SpellDictionaryHashMap(userWordList);
}
spellListener = new SuggestionListener(this, spellChecker);
// Add the user dictionary
spellChecker.addSpellCheckListener(spellListener);
spellChecker.setUserDictionary(userDictionary);
} catch (FileNotFoundException e) {
QMessageBox.critical(this, tr("Spell Check Error"),
tr("Dictionary ")+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
tr(".dic was not found."));
} catch (IOException e) {
QMessageBox.critical(this, tr("Spell Check Error"),
tr("Dictionary ")+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
tr(".dic is invalid."));
}
}
// Invoke spell checker dialog
@SuppressWarnings("unused")
private void spellCheckClicked() {
if (spellChecker == null) {
setupDictionary();
}
// Read user settings
spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREDIGITWORDS,
Global.getSpellSetting(Configuration.SPELL_IGNOREDIGITWORDS));
spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREINTERNETADDRESSES,
Global.getSpellSetting(Configuration.SPELL_IGNOREINTERNETADDRESSES));
spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREMIXEDCASE,
Global.getSpellSetting(Configuration.SPELL_IGNOREMIXEDCASE));
spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREUPPERCASE,
Global.getSpellSetting(Configuration.SPELL_IGNOREUPPERCASE));
spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNORESENTENCECAPITALIZATION,
Global.getSpellSetting(Configuration.SPELL_IGNORESENTENCECAPITALIZATION));
spellListener.abortSpellCheck = false;
spellListener.errorsFound = false;
String content = getBrowser().page().mainFrame().toPlainText();
StringWordTokenizer tokenizer = new StringWordTokenizer(content);
if (!tokenizer.hasMoreWords())
return;
getBrowser().page().action(WebAction.MoveToStartOfDocument);
getBrowser().setFocus();
boolean found;
// Move to the start of page
KeyboardModifiers ctrl = new KeyboardModifiers(KeyboardModifier.ControlModifier.value());
QKeyEvent home = new QKeyEvent(Type.KeyPress, Key.Key_Home.value(), ctrl);
browser.keyPressEvent(home);
getBrowser().setFocus();
tokenizer = new StringWordTokenizer(content);
String word;
while(tokenizer.hasMoreWords()) {
word = tokenizer.nextWord();
found = getBrowser().page().findText(word);
if (found && !spellListener.abortSpellCheck) {
spellChecker.checkSpelling(new StringWordTokenizer(word));
getBrowser().setFocus();
}
}
// Go to the end of the document & finish up.
home = new QKeyEvent(Type.KeyPress, Key.Key_End.value(), ctrl);
browser.keyPressEvent(home);
if (!spellListener.errorsFound)
QMessageBox.information(this, tr("Spell Check Complete"),
tr("No Errors Found"));
}
// Source edited
@SuppressWarnings("unused")
private void sourceEdited() {
QTextCodec codec = QTextCodec.codecForLocale();
codec = QTextCodec.codecForName("UTF-8");
String content = codec.fromUnicode(sourceEdit.toHtml()).toString();
content = StringEscapeUtils.unescapeHtml4(removeTags(content));
QByteArray data = new QByteArray(sourceEditHeader+content+"</body></html>");
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("<body");
if (body > 0) {
body = text.indexOf(">",body);
if (body > 0) {
sourceEditHeader =text.substring(0, body+1);
text = text.substring(body+1);
}
}
text = text.replace("</body></html>", "");
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("<body");
for (int i=buffer.length()-1; i>=0; i--) {
if (buffer.charAt(i) == '>')
inTag = true;
if (buffer.charAt(i) == '<')
inTag = false;
if (inTag || buffer.charAt(i) == '<' || i<bodyPosition)
buffer.deleteCharAt(i);
}
return buffer.toString();
}
}