2 * This file is part of NixNote
\r
3 * Copyright 2009 Randy Baumgarte
\r
5 * This file may be licensed under the terms of of the
\r
6 * GNU General Public License Version 2 (the ``GPL'').
\r
8 * Software distributed under the License is distributed
\r
9 * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
\r
10 * express or implied. See the GPL for the specific language
\r
11 * governing rights and limitations.
\r
13 * You should have received a copy of the GPL along with this
\r
14 * program. If not, go to http://www.gnu.org/licenses/gpl.html
\r
15 * or write to the Free Software Foundation, Inc.,
\r
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
\r
20 package cx.fbn.nevernote.gui;
\r
22 import java.io.File;
\r
23 import java.io.FileNotFoundException;
\r
24 import java.io.IOException;
\r
25 import java.net.FileNameMap;
\r
26 import java.net.URI;
\r
27 import java.net.URLConnection;
\r
28 import java.security.MessageDigest;
\r
29 import java.security.NoSuchAlgorithmException;
\r
30 import java.text.SimpleDateFormat;
\r
31 import java.util.ArrayList;
\r
32 import java.util.Calendar;
\r
33 import java.util.Collections;
\r
34 import java.util.Date;
\r
35 import java.util.GregorianCalendar;
\r
36 import java.util.HashMap;
\r
37 import java.util.List;
\r
38 import java.util.Locale;
\r
39 import java.util.StringTokenizer;
\r
41 import org.apache.commons.lang3.StringEscapeUtils;
\r
42 import org.apache.commons.lang3.StringUtils;
\r
44 import com.evernote.edam.limits.Constants;
\r
45 import com.evernote.edam.type.Data;
\r
46 import com.evernote.edam.type.Note;
\r
47 import com.evernote.edam.type.Notebook;
\r
48 import com.evernote.edam.type.Resource;
\r
49 import com.evernote.edam.type.ResourceAttributes;
\r
50 import com.evernote.edam.type.Tag;
\r
51 import com.swabunga.spell.engine.Configuration;
\r
52 import com.swabunga.spell.engine.SpellDictionary;
\r
53 import com.swabunga.spell.engine.SpellDictionaryHashMap;
\r
54 import com.swabunga.spell.engine.Word;
\r
55 import com.swabunga.spell.event.SpellCheckEvent;
\r
56 import com.swabunga.spell.event.SpellCheckListener;
\r
57 import com.swabunga.spell.event.SpellChecker;
\r
58 import com.swabunga.spell.event.StringWordTokenizer;
\r
59 import com.trolltech.qt.core.QByteArray;
\r
60 import com.trolltech.qt.core.QCoreApplication;
\r
61 import com.trolltech.qt.core.QDataStream;
\r
62 import com.trolltech.qt.core.QDateTime;
\r
63 import com.trolltech.qt.core.QEvent;
\r
64 import com.trolltech.qt.core.QEvent.Type;
\r
65 import com.trolltech.qt.core.QFile;
\r
66 import com.trolltech.qt.core.QFileSystemWatcher;
\r
67 import com.trolltech.qt.core.QIODevice;
\r
68 import com.trolltech.qt.core.QMimeData;
\r
69 import com.trolltech.qt.core.QTextCodec;
\r
70 import com.trolltech.qt.core.QTimer;
\r
71 import com.trolltech.qt.core.QUrl;
\r
72 import com.trolltech.qt.core.Qt;
\r
73 import com.trolltech.qt.core.Qt.Key;
\r
74 import com.trolltech.qt.core.Qt.KeyboardModifier;
\r
75 import com.trolltech.qt.core.Qt.KeyboardModifiers;
\r
76 import com.trolltech.qt.gui.QAction;
\r
77 import com.trolltech.qt.gui.QApplication;
\r
78 import com.trolltech.qt.gui.QCalendarWidget;
\r
79 import com.trolltech.qt.gui.QClipboard;
\r
80 import com.trolltech.qt.gui.QClipboard.Mode;
\r
81 import com.trolltech.qt.gui.QColor;
\r
82 import com.trolltech.qt.gui.QComboBox;
\r
83 import com.trolltech.qt.gui.QDateEdit;
\r
84 import com.trolltech.qt.gui.QDesktopServices;
\r
85 import com.trolltech.qt.gui.QFileDialog;
\r
86 import com.trolltech.qt.gui.QFileDialog.AcceptMode;
\r
87 import com.trolltech.qt.gui.QFileDialog.FileMode;
\r
88 import com.trolltech.qt.gui.QFont;
\r
89 import com.trolltech.qt.gui.QFontDatabase;
\r
90 import com.trolltech.qt.gui.QFormLayout;
\r
91 import com.trolltech.qt.gui.QGridLayout;
\r
92 import com.trolltech.qt.gui.QHBoxLayout;
\r
93 import com.trolltech.qt.gui.QIcon;
\r
94 import com.trolltech.qt.gui.QImage;
\r
95 import com.trolltech.qt.gui.QKeyEvent;
\r
96 import com.trolltech.qt.gui.QKeySequence;
\r
97 import com.trolltech.qt.gui.QLabel;
\r
98 import com.trolltech.qt.gui.QLineEdit;
\r
99 import com.trolltech.qt.gui.QListWidgetItem;
\r
100 import com.trolltech.qt.gui.QMatrix;
\r
101 import com.trolltech.qt.gui.QMessageBox;
\r
102 import com.trolltech.qt.gui.QPalette;
\r
103 import com.trolltech.qt.gui.QPalette.ColorRole;
\r
104 import com.trolltech.qt.gui.QPushButton;
\r
105 import com.trolltech.qt.gui.QShortcut;
\r
106 import com.trolltech.qt.gui.QSplitter;
\r
107 import com.trolltech.qt.gui.QTextEdit;
\r
108 import com.trolltech.qt.gui.QTextEdit.LineWrapMode;
\r
109 import com.trolltech.qt.gui.QTimeEdit;
\r
110 import com.trolltech.qt.gui.QToolButton;
\r
111 import com.trolltech.qt.gui.QToolButton.ToolButtonPopupMode;
\r
112 import com.trolltech.qt.gui.QVBoxLayout;
\r
113 import com.trolltech.qt.gui.QWidget;
\r
114 import com.trolltech.qt.network.QNetworkAccessManager;
\r
115 import com.trolltech.qt.network.QNetworkReply;
\r
116 import com.trolltech.qt.network.QNetworkReply.NetworkError;
\r
117 import com.trolltech.qt.network.QNetworkRequest;
\r
118 import com.trolltech.qt.webkit.QWebPage;
\r
119 import com.trolltech.qt.webkit.QWebPage.WebAction;
\r
120 import com.trolltech.qt.webkit.QWebSettings;
\r
121 import com.trolltech.qt.webkit.QWebView;
\r
123 import cx.fbn.nevernote.Global;
\r
124 import cx.fbn.nevernote.dialog.EnCryptDialog;
\r
125 import cx.fbn.nevernote.dialog.EnDecryptDialog;
\r
126 import cx.fbn.nevernote.dialog.GeoDialog;
\r
127 import cx.fbn.nevernote.dialog.InsertLatexImage;
\r
128 import cx.fbn.nevernote.dialog.InsertLinkDialog;
\r
129 import cx.fbn.nevernote.dialog.SpellCheck;
\r
130 import cx.fbn.nevernote.dialog.TableDialog;
\r
131 import cx.fbn.nevernote.dialog.TagAssign;
\r
132 import cx.fbn.nevernote.evernote.EnCrypt;
\r
133 import cx.fbn.nevernote.filters.FilterEditorTags;
\r
134 import cx.fbn.nevernote.signals.NoteResourceSignal;
\r
135 import cx.fbn.nevernote.signals.NoteSignal;
\r
136 import cx.fbn.nevernote.sql.DatabaseConnection;
\r
137 import cx.fbn.nevernote.utilities.ApplicationLogger;
\r
138 import cx.fbn.nevernote.utilities.FileUtils;
\r
139 import cx.fbn.nevernote.utilities.Pair;
\r
140 import cx.fbn.nevernote.xml.HtmlTagModifier;
\r
142 public class BrowserWindow extends QWidget {
\r
144 public final QLineEdit titleLabel;
\r
145 private final QLineEdit urlText;
\r
146 private final QLabel authorLabel;
\r
147 private final QLineEdit authorText;
\r
148 private final QComboBox geoBox;
\r
149 public final TagLineEdit tagEdit;
\r
150 public final QLabel tagLabel;
\r
151 private final QPushButton urlLabel;
\r
152 private final QLabel alteredLabel;
\r
153 private final QDateEdit alteredDate;
\r
154 private final QTimeEdit alteredTime;
\r
155 private final QDateEdit createdDate;
\r
156 private final QTimeEdit createdTime;
\r
157 private final QLabel subjectLabel;
\r
158 private final QDateEdit subjectDate;
\r
159 private final QTimeEdit subjectTime;
\r
160 public final QComboBox notebookBox;
\r
161 private final QLabel notebookLabel;
\r
162 private final QLabel createdLabel;
\r
163 public final QComboBox fontSize;
\r
164 public final QAction fontSizeAction;
\r
165 private boolean extendedOn;
\r
166 public boolean buttonsVisible;
\r
167 private final String iconPath;
\r
168 private final ContentView browser;
\r
169 private final QTextEdit sourceEdit;
\r
170 private String sourceEditHeader;
\r
171 Highlighter syntaxHighlighter;
\r
172 private List<Tag> allTags;
\r
173 private List<String> currentTags;
\r
174 public NoteSignal noteSignal;
\r
175 public Signal2<String,String> evernoteLinkClicked;
\r
176 private List<Notebook> notebookList;
\r
177 private Note currentNote;
\r
178 private String saveNoteTitle;
\r
179 private String saveTagList;
\r
180 private boolean insideList;
\r
181 private final DatabaseConnection conn;
\r
182 private final QCalendarWidget createdCalendarWidget;
\r
183 private final QCalendarWidget alteredCalendarWidget;
\r
184 private final QCalendarWidget subjectCalendarWidget;
\r
186 public final QPushButton undoButton;
\r
187 public final QAction undoAction;
\r
188 public final QPushButton redoButton;
\r
189 public final QAction redoAction;
\r
190 public final QPushButton cutButton;
\r
191 public final QAction cutAction;
\r
192 public final QPushButton copyButton;
\r
193 public final QAction copyAction;
\r
194 public final QPushButton pasteButton;
\r
195 public final QAction pasteAction;
\r
196 public final QPushButton boldButton;
\r
197 public final QAction boldAction;
\r
198 public final QPushButton underlineButton;
\r
199 public final QAction underlineAction;
\r
200 public final QPushButton italicButton;
\r
201 public final QAction italicAction;
\r
202 public final Signal0 focusLost;
\r
203 public final NoteResourceSignal resourceSignal;
\r
205 public QPushButton rightAlignButton;
\r
206 public final QAction rightAlignAction;
\r
207 public QPushButton leftAlignButton;
\r
208 public final QAction leftAlignAction;
\r
209 public QPushButton centerAlignButton;
\r
210 public final QAction centerAlignAction;
\r
212 public final QPushButton strikethroughButton;
\r
213 public final QAction strikethroughAction;
\r
214 public final QPushButton hlineButton;
\r
215 public final QAction hlineAction;
\r
216 public final QPushButton indentButton;
\r
217 public final QAction indentAction;
\r
218 public final QPushButton outdentButton;
\r
219 public final QAction outdentAction;
\r
220 public final QPushButton bulletListButton;
\r
221 public final QAction bulletListAction;
\r
222 public final QPushButton numberListButton;
\r
223 public final QAction numberListAction;
\r
224 public final QPushButton spellCheckButton;
\r
225 public final QAction spellCheckAction;
\r
226 public final QPushButton todoButton;
\r
227 public final QAction todoAction;
\r
229 public final QShortcut focusTitleShortcut;
\r
230 public final QShortcut focusTagShortcut;
\r
231 public final QShortcut focusNoteShortcut;
\r
232 public final QShortcut focusUrlShortcut;
\r
233 public final QShortcut focusAuthorShortcut;
\r
235 public EditorButtonBar buttonLayout;
\r
236 public final QComboBox fontList;
\r
237 public final QAction fontListAction;
\r
238 public final QToolButton fontColor;
\r
239 public final QAction fontColorAction;
\r
240 private final ColorMenu fontColorMenu;
\r
241 public final QToolButton fontHilight;
\r
242 public final QAction fontHilightAction;
\r
243 private final ColorMenu fontHilightColorMenu;
\r
244 public final QFileSystemWatcher fileWatcher;
\r
245 public int cursorPosition;
\r
246 private boolean forceTextPaste;
\r
247 private String selectedFile;
\r
248 private String currentHyperlink;
\r
249 public boolean keepPDFNavigationHidden;
\r
250 private final ApplicationLogger logger;
\r
251 SpellDictionary dictionary;
\r
252 SpellDictionary userDictionary;
\r
253 SpellChecker spellChecker;
\r
254 SuggestionListener spellListener;
\r
255 private final HashMap<String,Integer> previewPageList;
\r
256 boolean insertHyperlink;
\r
257 boolean insideTable;
\r
258 boolean insideEncryption;
\r
259 public Signal1<BrowserWindow> blockApplication;
\r
260 public Signal0 unblockApplication;
\r
261 public boolean awaitingHttpResponse;
\r
262 public long unblockTime;
\r
263 private final QTimer setSourceTimer;
\r
264 String latexGuid; // This is set if we are editing an existing LaTeX formula. Useful to track guid.
\r
267 public static class SuggestionListener implements SpellCheckListener {
\r
268 public boolean abortSpellCheck = false;
\r
269 public boolean errorsFound = false;
\r
270 private final SpellCheck spellCheckDialog;
\r
273 private final BrowserWindow parent;
\r
274 public SuggestionListener(BrowserWindow parent, SpellChecker checker) {
\r
275 this.parent = parent;
\r
276 spellCheckDialog = new SpellCheck(checker);
\r
278 public void spellingError(SpellCheckEvent event) {
\r
279 errorsFound = true;
\r
280 spellCheckDialog.setWord(event.getInvalidWord());
\r
282 @SuppressWarnings("unchecked")
\r
283 List<Word> suggestions = event.getSuggestions();
\r
284 spellCheckDialog.clearSuggestions();
\r
285 if (!suggestions.isEmpty()) {
\r
286 // spellCheckDialog.setCurrentSuggestion(suggestions.get(0).getWord());
\r
287 for (int i=0; i<suggestions.size(); i++) {
\r
288 spellCheckDialog.addSuggestion(suggestions.get(i).getWord());
\r
290 spellCheckDialog.setSelectedSuggestion(0);
\r
292 spellCheckDialog.exec();
\r
293 if (spellCheckDialog.cancelPressed()) {
\r
294 abortSpellCheck = true;
\r
298 if (spellCheckDialog.replacePressed()) {
\r
299 QClipboard clipboard = QApplication.clipboard();
\r
300 clipboard.setText(spellCheckDialog.getReplacementWord());
\r
301 parent.pasteClicked();
\r
309 public BrowserWindow(DatabaseConnection c) {
\r
310 logger = new ApplicationLogger("browser.log");
\r
311 logger.log(logger.HIGH, "Setting up browser");
\r
312 iconPath = new String("classpath:cx/fbn/nevernote/icons/");
\r
313 forceTextPaste = false;
\r
314 insertHyperlink = true;
\r
315 insideTable = false;
\r
316 insideEncryption = false;
\r
318 fileWatcher = new QFileSystemWatcher();
\r
319 // fileWatcher.fileChanged.connect(this, "fileChanged(String)");
\r
320 noteSignal = new NoteSignal();
\r
321 titleLabel = new QLineEdit();
\r
322 evernoteLinkClicked = new Signal2<String,String>();
\r
323 titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX);
\r
324 urlText = new QLineEdit();
\r
325 authorText = new QLineEdit();
\r
326 geoBox = new QComboBox();
\r
327 urlLabel = new QPushButton();
\r
328 urlLabel.clicked.connect(this, "sourceUrlClicked()");
\r
329 authorLabel = new QLabel();
\r
332 focusLost = new Signal0();
\r
334 tagEdit = new TagLineEdit(allTags);
\r
335 tagLabel = new QLabel(tr("Tags:"));
\r
336 tagEdit.focusLost.connect(this, "modifyTagsTyping()");
\r
338 createdCalendarWidget = new QCalendarWidget();
\r
339 createdDate = new QDateEdit();
\r
340 createdDate.setDisplayFormat(Global.getDateFormat());
\r
341 createdDate.setCalendarPopup(true);
\r
342 createdDate.setCalendarWidget(createdCalendarWidget);
\r
343 createdTime = new QTimeEdit();
\r
344 createdDate.dateChanged.connect(this, "createdChanged()");
\r
345 createdTime.timeChanged.connect(this, "createdChanged()");
\r
347 alteredCalendarWidget = new QCalendarWidget();
\r
348 alteredDate = new QDateEdit();
\r
349 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
350 alteredDate.setCalendarPopup(true);
\r
351 alteredDate.setCalendarWidget(alteredCalendarWidget);
\r
352 alteredTime = new QTimeEdit();
\r
353 alteredLabel = new QLabel(tr("Altered:"));
\r
354 alteredDate.dateChanged.connect(this, "alteredChanged()");
\r
355 alteredTime.timeChanged.connect(this, "alteredChanged()");
\r
357 subjectCalendarWidget = new QCalendarWidget();
\r
358 subjectDate = new QDateEdit();
\r
359 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
360 subjectDate.setCalendarPopup(true);
\r
361 subjectDate.setCalendarWidget(subjectCalendarWidget);
\r
362 subjectTime = new QTimeEdit();
\r
363 subjectLabel = new QLabel(tr("Subject Date:"));
\r
364 subjectDate.dateChanged.connect(this, "subjectDateTimeChanged()");
\r
365 subjectTime.timeChanged.connect(this, "subjectDateTimeChanged()");
\r
366 authorText.textChanged.connect(this, "authorChanged()");
\r
367 urlText.textChanged.connect(this, "sourceUrlChanged()");
\r
369 notebookBox = new QComboBox();
\r
370 notebookLabel = new QLabel(tr("Notebook"));
\r
371 createdLabel = new QLabel(tr("Created:"));
\r
372 // selectedText = new String();
\r
374 urlLabel.setVisible(false);
\r
375 urlText.setVisible(false);
\r
376 authorLabel.setVisible(false);
\r
378 geoBox.setVisible(false);
\r
379 geoBox.addItem(new QIcon(iconPath+"globe.png"), "");
\r
380 geoBox.addItem(new String(tr("Set")));
\r
381 geoBox.addItem(new String(tr("Clear")));
\r
382 geoBox.addItem(new String(tr("View On Map")));
\r
383 geoBox.activated.connect(this, "geoBoxChanged()");
\r
385 authorText.setVisible(false);
\r
386 createdDate.setVisible(false);
\r
387 alteredLabel.setVisible(false);
\r
388 //notebookBox.setVisible(false);
\r
389 notebookLabel.setVisible(false);
\r
390 createdLabel.setVisible(false);
\r
391 createdTime.setVisible(false);
\r
392 alteredDate.setVisible(false);
\r
393 alteredTime.setVisible(false);
\r
394 subjectLabel.setVisible(false);
\r
395 subjectDate.setVisible(false);
\r
396 subjectTime.setVisible(false);
\r
397 extendedOn = false;
\r
398 buttonsVisible = true;
\r
399 setAcceptDrops(true);
\r
401 browser = new ContentView(this);
\r
403 browser.page().setLinkDelegationPolicy(
\r
404 QWebPage.LinkDelegationPolicy.DelegateAllLinks);
\r
405 browser.linkClicked.connect(this, "linkClicked(QUrl)");
\r
406 currentHyperlink = "";
\r
408 //Setup the source editor
\r
409 sourceEdit = new QTextEdit(this);
\r
410 sourceEdit.setVisible(false);
\r
411 sourceEdit.setTabChangesFocus(true);
\r
412 sourceEdit.setLineWrapMode(LineWrapMode.NoWrap);
\r
413 QFont font = new QFont();
\r
414 font.setFamily("Courier");
\r
415 font.setFixedPitch(true);
\r
416 font.setPointSize(10);
\r
417 sourceEdit.setFont(font);
\r
418 syntaxHighlighter = new Highlighter(sourceEdit.document());
\r
419 sourceEdit.textChanged.connect(this, "sourceEdited()");
\r
421 QVBoxLayout v = new QVBoxLayout();
\r
422 QFormLayout notebookLayout = new QFormLayout();
\r
423 QGridLayout dateLayout = new QGridLayout();
\r
424 titleLabel.setReadOnly(false);
\r
425 titleLabel.editingFinished.connect(this, "titleEdited()");
\r
426 browser.page().contentsChanged.connect(this, "contentChanged()");
\r
427 browser.page().selectionChanged.connect(this, "selectionChanged()");
\r
428 browser.page().mainFrame().javaScriptWindowObjectCleared.connect(this,
\r
429 "exposeToJavascript()");
\r
431 notebookBox.activated.connect(this, "notebookChanged()");
\r
432 resourceSignal = new NoteResourceSignal();
\r
434 QHBoxLayout tagLayout = new QHBoxLayout();
\r
435 v.addWidget(titleLabel, 0);
\r
436 notebookLayout.addRow(notebookLabel, notebookBox);
\r
437 tagLayout.addLayout(notebookLayout, 0);
\r
438 tagLayout.stretch(4);
\r
439 tagLayout.addWidget(tagLabel, 0);
\r
440 tagLayout.addWidget(tagEdit, 1);
\r
441 v.addLayout(tagLayout);
\r
443 QHBoxLayout urlLayout = new QHBoxLayout();
\r
444 urlLayout.addWidget(urlLabel, 0);
\r
445 urlLayout.addWidget(urlText, 0);
\r
446 v.addLayout(urlLayout);
\r
448 QHBoxLayout authorLayout = new QHBoxLayout();
\r
449 authorLayout.addWidget(authorLabel, 0);
\r
450 authorLayout.addWidget(authorText, 0);
\r
451 authorLayout.addWidget(geoBox);
\r
452 v.addLayout(authorLayout);
\r
454 dateLayout.addWidget(createdLabel, 0, 0);
\r
455 dateLayout.addWidget(createdDate, 0, 1);
\r
456 dateLayout.addWidget(createdTime, 0, 2);
\r
457 dateLayout.setColumnStretch(9, 100);
\r
458 dateLayout.addWidget(alteredLabel, 0, 3);
\r
459 dateLayout.addWidget(alteredDate, 0, 4);
\r
460 dateLayout.addWidget(alteredTime, 0, 5);
\r
461 dateLayout.addWidget(subjectLabel, 0, 6);
\r
462 dateLayout.addWidget(subjectDate, 0, 7);
\r
463 dateLayout.addWidget(subjectTime, 0, 8);
\r
464 v.addLayout(dateLayout, 0);
\r
466 undoButton = newEditorButton("undo", tr("Undo Change"));
\r
467 redoButton = newEditorButton("redo", tr("Redo Change"));
\r
468 cutButton = newEditorButton("cut", tr("Cut"));
\r
469 copyButton = newEditorButton("copy", tr("Copy"));
\r
470 pasteButton = newEditorButton("paste", tr("Paste"));
\r
471 boldButton = newEditorButton("bold", tr("Bold"));
\r
472 underlineButton = newEditorButton("underline", tr("Underline"));
\r
473 italicButton = newEditorButton("italic", tr("Italic"));
\r
475 rightAlignButton = newEditorButton("justifyRight", tr("Right Align"));
\r
476 leftAlignButton = newEditorButton("justifyLeft", tr("Left Align"));
\r
477 centerAlignButton = newEditorButton("justifyCenter", tr("Center Align"));
\r
479 strikethroughButton = newEditorButton("strikethrough", tr("Strikethrough"));
\r
480 hlineButton = newEditorButton("hline", tr("Insert Horizontal Line"));
\r
481 indentButton = newEditorButton("indent", tr("Shift Right"));
\r
482 outdentButton = newEditorButton("outdent", tr("Shift Left"));
\r
483 bulletListButton = newEditorButton("bulletList", tr("Bullet List"));
\r
484 numberListButton = newEditorButton("numberList", tr("Number List"));
\r
485 spellCheckButton = newEditorButton("spellCheck", tr("Spell Check"));
\r
486 todoButton = newEditorButton("todo", tr("To-do"));
\r
489 buttonLayout = new EditorButtonBar();
\r
490 v.addWidget(buttonLayout);
\r
492 undoAction = buttonLayout.addWidget(undoButton);
\r
493 buttonLayout.toggleUndoVisible.triggered.connect(this, "toggleUndoVisible(Boolean)");
\r
494 redoAction = buttonLayout.addWidget(redoButton);
\r
495 buttonLayout.toggleRedoVisible.triggered.connect(this, "toggleRedoVisible(Boolean)");
\r
497 buttonLayout.addWidget(newSeparator());
\r
498 cutAction = buttonLayout.addWidget(cutButton);
\r
499 buttonLayout.toggleCutVisible.triggered.connect(this, "toggleCutVisible(Boolean)");
\r
500 copyAction = buttonLayout.addWidget(copyButton);
\r
501 buttonLayout.toggleCopyVisible.triggered.connect(this, "toggleCopyVisible(Boolean)");
\r
502 pasteAction = buttonLayout.addWidget(pasteButton);
\r
503 buttonLayout.togglePasteVisible.triggered.connect(this, "togglePasteVisible(Boolean)");
\r
505 buttonLayout.addWidget(newSeparator());
\r
506 boldAction = buttonLayout.addWidget(boldButton);
\r
507 buttonLayout.toggleBoldVisible.triggered.connect(this, "toggleBoldVisible(Boolean)");
\r
508 italicAction = buttonLayout.addWidget(italicButton);
\r
509 buttonLayout.toggleItalicVisible.triggered.connect(this, "toggleItalicVisible(Boolean)");
\r
510 underlineAction = buttonLayout.addWidget(underlineButton);
\r
511 buttonLayout.toggleUnderlineVisible.triggered.connect(this, "toggleUnderlineVisible(Boolean)");
\r
512 strikethroughAction = buttonLayout.addWidget(strikethroughButton);
\r
513 buttonLayout.toggleStrikethroughVisible.triggered.connect(this, "toggleStrikethroughVisible(Boolean)");
\r
516 buttonLayout.addWidget(newSeparator());
\r
517 leftAlignAction = buttonLayout.addWidget(leftAlignButton);
\r
518 buttonLayout.toggleLeftAlignVisible.triggered.connect(this, "toggleLeftAlignVisible(Boolean)");
\r
519 centerAlignAction = buttonLayout.addWidget(centerAlignButton);
\r
520 buttonLayout.toggleCenterAlignVisible.triggered.connect(this, "toggleCenterAlignVisible(Boolean)");
\r
521 rightAlignAction = buttonLayout.addWidget(rightAlignButton);
\r
522 buttonLayout.toggleRightAlignVisible.triggered.connect(this, "toggleRightAlignVisible(Boolean)");
\r
524 buttonLayout.addWidget(newSeparator());
\r
525 hlineAction = buttonLayout.addWidget(hlineButton);
\r
526 buttonLayout.toggleHLineVisible.triggered.connect(this, "toggleHLineVisible(Boolean)");
\r
528 indentAction = buttonLayout.addWidget(indentButton);
\r
529 buttonLayout.toggleIndentVisible.triggered.connect(this, "toggleIndentVisible(Boolean)");
\r
530 outdentAction = buttonLayout.addWidget(outdentButton);
\r
531 buttonLayout.toggleOutdentVisible.triggered.connect(this, "toggleOutdentVisible(Boolean)");
\r
532 bulletListAction = buttonLayout.addWidget(bulletListButton);
\r
533 buttonLayout.toggleBulletListVisible.triggered.connect(this, "toggleBulletListVisible(Boolean)");
\r
534 numberListAction = buttonLayout.addWidget(numberListButton);
\r
535 buttonLayout.toggleNumberListVisible.triggered.connect(this, "toggleNumberListVisible(Boolean)");
\r
537 // Setup the font & font size combo boxes
\r
538 buttonLayout.addWidget(newSeparator());
\r
539 fontList = new QComboBox();
\r
540 fontSize = new QComboBox();
\r
541 fontList.setToolTip("Font");
\r
542 fontSize.setToolTip("Font Size");
\r
543 fontList.activated.connect(this, "fontChanged(String)");
\r
544 fontSize.activated.connect(this, "fontSizeChanged(String)");
\r
545 fontListAction = buttonLayout.addWidget(fontList);
\r
546 buttonLayout.toggleFontVisible.triggered.connect(this, "toggleFontListVisible(Boolean)");
\r
547 fontSizeAction = buttonLayout.addWidget(fontSize);
\r
548 buttonLayout.toggleFontSizeVisible.triggered.connect(this, "toggleFontSizeVisible(Boolean)");
\r
549 QFontDatabase fonts = new QFontDatabase();
\r
550 List<String> fontFamilies = fonts.families();
\r
551 for (int i = 0; i < fontFamilies.size(); i++) {
\r
552 fontList.addItem(fontFamilies.get(i));
\r
554 loadFontSize(fontFamilies.get(i));
\r
558 // buttonLayout.addWidget(newSeparator(), 0);
\r
559 fontColor = newToolButton("fontColor", tr("Font Color"));
\r
560 fontColorMenu = new ColorMenu(this);
\r
561 fontColor.setMenu(fontColorMenu.getMenu());
\r
562 fontColor.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
563 fontColor.setAutoRaise(false);
\r
564 fontColorMenu.getMenu().triggered.connect(this, "fontColorClicked()");
\r
565 fontColorAction = buttonLayout.addWidget(fontColor);
\r
566 buttonLayout.toggleFontColorVisible.triggered.connect(this, "toggleFontColorVisible(Boolean)");
\r
567 fontHilight = newToolButton("fontHilight", tr("Font Hilight Color"));
\r
568 fontHilight.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
569 fontHilight.setAutoRaise(false);
\r
570 fontHilightColorMenu = new ColorMenu(this);
\r
571 fontHilightColorMenu.setDefault(QColor.yellow);
\r
572 fontHilight.setMenu(fontHilightColorMenu.getMenu());
\r
573 fontHilightColorMenu.getMenu().triggered.connect(this, "fontHilightClicked()");
\r
574 fontHilightAction = buttonLayout.addWidget(fontHilight);
\r
575 fontHilightColorMenu.setDefault(QColor.yellow);
\r
576 buttonLayout.toggleFontHilight.triggered.connect(this, "toggleFontHilightVisible(Boolean)");
\r
578 spellCheckAction = buttonLayout.addWidget(spellCheckButton);
\r
579 buttonLayout.toggleNumberListVisible.triggered.connect(this, "spellCheckClicked()");
\r
580 buttonLayout.toggleSpellCheck.triggered.connect(this, "toggleSpellCheckVisible(Boolean)");
\r
582 todoAction = buttonLayout.addWidget(todoButton);
\r
583 buttonLayout.toggleNumberListVisible.triggered.connect(this, "todoClicked()");
\r
584 buttonLayout.toggleTodo.triggered.connect(this, "toggleTodoVisible(Boolean)");
\r
586 // Setup the source browser);
\r
588 // buttonLayout.addWidget(new QLabel(), 1);
\r
589 QSplitter editSplitter = new QSplitter(this);
\r
590 editSplitter.addWidget(browser);
\r
591 editSplitter.setOrientation(Qt.Orientation.Vertical);
\r
592 editSplitter.addWidget(sourceEdit);
\r
596 // v.addWidget(browser, 1);
\r
597 // v.addWidget(sourceEdit);
\r
598 v.addWidget(editSplitter);
\r
601 browser.downloadAttachmentRequested.connect(this,
\r
602 "downloadAttachment(QNetworkRequest)");
\r
603 browser.downloadImageRequested.connect(this,
\r
604 "downloadImage(QNetworkRequest)");
\r
605 setTabOrder(notebookBox, tagEdit);
\r
606 setTabOrder(tagEdit, browser);
\r
608 focusNoteShortcut = new QShortcut(this);
\r
609 setupShortcut(focusNoteShortcut, "Focus_Note");
\r
610 focusNoteShortcut.activated.connect(this, "focusNote()");
\r
611 focusTitleShortcut = new QShortcut(this);
\r
612 setupShortcut(focusTitleShortcut, "Focus_Title");
\r
613 focusTitleShortcut.activated.connect(this, "focusTitle()");
\r
614 focusTagShortcut = new QShortcut(this);
\r
615 setupShortcut(focusTagShortcut, "Focus_Tag");
\r
616 focusTagShortcut.activated.connect(this, "focusTag()");
\r
617 focusAuthorShortcut = new QShortcut(this);
\r
618 setupShortcut(focusAuthorShortcut, "Focus_Author");
\r
619 focusAuthorShortcut.activated.connect(this, "focusAuthor()");
\r
620 focusUrlShortcut = new QShortcut(this);
\r
621 setupShortcut(focusUrlShortcut, "Focus_Url");
\r
622 focusUrlShortcut.activated.connect(this, "focusUrl()");
\r
624 browser.page().mainFrame().setTextSizeMultiplier(Global.getTextSizeMultiplier());
\r
625 browser.page().mainFrame().setZoomFactor(Global.getZoomFactor());
\r
627 previewPageList = new HashMap<String,Integer>();
\r
629 browser.page().microFocusChanged.connect(this, "microFocusChanged()");
\r
633 QPalette pal = new QPalette();
\r
634 pal.setColor(ColorRole.Text, QColor.black);
\r
635 titleLabel.setPalette(pal);
\r
636 authorText.setPalette(pal);
\r
637 authorLabel.setPalette(pal);
\r
638 urlLabel.setPalette(pal);
\r
639 urlText.setPalette(pal);
\r
640 createdDate.setPalette(pal);
\r
641 createdTime.setPalette(pal);
\r
642 alteredDate.setPalette(pal);
\r
643 alteredTime.setPalette(pal);
\r
644 subjectDate.setPalette(pal);
\r
645 subjectTime.setPalette(pal);
\r
646 tagEdit.setPalette(pal);
\r
647 notebookBox.setPalette(pal);
\r
649 blockApplication = new Signal1<BrowserWindow>();
\r
650 unblockApplication = new Signal0();
\r
652 setSourceTimer = new QTimer();
\r
653 setSourceTimer.timeout.connect(this, "setSource()");
\r
655 logger.log(logger.HIGH, "Browser setup complete");
\r
660 private void setupShortcut(QShortcut action, String text) {
\r
661 if (!Global.shortcutKeys.containsAction(text))
\r
663 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
\r
669 // Getter for the QWebView
\r
670 public QWebView getBrowser() {
\r
674 // Block signals while loading data or things are flagged as dirty by
\r
676 public void loadingData(boolean val) {
\r
677 logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val);
\r
678 notebookBox.blockSignals(val);
\r
679 browser.page().blockSignals(val);
\r
680 browser.page().mainFrame().blockSignals(val);
\r
681 titleLabel.blockSignals(val);
\r
682 alteredDate.blockSignals(val);
\r
683 alteredTime.blockSignals(val);
\r
684 createdTime.blockSignals(val);
\r
685 createdDate.blockSignals(val);
\r
686 subjectDate.blockSignals(val);
\r
687 subjectTime.blockSignals(val);
\r
688 urlText.blockSignals(val);
\r
689 authorText.blockSignals(val);
\r
691 exposeToJavascript();
\r
692 logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val);
\r
696 public void setReadOnly(boolean v) {
\r
698 titleLabel.setEnabled(!v);
\r
699 notebookBox.setEnabled(!v);
\r
700 tagEdit.setEnabled(!v);
\r
701 authorLabel.setEnabled(!v);
\r
702 geoBox.setEnabled(!v);
\r
703 urlText.setEnabled(!v);
\r
704 createdDate.setEnabled(!v);
\r
705 subjectDate.setEnabled(!v);
\r
706 alteredDate.setEnabled(!v);
\r
707 authorText.setEnabled(!v);
\r
708 createdTime.setEnabled(!v);
\r
709 alteredTime.setEnabled(!v);
\r
710 subjectTime.setEnabled(!v);
\r
711 getBrowser().setEnabled(true);
\r
712 // getBrowser().setEnabled(!v);
\r
715 // expose this class to Javascript on the web page
\r
716 private void exposeToJavascript() {
\r
717 browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this);
\r
720 // Custom event queue
\r
722 public boolean event(QEvent e) {
\r
723 if (e.type().equals(QEvent.Type.FocusOut)) {
\r
724 logger.log(logger.EXTREME, "Focus lost");
\r
727 return super.event(e);
\r
730 // clear out browser
\r
731 public void clear() {
\r
732 logger.log(logger.EXTREME, "Entering BrowserWindow.clear()");
\r
734 setContent(new QByteArray());
\r
735 tagEdit.setText("");
\r
736 tagEdit.tagCompleter.reset();
\r
737 urlLabel.setText(tr("Source URL:"));
\r
738 titleLabel.setText("");
\r
739 logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()");
\r
742 public void setContent(QByteArray data) {
\r
743 sourceEdit.blockSignals(true);
\r
744 browser.setContent(data);
\r
747 // get/set current note
\r
748 public void setNote(Note n) {
\r
752 saveNoteTitle = n.getTitle();
\r
756 public Note getNote() {
\r
757 return currentNote;
\r
760 // New Editor Button
\r
761 private QPushButton newEditorButton(String name, String toolTip) {
\r
762 QPushButton button = new QPushButton();
\r
763 // QIcon icon = new QIcon(iconPath + name + ".gif");
\r
764 QIcon icon = new QIcon(iconPath + name + ".png");
\r
765 button.setIcon(icon);
\r
766 button.setToolTip(toolTip);
\r
767 button.clicked.connect(this, name + "Clicked()");
\r
770 // New Editor Button
\r
771 private QToolButton newToolButton(String name, String toolTip) {
\r
772 QToolButton button = new QToolButton();
\r
773 // QIcon icon = new QIcon(iconPath + name + ".gif");
\r
774 QIcon icon = new QIcon(iconPath + name + ".png");
\r
775 button.setIcon(icon);
\r
776 button.setToolTip(toolTip);
\r
777 button.clicked.connect(this, name + "Clicked()");
\r
782 private QLabel newSeparator() {
\r
783 return new QLabel(" ");
\r
786 // Set the title in the window
\r
787 public void setTitle(String t) {
\r
788 titleLabel.setText(t);
\r
793 // Return the current text title
\r
794 public String getTitle() {
\r
795 return titleLabel.text();
\r
798 // Set the tag name string
\r
799 public void setTag(String t) {
\r
801 tagEdit.setText(t);
\r
802 tagEdit.tagCompleter.reset();
\r
805 // Set the source URL
\r
806 public void setUrl(String t) {
\r
807 urlLabel.setText(tr("Source URL:\t"));
\r
808 urlText.setText(t);
\r
811 // The user want's to launch a web browser on the source of the URL
\r
812 public void sourceUrlClicked() {
\r
813 // Make sure we have a valid URL
\r
814 if (urlText.text().trim().equals(""))
\r
817 String url = urlText.text();
\r
818 if (!url.toLowerCase().startsWith(tr("http://")))
\r
819 url = tr("http://") +url;
\r
821 if (!QDesktopServices.openUrl(new QUrl(url))) {
\r
822 logger.log(logger.LOW, "Error opening file :" +url);
\r
826 public void setAuthor(String t) {
\r
827 authorLabel.setText(tr("Author:\t"));
\r
828 authorText.setText(t);
\r
831 // Set the creation date
\r
832 public void setCreation(long date) {
\r
833 QDateTime dt = new QDateTime();
\r
834 dt.setTime_t((int) (date / 1000));
\r
835 createdDate.setDateTime(dt);
\r
836 createdTime.setDateTime(dt);
\r
837 createdDate.setDisplayFormat(Global.getDateFormat());
\r
838 createdTime.setDisplayFormat(Global.getTimeFormat());
\r
841 // Set the creation date
\r
842 public void setAltered(long date) {
\r
843 QDateTime dt = new QDateTime();
\r
844 dt.setTime_t((int) (date / 1000));
\r
845 alteredDate.setDateTime(dt);
\r
846 alteredTime.setDateTime(dt);
\r
847 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
848 alteredTime.setDisplayFormat(Global.getTimeFormat());
\r
851 // Set the subject date
\r
852 public void setSubjectDate(long date) {
\r
853 QDateTime dt = new QDateTime();
\r
854 dt.setTime_t((int) (date / 1000));
\r
855 subjectDate.setDateTime(dt);
\r
856 subjectTime.setDateTime(dt);
\r
857 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
858 subjectTime.setDisplayFormat(Global.getTimeFormat());
\r
861 // Toggle the extended attribute information
\r
862 public void toggleInformation() {
\r
864 extendedOn = false;
\r
868 urlLabel.setVisible(extendedOn);
\r
869 urlText.setVisible(extendedOn);
\r
870 authorText.setVisible(extendedOn);
\r
871 geoBox.setVisible(extendedOn);
\r
872 authorLabel.setVisible(extendedOn);
\r
873 createdDate.setVisible(extendedOn);
\r
874 createdTime.setVisible(extendedOn);
\r
875 createdLabel.setVisible(extendedOn);
\r
876 alteredLabel.setVisible(extendedOn);
\r
877 alteredDate.setVisible(extendedOn);
\r
878 alteredTime.setVisible(extendedOn);
\r
879 //notebookBox.setVisible(extendedOn);
\r
880 notebookLabel.setVisible(extendedOn);
\r
881 subjectLabel.setVisible(extendedOn);
\r
882 subjectDate.setVisible(extendedOn);
\r
883 subjectTime.setVisible(extendedOn);
\r
886 public void hideButtons() {
\r
888 undoButton.parentWidget().setVisible(false);
\r
889 buttonsVisible = false;
\r
893 // Is the extended view on?
\r
894 public boolean isExtended() {
\r
898 // Listener for when a link is clicked
\r
899 @SuppressWarnings("unused")
\r
900 private void openFile() {
\r
901 logger.log(logger.EXTREME, "Starting openFile()");
\r
902 File fileHandle = new File(selectedFile);
\r
903 URI fileURL = fileHandle.toURI();
\r
904 String localURL = fileURL.toString();
\r
905 QUrl url = new QUrl(localURL);
\r
906 QFile file = new QFile(selectedFile);
\r
908 logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName());
\r
909 fileWatcher.addPath(file.fileName());
\r
911 if (!QDesktopServices.openUrl(url)) {
\r
912 logger.log(logger.LOW, "Error opening file :" +url);
\r
917 // Listener for when a link is clicked
\r
918 @SuppressWarnings("unused")
\r
919 private void linkClicked(QUrl url) {
\r
920 logger.log(logger.EXTREME, "URL Clicked: " +url.toString());
\r
921 if (url.toString().startsWith("latex:")) {
\r
922 int position = url.toString().lastIndexOf(".");
\r
923 String guid = url.toString().substring(0,position);
\r
924 position = guid.lastIndexOf("/");
\r
925 guid = guid.substring(position+1);
\r
929 if (url.toString().startsWith("evernote:/view/")) {
\r
930 StringTokenizer tokens = new StringTokenizer(url.toString().replace("evernote:/view/", ""), "/");
\r
931 tokens.nextToken();
\r
932 tokens.nextToken();
\r
933 String sid = tokens.nextToken();
\r
934 String lid = tokens.nextToken();
\r
936 // Emit that we want to switch to a new note
\r
937 evernoteLinkClicked.emit(sid, lid);
\r
941 if (url.toString().startsWith("nnres://")) {
\r
942 logger.log(logger.EXTREME, "URL is NN resource");
\r
943 if (url.toString().endsWith("/vnd.evernote.ink")) {
\r
944 logger.log(logger.EXTREME, "Unable to open ink note");
\r
945 QMessageBox.information(this, tr("Unable Open"), tr("This is an ink note.\n"+
\r
946 "Ink notes are not supported since Evernote has not\n published any specifications on them\n" +
\r
947 "and I'm too lazy to figure them out by myself."));
\r
950 String fullName = url.toString().substring(8);
\r
951 int index = fullName.indexOf(".");
\r
955 type = fullName.substring(index+1);
\r
956 guid = fullName.substring(0,index);
\r
958 index = guid.indexOf(Global.attachmentNameDelimeter);
\r
960 guid = guid.substring(0,index);
\r
962 List<Resource> resList = currentNote.getResources();
\r
963 Resource res = null;
\r
964 for (int i=0; i<resList.size(); i++) {
\r
965 if (resList.get(i).getGuid().equals(guid)) {
\r
966 res = resList.get(i);
\r
971 String resGuid = Global.resourceMap.get(guid);
\r
972 if (resGuid != null)
\r
973 res = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, true);
\r
977 if (res.getAttributes() != null &&
\r
978 res.getAttributes().getFileName() != null &&
\r
979 !res.getAttributes().getFileName().trim().equals(""))
\r
980 fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();
\r
982 fileName = res.getGuid()+"."+type;
\r
983 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
984 QFile.OpenMode mode = new QFile.OpenMode();
\r
985 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
986 boolean openResult = file.open(mode);
\r
987 logger.log(logger.EXTREME, "File opened:" +openResult);
\r
988 QDataStream out = new QDataStream(file);
\r
989 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);
\r
990 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
992 logger.log(logger.EXTREME, "Writing resource");
\r
993 out.writeBytes(binData.toByteArray());
\r
996 String whichOS = System.getProperty("os.name");
\r
997 if (whichOS.contains("Windows"))
\r
998 url.setUrl("file:///"+file.fileName());
\r
1000 url.setUrl("file://"+file.fileName());
\r
1001 // fileWatcher.removePath(file.fileName());
\r
1002 logger.log(logger.EXTREME, "Adding file watcher " +file.fileName());
\r
1003 fileWatcher.addPath(file.fileName());
\r
1005 // If we can't open it, then prompt the user to save it.
\r
1006 if (!QDesktopServices.openUrl(url)) {
\r
1007 logger.log(logger.EXTREME, "We can't handle this. Where do we put it?");
\r
1008 QFileDialog dialog = new QFileDialog();
\r
1010 if (dialog.exec()!=0) {
\r
1011 List<String> fileNames = dialog.selectedFiles(); //gets all selected filenames
\r
1012 if (fileNames.size() == 0)
\r
1014 String sf = fileNames.get(0);
\r
1015 QFile saveFile = new QFile(sf);
\r
1016 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
1017 saveFile.open(mode);
\r
1018 QDataStream saveOut = new QDataStream(saveFile);
\r
1019 saveOut.writeBytes(binData.toByteArray());
\r
1027 logger.log(logger.EXTREME, "Launching URL");
\r
1028 QDesktopServices.openUrl(url);
\r
1031 // Listener for when BOLD is clicked
\r
1032 @SuppressWarnings("unused")
\r
1033 private void undoClicked() {
\r
1034 browser.page().triggerAction(WebAction.Undo);
\r
1035 browser.setFocus();
\r
1038 // Listener for when BOLD is clicked
\r
1039 @SuppressWarnings("unused")
\r
1040 private void redoClicked() {
\r
1041 browser.page().triggerAction(WebAction.Redo);
\r
1042 browser.setFocus();
\r
1045 // Listener for when BOLD is clicked
\r
1046 @SuppressWarnings("unused")
\r
1047 private void boldClicked() {
\r
1048 browser.page().triggerAction(WebAction.ToggleBold);
\r
1049 microFocusChanged();
\r
1050 browser.setFocus();
\r
1053 // Listener for when Italics is clicked
\r
1054 @SuppressWarnings("unused")
\r
1055 private void italicClicked() {
\r
1056 browser.page().triggerAction(WebAction.ToggleItalic);
\r
1057 microFocusChanged();
\r
1058 browser.setFocus();
\r
1061 // Listener for when UNDERLINE is clicked
\r
1062 @SuppressWarnings("unused")
\r
1063 private void underlineClicked() {
\r
1064 browser.page().triggerAction(WebAction.ToggleUnderline);
\r
1065 microFocusChanged();
\r
1066 browser.setFocus();
\r
1069 // Listener for when Strikethrough is clicked
\r
1070 @SuppressWarnings("unused")
\r
1071 private void strikethroughClicked() {
\r
1072 browser.page().mainFrame().evaluateJavaScript(
\r
1073 "document.execCommand('strikeThrough', false, '');");
\r
1074 browser.setFocus();
\r
1077 // Listener for when cut is clicked
\r
1078 @SuppressWarnings("unused")
\r
1079 private void cutClicked() {
\r
1080 browser.page().triggerAction(WebAction.Cut);
\r
1081 browser.setFocus();
\r
1084 // Listener when COPY is clicked
\r
1085 @SuppressWarnings("unused")
\r
1086 private void copyClicked() {
\r
1087 browser.page().triggerAction(WebAction.Copy);
\r
1088 browser.setFocus();
\r
1091 // Listener when PASTE is clicked
\r
1092 public void pasteClicked() {
\r
1093 logger.log(logger.EXTREME, "Paste Clicked");
\r
1094 if (forceTextPaste) {
\r
1095 pasteWithoutFormattingClicked();
\r
1098 QClipboard clipboard = QApplication.clipboard();
\r
1099 QMimeData mime = clipboard.mimeData();
\r
1101 // String x = mime.html();
\r
1103 if (mime.hasImage()) {
\r
1104 logger.log(logger.EXTREME, "Image paste found");
\r
1105 browser.setFocus();
\r
1106 insertImage(mime);
\r
1107 browser.setFocus();
\r
1111 if (mime.hasUrls()) {
\r
1112 logger.log(logger.EXTREME, "URL paste found");
\r
1113 if (!mime.text().startsWith("evernote:")) {
\r
1114 handleNoteLink(mime);
\r
1117 browser.setFocus();
\r
1122 String text = mime.html();
\r
1123 if (text.contains("en-tag") && mime.hasHtml()) {
\r
1124 logger.log(logger.EXTREME, "Intra-note paste found");
\r
1125 text = fixInternotePaste(text);
\r
1126 mime.setHtml(text);
\r
1127 clipboard.setMimeData(mime);
\r
1130 logger.log(logger.EXTREME, "Final paste choice encountered");
\r
1131 browser.page().triggerAction(WebAction.Paste);
\r
1132 browser.setFocus();
\r
1136 // Paste text without formatting
\r
1137 private void pasteWithoutFormattingClicked() {
\r
1138 logger.log(logger.EXTREME, "Paste without format clipped");
\r
1139 QClipboard clipboard = QApplication.clipboard();
\r
1140 QMimeData mime = clipboard.mimeData();
\r
1141 if (!mime.hasText())
\r
1143 String text = mime.text();
\r
1144 clipboard.clear();
\r
1145 clipboard.setText(text, Mode.Clipboard);
\r
1146 browser.page().triggerAction(WebAction.Paste);
\r
1148 // This is done because pasting into an encryption block
\r
1149 // can cause multiple cells (which can't happen). It
\r
1150 // just goes through the table, extracts the data, &
\r
1151 // puts it back as one table cell.
\r
1152 if (insideEncryption) {
\r
1153 String js = new String( "function fixEncryption() { "
\r
1154 +" var selObj = window.getSelection();"
\r
1155 +" var selRange = selObj.getRangeAt(0);"
\r
1156 +" var workingNode = window.getSelection().anchorNode;"
\r
1157 +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
\r
1158 +" workingNode = workingNode.parentNode;"
\r
1160 +" workingNode.innerHTML = window.jambi.fixEncryptionPaste(workingNode.innerHTML);"
\r
1161 +"} fixEncryption();");
\r
1162 browser.page().mainFrame().evaluateJavaScript(js);
\r
1166 // This basically removes all the table tags and returns just the contents.
\r
1167 // This is called by JavaScript to fix encryption pastes.
\r
1168 public String fixEncryptionPaste(String data) {
\r
1169 data = data.replace("<tbody>", "");
\r
1170 data = data.replace("</tbody>", "");
\r
1171 data = data.replace("<tr>", "");
\r
1172 data = data.replace("</tr>", "");
\r
1173 data = data.replace("<td>", "");
\r
1174 data = data.replace("</td>", "<br>");
\r
1175 data = data.replace("<br><br>", "<br>");
\r
1177 return "<tbody><tr><td>"+data+"</td></tr></tbody>";
\r
1180 // insert date/time
\r
1181 @SuppressWarnings("unused")
\r
1182 private void insertDateTime() {
\r
1183 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
\r
1184 String dateTimeFormat = new String(fmt);
\r
1185 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
\r
1186 Calendar cal = Calendar.getInstance();
\r
1188 browser.page().mainFrame().evaluateJavaScript(
\r
1189 "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");
\r
1191 browser.setFocus();
\r
1195 // Listener when Left is clicked
\r
1196 @SuppressWarnings("unused")
\r
1197 private void justifyLeftClicked() {
\r
1198 browser.page().mainFrame().evaluateJavaScript(
\r
1199 "document.execCommand('JustifyLeft', false, '');");
\r
1200 browser.setFocus();
\r
1203 // Listener when Center is clicked
\r
1204 @SuppressWarnings("unused")
\r
1205 private void justifyCenterClicked() {
\r
1206 browser.page().mainFrame().evaluateJavaScript(
\r
1207 "document.execCommand('JustifyCenter', false, '');");
\r
1208 browser.setFocus();
\r
1211 // Listener when Left is clicked
\r
1212 @SuppressWarnings("unused")
\r
1213 private void justifyRightClicked() {
\r
1214 browser.page().mainFrame().evaluateJavaScript(
\r
1215 "document.execCommand('JustifyRight', false, '');");
\r
1216 browser.setFocus();
\r
1219 // Listener when HLINE is clicked
\r
1220 @SuppressWarnings("unused")
\r
1221 private void hlineClicked() {
\r
1222 browser.page().mainFrame().evaluateJavaScript(
\r
1223 "document.execCommand('insertHorizontalRule', false, '');");
\r
1224 browser.setFocus();
\r
1227 // Listener when outdent is clicked
\r
1228 private void outdentClicked() {
\r
1229 browser.page().mainFrame().evaluateJavaScript(
\r
1230 "document.execCommand('outdent', false, '');");
\r
1231 browser.setFocus();
\r
1234 // Listener when a bullet list is clicked
\r
1235 @SuppressWarnings("unused")
\r
1236 private void bulletListClicked() {
\r
1237 browser.page().mainFrame().evaluateJavaScript(
\r
1238 "document.execCommand('InsertUnorderedList', false, '');");
\r
1239 browser.setFocus();
\r
1242 // Listener when a bullet list is clicked
\r
1243 @SuppressWarnings("unused")
\r
1244 private void numberListClicked() {
\r
1245 browser.page().mainFrame().evaluateJavaScript(
\r
1246 "document.execCommand('InsertOrderedList', false, '');");
\r
1247 browser.setFocus();
\r
1250 // Listener when indent is clicked
\r
1251 private void indentClicked() {
\r
1252 browser.page().mainFrame().evaluateJavaScript(
\r
1253 "document.execCommand('indent', false, '');");
\r
1254 browser.setFocus();
\r
1257 // Listener when the font name is changed
\r
1258 @SuppressWarnings("unused")
\r
1259 private void fontChanged(String font) {
\r
1260 browser.page().mainFrame().evaluateJavaScript(
\r
1261 "document.execCommand('fontName',false,'" + font + "');");
\r
1262 browser.setFocus();
\r
1265 // Listener when a font size is changed
\r
1266 @SuppressWarnings("unused")
\r
1267 private void fontSizeChanged(String font) {
\r
1268 String text = browser.selectedText();
\r
1269 if (text.trim().equalsIgnoreCase(""))
\r
1272 String selectedText = browser.selectedText();
\r
1273 String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";
\r
1274 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1275 browser.page().mainFrame().evaluateJavaScript(script);
\r
1276 /* browser.page().mainFrame().evaluateJavaScript(
\r
1277 "document.execCommand('fontSize',false,'"
\r
1280 browser.setFocus();
\r
1283 // Load the font combo box based upon the font selected
\r
1284 private void loadFontSize(String name) {
\r
1285 QFontDatabase db = new QFontDatabase();
\r
1287 List<Integer> points = db.pointSizes(name);
\r
1288 for (int i=0; i<points.size(); i++) {
\r
1289 fontSize.addItem(points.get(i).toString());
\r
1292 fontSize.addItem("x-small");
\r
1293 fontSize.addItem("small");
\r
1294 fontSize.addItem("medium");
\r
1295 fontSize.addItem("large");
\r
1296 fontSize.addItem("x-large");
\r
1297 fontSize.addItem("xx-large");
\r
1298 fontSize.addItem("xxx-large");
\r
1302 // Listener when a font size is changed
\r
1303 @SuppressWarnings("unused")
\r
1304 private void fontColorClicked() {
\r
1305 // QColorDialog dialog = new QColorDialog();
\r
1306 // QColor color = QColorDialog.getColor();
\r
1307 QColor color = fontColorMenu.getColor();
\r
1308 if (color.isValid())
\r
1309 browser.page().mainFrame().evaluateJavaScript(
\r
1310 "document.execCommand('foreColor',false,'" + color.name()
\r
1312 browser.setFocus();
\r
1315 // Listener for when a background color change is requested
\r
1316 @SuppressWarnings("unused")
\r
1317 private void fontHilightClicked() {
\r
1318 // QColorDialog dialog = new QColorDialog();
\r
1319 // QColor color = QColorDialog.getColor();
\r
1320 QColor color = fontHilightColorMenu.getColor();
\r
1321 if (color.isValid())
\r
1322 browser.page().mainFrame().evaluateJavaScript(
\r
1323 "document.execCommand('backColor',false,'" + color.name()
\r
1325 browser.setFocus();
\r
1328 // Listener for when a background color change is requested
\r
1329 @SuppressWarnings("unused")
\r
1330 private void superscriptClicked() {
\r
1331 browser.page().mainFrame().evaluateJavaScript(
\r
1332 "document.execCommand('superscript');");
\r
1333 browser.setFocus();
\r
1336 // Listener for when a background color change is requested
\r
1337 @SuppressWarnings("unused")
\r
1338 private void subscriptClicked() {
\r
1339 browser.page().mainFrame().evaluateJavaScript(
\r
1340 "document.execCommand('subscript');");
\r
1341 browser.setFocus();
\r
1343 // Insert a to-do checkbox
\r
1344 @SuppressWarnings("unused")
\r
1345 private void todoClicked() {
\r
1346 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1347 String script_start = new String(
\r
1348 "document.execCommand('insertHtml', false, '");
\r
1349 String script_end = new String("');");
\r
1350 String todo = new String(
\r
1351 "<input TYPE=\"CHECKBOX\" value=\"false\" " +
\r
1352 "onMouseOver=\"style.cursor=\\'hand\\'\" " +
\r
1353 "onClick=\"value=checked; window.jambi.contentChanged(); \" />");
\r
1354 browser.page().mainFrame().evaluateJavaScript(
\r
1355 script_start + todo + script_end);
\r
1356 browser.setFocus();
\r
1359 // Encrypt the selected text
\r
1360 @SuppressWarnings("unused")
\r
1361 private void encryptText() {
\r
1362 String text = browser.selectedText();
\r
1363 if (text.trim().equalsIgnoreCase(""))
\r
1365 text = new String(text.replaceAll("\n", "<br/>"));
\r
1367 EnCryptDialog dialog = new EnCryptDialog();
\r
1369 if (!dialog.okPressed()) {
\r
1373 EnCrypt crypt = new EnCrypt();
\r
1374 String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);
\r
1375 String decrypted = crypt.decrypt(encrypted, dialog.getPassword().trim(), 64);
\r
1377 if (encrypted.trim().equals("")) {
\r
1378 QMessageBox.information(this, tr("Error"), tr("Error Encrypting String"));
\r
1381 StringBuffer buffer = new StringBuffer(encrypted.length() + 100);
\r
1382 buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""
\r
1383 + dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");
\r
1384 buffer.append("contentEditable=\"false\" alt=\"");
\r
1385 buffer.append(encrypted);
\r
1386 buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png") +"\""));
\r
1387 Global.cryptCounter++;
\r
1388 buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");
\r
1389 buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");
\r
1390 buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString()
\r
1391 +"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&apos;")+"\\');\"");
\r
1392 buffer.append("style=\"display:block\" />");
\r
1394 String script_start = new String(
\r
1395 "document.execCommand('insertHtml', false, '");
\r
1396 String script_end = new String("');");
\r
1397 browser.page().mainFrame().evaluateJavaScript(
\r
1398 script_start + buffer.toString() + script_end);
\r
1402 // Insert a hyperlink
\r
1403 public void insertLink() {
\r
1404 logger.log(logger.EXTREME, "Inserting link");
\r
1405 String text = browser.selectedText();
\r
1406 if (text.trim().equalsIgnoreCase(""))
\r
1409 InsertLinkDialog dialog = new InsertLinkDialog(insertHyperlink);
\r
1410 if (currentHyperlink != null && currentHyperlink != "") {
\r
1411 dialog.setUrl(currentHyperlink);
\r
1414 if (!dialog.okPressed()) {
\r
1415 logger.log(logger.EXTREME, "Insert link canceled");
\r
1419 // Take care of inserting new links
\r
1420 if (insertHyperlink) {
\r
1421 String selectedText = browser.selectedText();
\r
1422 if (dialog.getUrl().trim().equals(""))
\r
1424 logger.log(logger.EXTREME, "Inserting link on text "+selectedText);
\r
1425 logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim());
\r
1426 String dUrl = StringUtils.replace(dialog.getUrl().trim(), "'", "\\'");
\r
1427 String url = "<a href=\"" +dUrl
\r
1428 +"\" title=" +dUrl
\r
1429 +" >"+selectedText +"</a>";
\r
1430 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1431 browser.page().mainFrame().evaluateJavaScript(script);
\r
1435 // Edit existing links
\r
1436 String js = new String( "function getCursorPos() {"
\r
1438 +"if (window.getSelection) {"
\r
1439 +" var selObj = window.getSelection();"
\r
1440 +" var selRange = selObj.getRangeAt(0);"
\r
1441 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1442 +" while(workingNode != null) { "
\r
1443 +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');"
\r
1444 +" workingNode = workingNode.parentNode;"
\r
1447 +"} getCursorPos();");
\r
1448 browser.page().mainFrame().evaluateJavaScript(js);
\r
1450 if (!dialog.getUrl().trim().equals("")) {
\r
1456 js = new String( "function getCursorPos() {"
\r
1458 +"if (window.getSelection) {"
\r
1459 +" var selObj = window.getSelection();"
\r
1460 +" var selRange = selObj.getRangeAt(0);"
\r
1461 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1462 +" while(workingNode != null) { "
\r
1463 +" if (workingNode.nodeName.toLowerCase()=='a') { "
\r
1464 +" workingNode.removeAttribute('href');"
\r
1465 +" workingNode.removeAttribute('title');"
\r
1466 +" var text = document.createTextNode(workingNode.innerText);"
\r
1467 +" workingNode.parentNode.insertBefore(text, workingNode);"
\r
1468 +" workingNode.parentNode.removeChild(workingNode);"
\r
1470 +" workingNode = workingNode.parentNode;"
\r
1473 +"} getCursorPos();");
\r
1474 browser.page().mainFrame().evaluateJavaScript(js);
\r
1482 // Insert a hyperlink
\r
1483 public void insertLatex() {
\r
1486 public void editLatex(String guid) {
\r
1487 logger.log(logger.EXTREME, "Inserting latex");
\r
1488 String text = browser.selectedText();
\r
1489 if (text.trim().equalsIgnoreCase(" ") || text.trim().equalsIgnoreCase("")) {
\r
1490 InsertLatexImage dialog = new InsertLatexImage();
\r
1491 if (guid != null) {
\r
1492 String formula = conn.getNoteTable().noteResourceTable.getNoteSourceUrl(guid).replace("http://latex.codecogs.com/gif.latex?", "");
\r
1493 dialog.setFormula(formula);
\r
1496 if (!dialog.okPressed()) {
\r
1497 logger.log(logger.EXTREME, "Edit LaTex canceled");
\r
1500 text = dialog.getFormula().trim();
\r
1502 blockApplication.emit(this);
\r
1503 logger.log(logger.EXTREME, "Inserting LaTeX formula:" +text);
\r
1505 text = StringUtils.replace(text, "'", "\\'");
\r
1506 String url = "http://latex.codecogs.com/gif.latex?" +text;
\r
1507 logger.log(logger.EXTREME, "Sending request to codecogs --> " + url);
\r
1508 QNetworkAccessManager manager = new QNetworkAccessManager(this);
\r
1509 manager.finished.connect(this, "insertLatexImageReady(QNetworkReply)");
\r
1510 unblockTime = new GregorianCalendar().getTimeInMillis()+5000;
\r
1511 awaitingHttpResponse = true;
\r
1512 manager.get(new QNetworkRequest(new QUrl(url)));
\r
1515 public void insertLatexImageReady(QNetworkReply reply) {
\r
1516 logger.log(logger.EXTREME, "Response received from CodeCogs");
\r
1517 if (reply.error() != NetworkError.NoError)
\r
1521 if (!awaitingHttpResponse)
\r
1524 awaitingHttpResponse = false;
\r
1525 QUrl replyUrl = reply.url();
\r
1526 QByteArray image = reply.readAll();
\r
1528 logger.log(logger.EXTREME, "New image size: " +image.size());
\r
1530 Resource newRes = null;
\r
1533 if (latexGuid == null) {
\r
1534 logger.log(logger.EXTREME, "Creating temporary gif");
\r
1535 path = Global.getFileManager().getResDirPath("latex-temp.gif");
\r
1536 tfile = new QFile(path);
\r
1537 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1538 logger.log(logger.EXTREME, "File Open: " +tfile.errorString());
\r
1539 tfile.write(image);
\r
1540 logger.log(logger.EXTREME, "Bytes writtes: "+tfile.size());
\r
1542 logger.log(logger.EXTREME, "Creating resource");
\r
1544 if (currentNote.getResources() != null || currentNote.getResources().size() > 0)
\r
1545 sequence = currentNote.getResources().size();
\r
1546 newRes = createResource(path,sequence ,"image/gif", false);
\r
1547 QImage pix = new QImage();
\r
1548 pix.loadFromData(image);
\r
1549 newRes.setHeight(new Integer(pix.height()).shortValue());
\r
1550 newRes.setWidth(new Integer(pix.width()).shortValue());
\r
1551 logger.log(logger.EXTREME, "Renaming temporary file to " +newRes.getGuid()+".gif");
\r
1552 path = Global.getFileManager().getResDirPath(newRes.getGuid()+".gif");
\r
1553 tfile.rename(path);
\r
1555 newRes = conn.getNoteTable().noteResourceTable.getNoteResource(latexGuid, false);
\r
1556 path = Global.getFileManager().getResDirPath(newRes.getGuid()+".gif");
\r
1557 tfile = new QFile(path);
\r
1558 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1559 tfile.write(image);
\r
1561 newRes.getData().setBody(image.toByteArray());
\r
1562 // Calculate the new hash value
\r
1565 logger.log(logger.EXTREME, "Generating MD5");
\r
1567 md = MessageDigest.getInstance("MD5");
\r
1568 md.update(image.toByteArray());
\r
1569 byte[] hash = md.digest();
\r
1570 newRes.getData().setBodyHash(hash);
\r
1571 } catch (NoSuchAlgorithmException e) {
\r
1572 e.printStackTrace();
\r
1574 QImage pix = new QImage();
\r
1575 pix.loadFromData(image);
\r
1576 newRes.setHeight(new Integer(pix.height()).shortValue());
\r
1577 newRes.setWidth(new Integer(pix.width()).shortValue());
\r
1578 conn.getNoteTable().noteResourceTable.updateNoteResource(newRes, true);
\r
1581 logger.log(logger.EXTREME, "Setting source: " +replyUrl.toString());
\r
1582 newRes.getAttributes().setSourceURL(replyUrl.toString());
\r
1583 conn.getNoteTable().noteResourceTable.updateNoteSourceUrl(newRes.getGuid(), replyUrl.toString(), true);
\r
1585 for(int i=0; i<currentNote.getResourcesSize(); i++) {
\r
1586 if (currentNote.getResources().get(i).getGuid().equals(newRes.getGuid())) {
\r
1587 currentNote.getResources().remove(i);
\r
1588 i=currentNote.getResourcesSize();
\r
1591 currentNote.getResources().add(newRes);
\r
1594 // do the actual insert into the note. We only do this on new formulas.
\r
1595 if (latexGuid == null) {
\r
1596 StringBuffer buffer = new StringBuffer(100);
\r
1597 String formula = replyUrl.toString().toLowerCase().replace("http://latex.codecogs.com/gif.latex?", "");
\r
1598 buffer.append("<a href=\"latex://"+path.replace("\\", "/")+"\" title=\""+formula+"\""
\r
1600 buffer.append(path.replace("\\", "/"));
\r
1601 buffer.append("\" en-tag=\"en-latex\" type=\"image/gif\""
\r
1602 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1603 +" guid=\"" +newRes.getGuid() +"\""
\r
1606 String script_start = new String("document.execCommand('insertHTML', false, '");
\r
1607 String script_end = new String("');");
\r
1608 browser.page().mainFrame().evaluateJavaScript(
\r
1609 script_start + buffer + script_end);
\r
1611 HtmlTagModifier modifier = new HtmlTagModifier(getContent());
\r
1612 modifier.modifyLatexTagHash(newRes);
\r
1613 String newContent = modifier.getHtml();
\r
1614 setContent(new QByteArray(newContent));
\r
1617 logger.log(logger.EXTREME, "New HTML set\n" +browser.page().currentFrame().toHtml());
\r
1618 QWebSettings.setMaximumPagesInCache(0);
\r
1619 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
1621 browser.page().mainFrame().setHtml(browser.page().mainFrame().toHtml());
\r
1624 // resourceSignal.contentChanged.emit(path);
\r
1626 unblockApplication.emit();
\r
1634 public void insertTable() {
\r
1635 TableDialog dialog = new TableDialog();
\r
1637 if (!dialog.okPressed()) {
\r
1641 int cols = dialog.getCols();
\r
1642 int rows = dialog.getRows();
\r
1643 int width = dialog.getWidth();
\r
1644 boolean percent = dialog.isPercent();
\r
1646 String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();
\r
1648 newHTML = newHTML +"%";
\r
1649 newHTML = newHTML + "\"><tbody>";
\r
1651 for (int i=0; i<rows; i++) {
\r
1652 newHTML = newHTML +"<tr>";
\r
1653 for (int j=0; j<cols; j++) {
\r
1654 newHTML = newHTML +"<td> </td>";
\r
1656 newHTML = newHTML +"</tr>";
\r
1658 newHTML = newHTML+"</tbody></table>";
\r
1660 String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";
\r
1661 browser.page().mainFrame().evaluateJavaScript(script);
\r
1665 // Text content changed
\r
1666 @SuppressWarnings("unused")
\r
1667 private void selectionChanged() {
\r
1668 browser.encryptAction.setEnabled(true);
\r
1669 browser.insertLinkAction.setEnabled(true);
\r
1670 String scriptStart = "var selection_text = (window.getSelection()).toString();"
\r
1671 + "var range = (window.getSelection()).getRangeAt(0);"
\r
1672 + "var parent_html = range.commonAncestorContainer.innerHTML;"
\r
1673 + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"
\r
1674 + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"
\r
1675 + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"
\r
1676 + "var start = parent_html.indexOf(first_text);"
\r
1677 + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"
\r
1678 + "var value = parent_html.substring(start,end);"
\r
1679 + "window.jambi.saveSelectedText(value);" ;
\r
1680 browser.page().mainFrame().evaluateJavaScript(scriptStart);
\r
1684 public void saveSelectedText(String text) {
\r
1685 boolean enabled = true;
\r
1686 if (text.trim().length() == 0)
\r
1688 if (text.indexOf("en-tag=\"en-crypt\"") >= 0)
\r
1690 if (text.indexOf("<img en-tag=\"en-media\"") >= 0)
\r
1692 if (text.indexOf("<a en-tag=\"en-media\"") >= 0)
\r
1694 if (text.indexOf("<input ") >= 0)
\r
1697 browser.encryptAction.setEnabled(enabled);
\r
1698 browser.insertLinkAction.setEnabled(enabled);
\r
1699 // selectedText = text;
\r
1702 // Decrypt clicked text
\r
1703 public void decryptText(String id, String text, String hint) {
\r
1704 EnCrypt crypt = new EnCrypt();
\r
1705 String plainText = null;
\r
1706 Calendar currentTime = new GregorianCalendar();
\r
1707 Long l = new Long(currentTime.getTimeInMillis());
\r
1708 String slot = new String(Long.toString(l));
\r
1710 // First, try to decrypt with any keys we already have
\r
1711 for (int i=0; i<Global.passwordRemember.size(); i++) {
\r
1712 plainText = crypt.decrypt(text, Global.passwordRemember.get(i).getFirst(), 64);
\r
1713 if (plainText != null) {
\r
1714 slot = new String(Long.toString(l));
\r
1715 Global.passwordSafe.put(slot, Global.passwordRemember.get(i));
\r
1716 removeEncryption(id, plainText, false, slot);
\r
1722 EnDecryptDialog dialog = new EnDecryptDialog();
\r
1723 dialog.setHint(hint);
\r
1724 while (plainText == null || !dialog.okPressed()) {
\r
1726 if (!dialog.okPressed()) {
\r
1729 plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);
\r
1730 if (plainText == null) {
\r
1731 QMessageBox.warning(this, tr("Incorrect Password"), tr("The password entered is not correct"));
\r
1734 Pair<String,String> passwordPair = new Pair<String,String>();
\r
1735 passwordPair.setFirst(dialog.getPassword());
\r
1736 passwordPair.setSecond(dialog.getHint());
\r
1737 Global.passwordSafe.put(slot, passwordPair);
\r
1738 // removeEncryption(id, plainText.replaceAll("\n", "<br/>"), dialog.permanentlyDecrypt(), slot);
\r
1739 removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);
\r
1740 if (dialog.rememberPassword()) {
\r
1741 Pair<String, String> pair = new Pair<String,String>();
\r
1742 pair.setFirst(dialog.getPassword());
\r
1743 pair.setSecond(dialog.getHint());
\r
1744 Global.passwordRemember.add(pair);
\r
1749 // Get the editor tag line
\r
1750 public TagLineEdit getTagLine() {
\r
1754 // Modify a note's tags
\r
1755 @SuppressWarnings("unused")
\r
1756 private void modifyTags() {
\r
1757 TagAssign tagWindow = new TagAssign(allTags, currentTags, !conn.getNotebookTable().isLinked(currentNote.getNotebookGuid()));
\r
1759 if (tagWindow.okClicked()) {
\r
1760 currentTags.clear();
\r
1761 StringBuffer tagDisplay = new StringBuffer();
\r
1763 List<QListWidgetItem> newTags = tagWindow.getTagList()
\r
1765 for (int i = 0; i < newTags.size(); i++) {
\r
1766 currentTags.add(newTags.get(i).text());
\r
1767 tagDisplay.append(newTags.get(i).text());
\r
1768 if (i < newTags.size() - 1) {
\r
1769 tagDisplay.append(Global.tagDelimeter + " ");
\r
1772 tagEdit.setText(tagDisplay.toString());
\r
1773 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1777 // Tag line has been modified by typing text
\r
1778 @SuppressWarnings("unused")
\r
1779 private void modifyTagsTyping() {
\r
1780 String completionText = "";
\r
1781 if (tagEdit.currentCompleterSelection != null && !tagEdit.currentCompleterSelection.equals("")) {
\r
1782 completionText = tagEdit.currentCompleterSelection;
\r
1783 tagEdit.currentCompleterSelection = "";
\r
1786 if (tagEdit.text().equalsIgnoreCase(saveTagList))
\r
1789 // We know something has changed...
\r
1790 String oldTagArray[] = saveTagList.split(Global.tagDelimeter);
\r
1791 String newTagArray[];
\r
1792 if (!completionText.equals("")) {
\r
1793 String before = tagEdit.text().substring(0,tagEdit.cursorPosition());
\r
1794 int lastDelimiter = before.lastIndexOf(Global.tagDelimeter);
\r
1795 if (lastDelimiter > 0)
\r
1796 before = before.substring(0,before.lastIndexOf(Global.tagDelimeter));
\r
1799 String after = tagEdit.text().substring(tagEdit.cursorPosition());
\r
1800 newTagArray = (before+Global.tagDelimeter+completionText+Global.tagDelimeter+after).split(Global.tagDelimeter);
\r
1803 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1806 // Remove any traling or leading blanks
\r
1807 for (int i=0; i<newTagArray.length; i++)
\r
1808 newTagArray[i] = newTagArray[i].trim().replaceAll("^\\s+", "");;
\r
1810 // Remove any potential duplicates from the new list
\r
1811 for (int i=0; i<newTagArray.length; i++) {
\r
1812 boolean foundOnce = false;
\r
1813 for (int j=0; j<newTagArray.length; j++) {
\r
1814 if (newTagArray[j].equalsIgnoreCase(newTagArray[i])) {
\r
1818 newTagArray[j] = "";
\r
1823 List<String> newTagList = new ArrayList<String>();
\r
1824 List<String> oldTagList = new ArrayList<String>();
\r
1826 for (int i = 0; i < oldTagArray.length; i++)
\r
1827 if (!oldTagArray[i].trim().equals(""))
\r
1828 oldTagList.add(oldTagArray[i]);
\r
1829 for (int i = 0; i < newTagArray.length; i++)
\r
1830 if (!newTagArray[i].trim().equals(""))
\r
1831 newTagList.add(newTagArray[i]);
\r
1833 if (conn.getNotebookTable().isLinked(currentNote.getNotebookGuid())) {
\r
1834 for (int i=newTagList.size()-1; i>=0; i--) {
\r
1835 boolean found = false;
\r
1836 for (int j=0; j<allTags.size(); j++) {
\r
1837 if (allTags.get(j).getName().equalsIgnoreCase(newTagList.get(i))) {
\r
1843 newTagList.remove(i);
\r
1847 // Let's cleanup the appearance of the tag list
\r
1848 Collections.sort(newTagList);
\r
1849 String newDisplay = "";
\r
1850 for (int i=0; i<newTagList.size(); i++) {
\r
1851 newDisplay = newDisplay+newTagList.get(i);
\r
1852 if (i<newTagList.size()-1)
\r
1853 newDisplay = newDisplay+Global.tagDelimeter +" ";
\r
1855 tagEdit.blockSignals(true);
\r
1856 tagEdit.setText(newDisplay);
\r
1857 tagEdit.blockSignals(false);
\r
1859 // We now have lists of the new & old. Remove duplicates. If all
\r
1860 // are removed from both then nothing has really changed
\r
1861 for (int i = newTagList.size() - 1; i >= 0; i--) {
\r
1862 String nTag = newTagList.get(i);
\r
1863 for (int j = oldTagList.size() - 1; j >= 0; j--) {
\r
1864 String oTag = oldTagList.get(j);
\r
1865 if (oTag.equalsIgnoreCase(nTag)) {
\r
1866 oldTagList.remove(j);
\r
1867 newTagList.remove(i);
\r
1873 if (oldTagList.size() != 0 || newTagList.size() != 0) {
\r
1874 currentTags.clear();
\r
1875 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1876 for (int i = 0; i < newTagArray.length; i++)
\r
1877 if (!newTagArray[i].trim().equals(""))
\r
1878 currentTags.add(newTagArray[i].trim());
\r
1880 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1885 // Tab button was pressed
\r
1886 public void tabPressed() {
\r
1887 if (insideEncryption)
\r
1889 if (!insideList && !insideTable) {
\r
1890 String script_start = new String(
\r
1891 "document.execCommand('insertHtml', false, ' ');");
\r
1892 browser.page().mainFrame().evaluateJavaScript(script_start);
\r
1898 if (insideTable) {
\r
1899 String js = new String( "function getCursorPosition() { "
\r
1900 +" var selObj = window.getSelection();"
\r
1901 +" var selRange = selObj.getRangeAt(0);"
\r
1902 +" var workingNode = window.getSelection().anchorNode;"
\r
1903 +" var rowCount = 0;"
\r
1904 +" var colCount = 0;"
\r
1905 +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
\r
1906 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
1907 +" rowCount = rowCount+1;"
\r
1909 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
1910 +" colCount = colCount+1;"
\r
1912 +" if (workingNode.previousSibling != null)"
\r
1913 +" workingNode = workingNode.previousSibling;"
\r
1915 +" workingNode = workingNode.parentNode;"
\r
1917 +" var nodes = workingNode.getElementsByTagName('tr');"
\r
1918 +" var tableRows = nodes.length;"
\r
1919 +" nodes = nodes[0].getElementsByTagName('td');"
\r
1920 +" var tableColumns = nodes.length;"
\r
1921 +" window.jambi.setTableCursorPositionTab(rowCount, colCount, tableRows, tableColumns);"
\r
1922 +"} getCursorPosition();");
\r
1923 browser.page().mainFrame().evaluateJavaScript(js);
\r
1927 // If a user presses tab from within a table
\r
1928 public void setTableCursorPositionTab(int currentRow, int currentCol, int tableRows, int tableColumns) {
\r
1929 if (tableRows == currentRow && currentCol == tableColumns) {
\r
1932 KeyboardModifiers modifiers = new KeyboardModifiers(KeyboardModifier.NoModifier);
\r
1933 QKeyEvent right = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Right.value(), modifiers);
\r
1934 QKeyEvent end = new QKeyEvent(Type.KeyPress, Qt.Key.Key_End.value(), modifiers);
\r
1935 QKeyEvent end2 = new QKeyEvent(Type.KeyPress, Qt.Key.Key_End.value(), modifiers);
\r
1936 getBrowser().focusWidget();
\r
1937 QCoreApplication.postEvent(getBrowser(), end);
\r
1938 QCoreApplication.postEvent(getBrowser(), right);
\r
1939 QCoreApplication.postEvent(getBrowser(), end2);
\r
1942 public void backtabPressed() {
\r
1943 if (insideEncryption)
\r
1947 if (insideTable) {
\r
1948 String js = new String( "function getCursorPosition() { "
\r
1949 +" var selObj = window.getSelection();"
\r
1950 +" var selRange = selObj.getRangeAt(0);"
\r
1951 +" var workingNode = window.getSelection().anchorNode;"
\r
1952 +" var rowCount = 0;"
\r
1953 +" var colCount = 0;"
\r
1954 +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
\r
1955 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
1956 +" rowCount = rowCount+1;"
\r
1958 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
1959 +" colCount = colCount+1;"
\r
1961 +" if (workingNode.previousSibling != null)"
\r
1962 +" workingNode = workingNode.previousSibling;"
\r
1964 +" workingNode = workingNode.parentNode;"
\r
1966 +" var nodes = workingNode.getElementsByTagName('tr');"
\r
1967 +" var tableRows = nodes.length;"
\r
1968 +" nodes = nodes[0].getElementsByTagName('td');"
\r
1969 +" var tableColumns = nodes.length;"
\r
1970 +" window.jambi.setTableCursorPositionBackTab(rowCount, colCount, tableRows, tableColumns);"
\r
1971 +"} getCursorPosition();");
\r
1972 browser.page().mainFrame().evaluateJavaScript(js);
\r
1977 // If a user presses backtab from within a table
\r
1978 public void setTableCursorPositionBackTab(int currentRow, int currentCol, int tableRows, int tableColumns) {
\r
1979 if (currentRow == 1 && currentCol == 1) {
\r
1982 KeyboardModifiers modifiers = new KeyboardModifiers(KeyboardModifier.NoModifier);
\r
1983 QKeyEvent left = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Left.value(), modifiers);
\r
1984 QKeyEvent home = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Home.value(), modifiers);
\r
1985 getBrowser().focusWidget();
\r
1986 QCoreApplication.postEvent(getBrowser(), home);
\r
1987 QCoreApplication.postEvent(getBrowser(), left);
\r
1991 public void setInsideList() {
\r
1992 insideList = true;
\r
1995 // The title has been edited
\r
1996 @SuppressWarnings("unused")
\r
1997 private void titleEdited() {
\r
1998 // If we don't have a good note, or if the current title
\r
1999 // matches the old title then we don't need to do anything
\r
2000 if (currentNote == null)
\r
2002 if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))
\r
2005 // If we have a real change, we need to save it.
\r
2006 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text());
\r
2007 currentNote.setTitle(titleLabel.text());
\r
2008 saveNoteTitle = titleLabel.text();
\r
2012 // Set the list of note tags
\r
2013 public void setAllTags(List<Tag> l) {
\r
2015 tagEdit.setTagList(l);
\r
2018 // Setter for the current tags
\r
2019 public void setCurrentTags(List<String> s) {
\r
2023 // Save the list of notebooks
\r
2024 public void setNotebookList(List<Notebook> n) {
\r
2026 loadNotebookList();
\r
2029 // Load the notebook list and select the current notebook
\r
2030 private void loadNotebookList() {
\r
2031 if (notebookBox.count() != 0)
\r
2032 notebookBox.clear();
\r
2033 if (notebookList == null)
\r
2036 for (int i = 0; i < notebookList.size(); i++) {
\r
2037 notebookBox.addItem(notebookList.get(i).getName());
\r
2038 if (currentNote != null) {
\r
2039 if (currentNote.getNotebookGuid().equals(
\r
2040 notebookList.get(i).getGuid())) {
\r
2041 notebookBox.setCurrentIndex(i);
\r
2048 // Set the notebook for a note
\r
2049 public void setNotebook(String notebook) {
\r
2050 currentNote.setNotebookGuid(notebook);
\r
2051 loadNotebookList();
\r
2054 // Get the contents of the editor
\r
2055 public String getContent() {
\r
2056 return browser.page().currentFrame().toHtml();
\r
2059 // The note contents have changed
\r
2060 public void contentChanged() {
\r
2061 String content = getContent();
\r
2063 // This puts in a 1/2 second delay
\r
2064 // before updating the source editor.
\r
2065 // It improves response when someone is doing
\r
2066 // frequent updates on a large note.
\r
2067 // If the source editor isn't visible, then there
\r
2068 // is no point to doing any of this.
\r
2069 if (sourceEdit.isVisible()) {
\r
2070 setSourceTimer.stop();
\r
2071 setSourceTimer.setInterval(500);
\r
2072 setSourceTimer.setSingleShot(true);
\r
2073 setSourceTimer.start();
\r
2077 noteSignal.noteChanged.emit(currentNote.getGuid(), content);
\r
2080 // The notebook selection has changed
\r
2081 @SuppressWarnings("unused")
\r
2082 private void notebookChanged() {
\r
2083 boolean changed = false;
\r
2084 String n = notebookBox.currentText();
\r
2085 for (int i = 0; i < notebookList.size(); i++) {
\r
2086 if (n.equals(notebookList.get(i).getName())) {
\r
2087 if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {
\r
2088 String guid = conn.getNotebookTable().findNotebookByName(n);
\r
2089 if (conn.getNotebookTable().isLinked(guid)) {
\r
2090 tagEdit.setText("");
\r
2091 noteSignal.tagsChanged.emit(currentNote.getGuid(), new ArrayList<String>());
\r
2092 FilterEditorTags t = new FilterEditorTags(conn, logger);
\r
2093 setAllTags(t.getValidTags(currentNote));
\r
2095 currentNote.setNotebookGuid(notebookList.get(i).getGuid());
\r
2098 i = notebookList.size();
\r
2102 // If the notebook changed, signal the update
\r
2104 noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote
\r
2105 .getNotebookGuid());
\r
2108 // Check the note title
\r
2109 private void checkNoteTitle() {
\r
2110 String text = browser.page().currentFrame().toPlainText();
\r
2111 if (saveNoteTitle == null)
\r
2112 saveNoteTitle = new String();
\r
2113 if (saveNoteTitle.trim().equals("") || saveNoteTitle.trim().equals("Untitled Note")) {
\r
2114 int newLine = text.indexOf("\n");
\r
2115 if (newLine > 0) {
\r
2116 text = text.substring(0, newLine);
\r
2117 if (text.trim().equals(""))
\r
2118 text = tr("Untitled Note");
\r
2119 titleLabel.setText(text);
\r
2121 if (text.length() > Constants.EDAM_NOTE_TITLE_LEN_MAX)
\r
2122 titleLabel.setText(text.substring(0, Constants.EDAM_NOTE_TITLE_LEN_MAX));
\r
2124 titleLabel.blockSignals(true);
\r
2125 if (text.trim().equals(""))
\r
2126 titleLabel.setText(tr("Untitled Note"));
\r
2128 titleLabel.setText(text);
\r
2129 titleLabel.blockSignals(false);
\r
2132 if (currentNote != null && titleLabel != null)
\r
2133 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text());
\r
2137 // Return the note contents so we can email them
\r
2138 public String getContentsToEmail() {
\r
2139 return browser.page().currentFrame().toPlainText().trim();
\r
2141 * int body = browser.page().currentFrame().toHtml().indexOf("<body>");
\r
2142 * String temp = browser.page().currentFrame().toHtml(); if (body == -1)
\r
2143 * temp = "<html><body><b>Test</b></body></html>"; else temp =
\r
2144 * "<html>"+temp.substring(body); return temp; // return
\r
2145 * urlEncode(browser.page().currentFrame().toHtml());
\r
2149 // Insert an image into the editor
\r
2150 private void insertImage(QMimeData mime) {
\r
2151 logger.log(logger.EXTREME, "Entering insertImage");
\r
2152 QImage img = (QImage) mime.imageData();
\r
2153 String script_start = new String(
\r
2154 "document.execCommand('insertHTML', false, '");
\r
2155 String script_end = new String("');");
\r
2157 long now = new Date().getTime();
\r
2158 String path = Global.getFileManager().getResDirPath(
\r
2159 (new Long(now).toString()) + ".jpg");
\r
2161 // This block is just a hack to make sure we wait at least 1ms so we
\r
2163 // have collisions on image names
\r
2164 long i = new Date().getTime();
\r
2166 i = new Date().getTime();
\r
2168 // Open the file & write the data
\r
2169 QFile tfile = new QFile(path);
\r
2170 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
2171 if (!img.save(tfile)) {
\r
2177 Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);
\r
2178 if (newRes == null)
\r
2180 currentNote.getResources().add(newRes);
\r
2182 // do the actual insert into the note
\r
2183 StringBuffer buffer = new StringBuffer(100);
\r
2184 buffer.append("<img src=\"");
\r
2185 buffer.append(tfile.fileName());
\r
2186 buffer.append("\" en-tag=en-media type=\"image/jpeg\""
\r
2187 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
2188 +" guid=\"" +newRes.getGuid() +"\""
\r
2189 +" onContextMenu=\"window.jambi.imageContextMenu(&." +tfile.fileName() +"&.);\""
\r
2192 browser.page().mainFrame().evaluateJavaScript(
\r
2193 script_start + buffer + script_end);
\r
2198 // Handle pasting of a note-to-note link
\r
2199 private void handleNoteLink(QMimeData mime) {
\r
2200 for (int i=0; i<mime.urls().size(); i++) {
\r
2201 StringTokenizer tokens = new StringTokenizer(mime.urls().get(i).toString().replace("evernote:///view/", ""), "/");
\r
2202 tokens.nextToken();
\r
2203 tokens.nextToken();
\r
2204 String sid = tokens.nextToken();
\r
2205 String lid = tokens.nextToken();
\r
2207 if (!sid.equals(currentNote.getGuid()) && !lid.equals(currentNote.getGuid())) {
\r
2209 Note note = conn.getNoteTable().getNote(sid, false, false, false, false, false);
\r
2211 note = conn.getNoteTable().getNote(lid, false, false, false, false, false);
\r
2216 // If we've gotten this far, we have a bunch of values. We need to build the link.
\r
2217 StringBuffer url = new StringBuffer(100);
\r
2218 String script_start = new String(
\r
2219 "document.execCommand('insertHtml', false, '");
\r
2220 String script_end = new String("');");
\r
2222 url.append("<a href=\""+mime.urls().get(i).toString() +"\" style=\"color:#69aa35\">");
\r
2223 url.append(note.getTitle());
\r
2224 url.append("</a>");
\r
2225 if (mime.urls().size() > 1)
\r
2226 url.append(" ");
\r
2227 browser.page().mainFrame().evaluateJavaScript(
\r
2228 script_start + url + script_end);
\r
2233 // Handle URLs that are trying to be pasted
\r
2234 public void handleUrls(QMimeData mime) {
\r
2235 logger.log(logger.EXTREME, "Starting handleUrls");
\r
2236 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
2238 List<QUrl> urlList = mime.urls();
\r
2239 String url = new String();
\r
2240 String script_start = new String(
\r
2241 "document.execCommand('createLink', false, '");
\r
2242 String script_end = new String("');");
\r
2244 for (int i = 0; i < urlList.size(); i++) {
\r
2245 url = urlList.get(i).toString();
\r
2246 // Find out what type of file we have
\r
2247 String mimeType = fileNameMap.getContentTypeFor(url);
\r
2249 // If null returned, we need to guess at the file type
\r
2250 if (mimeType == null)
\r
2251 mimeType = "application/"
\r
2252 + url.substring(url.lastIndexOf(".") + 1);
\r
2254 // Check if we have an image or some other type of file
\r
2255 if (url.substring(0, 5).equalsIgnoreCase("file:")
\r
2256 && mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
2257 handleLocalImageURLPaste(mime, mimeType);
\r
2260 String[] type = mimeType.split("/");
\r
2261 boolean valid = validAttachment(type[1]);
\r
2262 boolean smallEnough = checkFileAttachmentSize(url);
\r
2263 if (smallEnough && valid
\r
2264 && url.substring(0, 5).equalsIgnoreCase("file:")
\r
2265 && !mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
2266 handleLocalAttachment(mime, mimeType);
\r
2269 browser.page().mainFrame().evaluateJavaScript(
\r
2270 script_start + url + script_end);
\r
2275 // If a URL being pasted is an image URL, then attach the image
\r
2276 private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {
\r
2277 List<QUrl> urlList = mime.urls();
\r
2278 String url = new String();
\r
2279 String script_start_image = new String(
\r
2280 "document.execCommand('insertHtml', false, '");
\r
2281 String script_end = new String("');");
\r
2282 StringBuffer buffer;
\r
2284 // Copy the image over into the resource directory and create a new resource
\r
2285 // record for each url pasted
\r
2286 for (int i = 0; i < urlList.size(); i++) {
\r
2287 url = urlList.get(i).toString();
\r
2289 Resource newRes = createResource(url, i, mimeType, false);
\r
2290 if (newRes == null)
\r
2292 currentNote.getResources().add(newRes);
\r
2293 buffer = new StringBuffer(100);
\r
2295 // Open the file & write the data
\r
2296 String fileName = Global.getFileManager().getResDirPath(newRes.getGuid());
\r
2297 QFile tfile = new QFile(fileName);
\r
2298 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
2299 tfile.write(newRes.getData().getBody());
\r
2301 buffer.append(script_start_image);
\r
2302 buffer.append("<img src=\"" + FileUtils.toForwardSlashedPath(fileName));
\r
2303 // if (mimeType.equalsIgnoreCase("image/jpg"))
\r
2304 // mimeType = "image/jpeg";
\r
2305 buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""
\r
2306 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
2307 +" guid=\"" +newRes.getGuid() +"\""
\r
2308 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
2310 buffer.append(script_end);
\r
2311 browser.page().mainFrame().evaluateJavaScript(buffer.toString());
\r
2317 // If a URL being pasted is a local file URL, then attach the file
\r
2318 private void handleLocalAttachment(QMimeData mime, String mimeType) {
\r
2319 logger.log(logger.EXTREME, "Attaching local file");
\r
2320 List<QUrl> urlList = mime.urls();
\r
2321 String script_start = new String(
\r
2322 "document.execCommand('insertHtml', false, '");
\r
2323 String script_end = new String("');");
\r
2324 StringBuffer buffer;
\r
2326 String[] type = mimeType.split("/");
\r
2327 String icon = findIcon(type[1]);
\r
2328 if (icon.equals("attachment.png"))
\r
2329 icon = findIcon(type[0]);
\r
2330 buffer = new StringBuffer(100);
\r
2332 for (int i = 0; i < urlList.size(); i++) {
\r
2333 String url = urlList.get(i).toString();
\r
2335 // Start building the HTML
\r
2336 if (icon.equals("attachment.png"))
\r
2337 icon = findIcon(url.substring(url.lastIndexOf(".")+1));
\r
2338 String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));
\r
2340 logger.log(logger.EXTREME, "Creating resource ");
\r
2341 Resource newRes = createResource(url, i, mimeType, true);
\r
2342 if (newRes == null)
\r
2344 logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());
\r
2345 currentNote.getResources().add(newRes);
\r
2347 String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();
\r
2348 // If we have a PDF, we need to setup the preview.
\r
2349 if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {
\r
2350 logger.log(logger.EXTREME, "Setting up PDF preview");
\r
2351 if (newRes.getAttributes() != null &&
\r
2352 newRes.getAttributes().getFileName() != null &&
\r
2353 !newRes.getAttributes().getFileName().trim().equals(""))
\r
2354 fileName = newRes.getGuid()+Global.attachmentNameDelimeter+
\r
2355 newRes.getAttributes().getFileName();
\r
2357 fileName = newRes.getGuid()+".pdf";
\r
2358 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
2359 QFile.OpenMode mode = new QFile.OpenMode();
\r
2360 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2362 QDataStream out = new QDataStream(file);
\r
2363 // Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);
\r
2364 QByteArray binData = new QByteArray(newRes.getData().getBody());
\r
2365 // resBinary = null;
\r
2366 out.writeBytes(binData.toByteArray());
\r
2369 PDFPreview pdfPreview = new PDFPreview();
\r
2370 if (pdfPreview.setupPreview(Global.getFileManager().getResDirPath(fileName), "pdf",0)) {
\r
2371 imageURL = file.fileName() + ".png";
\r
2375 logger.log(logger.EXTREME, "Generating link tags");
\r
2376 buffer.delete(0, buffer.length());
\r
2377 buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");
\r
2378 buffer.append(" onContextMenu=\"window.jambi.imageContextMenu('")
\r
2379 .append(Global.getFileManager().getResDirPath(fileName))
\r
2380 .append("');\" "); buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");
\r
2381 buffer.append("<img src=\"" + imageURL + "\" title=\"" +newRes.getAttributes().getFileName());
\r
2382 buffer.append("\"></img>");
\r
2383 buffer.append("</a>");
\r
2384 browser.page().mainFrame().evaluateJavaScript(
\r
2385 script_start + buffer.toString() + script_end);
\r
2390 private Resource createResource(String url, int sequence, String mime, boolean attachment) {
\r
2391 logger.log(logger.EXTREME, "Inside create resource");
\r
2392 QFile resourceFile;
\r
2393 String urlTest = new QUrl(url).toLocalFile();
\r
2394 if (!urlTest.equals(""))
\r
2396 url = url.replace("/", File.separator);
\r
2397 logger.log(logger.EXTREME, "Reading from file to create resource");
\r
2398 resourceFile = new QFile(url);
\r
2399 resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));
\r
2400 // logger.log(logger.EXTREME, "Error opening file "+url.toString() +": "+resourceFile.errorString());
\r
2401 byte[] fileData = resourceFile.readAll().toByteArray();
\r
2402 resourceFile.close();
\r
2403 if (fileData.length == 0)
\r
2407 logger.log(logger.EXTREME, "Generating MD5");
\r
2408 md = MessageDigest.getInstance("MD5");
\r
2409 md.update(fileData);
\r
2410 byte[] hash = md.digest();
\r
2412 Resource r = new Resource();
\r
2413 Calendar time = new GregorianCalendar();
\r
2414 long prevTime = time.getTimeInMillis();
\r
2415 while (prevTime == time.getTimeInMillis()) {
\r
2416 time = new GregorianCalendar();
\r
2418 r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());
\r
2419 r.setNoteGuid(currentNote.getGuid());
\r
2421 r.setActive(true);
\r
2422 r.setUpdateSequenceNum(0);
\r
2423 r.setWidth((short) 0);
\r
2424 r.setHeight((short) 0);
\r
2425 r.setDuration((short) 0);
\r
2427 Data d = new Data();
\r
2428 d.setBody(fileData);
\r
2429 d.setBodyIsSet(true);
\r
2430 d.setBodyHash(hash);
\r
2431 d.setBodyHashIsSet(true);
\r
2433 d.setSize(fileData.length);
\r
2435 int fileNamePos = url.lastIndexOf(File.separator);
\r
2436 if (fileNamePos == -1)
\r
2437 fileNamePos = url.lastIndexOf("/");
\r
2438 String fileName = url.substring(fileNamePos+1);
\r
2439 ResourceAttributes a = new ResourceAttributes();
\r
2441 a.setAltitudeIsSet(false);
\r
2442 a.setLongitude(0);
\r
2443 a.setLongitudeIsSet(false);
\r
2445 a.setLatitudeIsSet(false);
\r
2446 a.setCameraMake("");
\r
2447 a.setCameraMakeIsSet(false);
\r
2448 a.setCameraModel("");
\r
2449 a.setCameraModelIsSet(false);
\r
2450 a.setAttachment(attachment);
\r
2451 a.setAttachmentIsSet(true);
\r
2452 a.setClientWillIndex(false);
\r
2453 a.setClientWillIndexIsSet(true);
\r
2454 a.setRecoType("");
\r
2455 a.setRecoTypeIsSet(false);
\r
2456 a.setSourceURL(url);
\r
2457 a.setSourceURLIsSet(true);
\r
2458 a.setTimestamp(0);
\r
2459 a.setTimestampIsSet(false);
\r
2460 a.setFileName(fileName);
\r
2461 a.setFileNameIsSet(true);
\r
2462 r.setAttributes(a);
\r
2464 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
2465 logger.log(logger.EXTREME, "Resource created");
\r
2467 } catch (NoSuchAlgorithmException e1) {
\r
2468 e1.printStackTrace();
\r
2474 // find the appropriate icon for an attachment
\r
2475 private String findIcon(String appl) {
\r
2476 appl = appl.toLowerCase();
\r
2477 File f = Global.getFileManager().getImageDirFile(appl + ".png");
\r
2479 return appl+".png";
\r
2480 return "attachment.png";
\r
2483 // Check if the account supports this type of attachment
\r
2484 private boolean validAttachment(String type) {
\r
2485 if (Global.isPremium())
\r
2487 if (type.equalsIgnoreCase("JPG"))
\r
2489 if (type.equalsIgnoreCase("PNG"))
\r
2491 if (type.equalsIgnoreCase("GIF"))
\r
2493 if (type.equalsIgnoreCase("MP3"))
\r
2495 if (type.equalsIgnoreCase("WAV"))
\r
2497 if (type.equalsIgnoreCase("AMR"))
\r
2499 if (type.equalsIgnoreCase("PDF"))
\r
2501 String error = tr("Non-premium accounts can only attach JPG, PNG, GIF, MP3, WAV, AMR, or PDF files.");
\r
2502 QMessageBox.information(this, tr("Non-Premium Account"), error);
\r
2507 // Check the file attachment to be sure it isn't over 25 mb
\r
2508 private boolean checkFileAttachmentSize(String url) {
\r
2509 String fileName = url.substring(8);
\r
2510 QFile resourceFile = new QFile(fileName);
\r
2511 resourceFile.open(new QIODevice.OpenMode(
\r
2512 QIODevice.OpenModeFlag.ReadOnly));
\r
2513 long size = resourceFile.size();
\r
2514 resourceFile.close();
\r
2515 size = size / 1024 / 1024;
\r
2516 if (size < 50 && Global.isPremium())
\r
2521 String error = tr("A file attachment may not exceed 25MB.");
\r
2522 QMessageBox.information(this, tr("Attachment Size"), error);
\r
2527 @SuppressWarnings("unused")
\r
2528 private void createdChanged() {
\r
2529 QDateTime dt = new QDateTime();
\r
2530 dt.setDate(createdDate.date());
\r
2531 dt.setTime(createdTime.time());
\r
2532 noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);
\r
2536 @SuppressWarnings("unused")
\r
2537 private void alteredChanged() {
\r
2538 QDateTime dt = new QDateTime();
\r
2539 dt.setDate(alteredDate.date());
\r
2540 dt.setTime(alteredTime.time());
\r
2541 noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);
\r
2544 @SuppressWarnings("unused")
\r
2545 private void subjectDateTimeChanged() {
\r
2546 QDateTime dt = new QDateTime();
\r
2547 dt.setDate(subjectDate.date());
\r
2548 dt.setTime(subjectTime.time());
\r
2549 noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);
\r
2553 @SuppressWarnings("unused")
\r
2554 private void sourceUrlChanged() {
\r
2555 noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());
\r
2558 @SuppressWarnings("unused")
\r
2559 private void authorChanged() {
\r
2560 noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());
\r
2563 @SuppressWarnings("unused")
\r
2564 private void geoBoxChanged() {
\r
2565 int index = geoBox.currentIndex();
\r
2566 geoBox.setCurrentIndex(0);
\r
2568 GeoDialog box = new GeoDialog();
\r
2569 box.setLongitude(currentNote.getAttributes().getLongitude());
\r
2570 box.setLatitude(currentNote.getAttributes().getLatitude());
\r
2571 box.setAltitude(currentNote.getAttributes().getAltitude());
\r
2573 if (!box.okPressed())
\r
2575 double alt = box.getAltitude();
\r
2576 double lat = box.getLatitude();
\r
2577 double lon = box.getLongitude();
\r
2578 if (alt != currentNote.getAttributes().getAltitude() ||
\r
2579 lon != currentNote.getAttributes().getLongitude() ||
\r
2580 lat != currentNote.getAttributes().getLatitude()) {
\r
2581 noteSignal.geoChanged.emit(currentNote.getGuid(), lon, lat, alt);
\r
2582 currentNote.getAttributes().setAltitude(alt);
\r
2583 currentNote.getAttributes().setLongitude(lon);
\r
2584 currentNote.getAttributes().setLatitude(lat);
\r
2589 noteSignal.geoChanged.emit(currentNote.getGuid(), 0.0, 0.0, 0.0);
\r
2590 currentNote.getAttributes().setAltitude(0.0);
\r
2591 currentNote.getAttributes().setLongitude(0.0);
\r
2592 currentNote.getAttributes().setLatitude(0.0);
\r
2595 if (index == 3 || index == 0) {
\r
2596 QDesktopServices.openUrl(new QUrl("http://maps.google.com/maps?z=6&q="+currentNote.getAttributes().getLatitude() +"," +currentNote.getAttributes().getLongitude()));
\r
2600 // ************************************************************
\r
2601 // * User chose to save an attachment. Pares out the request *
\r
2602 // * into a guid & file. Save the result. *
\r
2603 // ************************************************************
\r
2604 public void downloadAttachment(QNetworkRequest request) {
\r
2606 QFileDialog fd = new QFileDialog(this);
\r
2607 fd.setFileMode(FileMode.AnyFile);
\r
2608 fd.setConfirmOverwrite(true);
\r
2609 fd.setWindowTitle(tr("Save File"));
\r
2610 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2611 fd.setDirectory(System.getProperty("user.home"));
\r
2612 String name = request.url().toString();
\r
2614 int pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2616 guid = name.substring(0, pos).replace("nnres://", "");
\r
2617 name = name.substring(pos +Global.attachmentNameDelimeter.length());
\r
2618 fd.selectFile(name);
\r
2619 pos = name.lastIndexOf('.');
\r
2621 String mimeType = "(*." + name.substring(pos + 1)
\r
2622 + ");; All Files (*)";
\r
2623 fd.setFilter(tr(mimeType));
\r
2629 // Strip URL prefix and base dir
\r
2630 guid = guid.replace("nnres://", "")
\r
2631 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2632 guid = guid.replace("file://", "").replace("/", "")
\r
2633 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2635 pos = guid.lastIndexOf('.');
\r
2637 guid = guid.substring(0,pos);
\r
2638 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2639 name = name.replace('\\', '/');
\r
2640 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2641 QFile saveFile = new QFile(fd.selectedFiles().get(0));
\r
2642 QFile.OpenMode mode = new QFile.OpenMode();
\r
2643 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2644 saveFile.open(mode);
\r
2645 QDataStream saveOut = new QDataStream(saveFile);
\r
2646 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2647 saveOut.writeBytes(binData.toByteArray());
\r
2654 // ************************************************************
\r
2655 // * User chose to save an attachment. Pares out the request *
\r
2656 // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!
\r
2657 // ************************************************************
\r
2658 public void downloadImage(QNetworkRequest request) {
\r
2659 QFileDialog fd = new QFileDialog(this);
\r
2660 fd.setFileMode(FileMode.AnyFile);
\r
2661 fd.setConfirmOverwrite(true);
\r
2662 fd.setWindowTitle(tr("Save File"));
\r
2663 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2664 fd.setDirectory(System.getProperty("user.home"));
\r
2665 String name = request.url().toString();
\r
2666 name = name.replace("nnres://", "");
\r
2667 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
\r
2668 name = name.replace(dPath, "");
\r
2669 int pos = name.lastIndexOf('.');
\r
2670 String guid = name;
\r
2672 String mimeType = "(*." + name.substring(pos + 1)
\r
2673 + ");; All Files (*)";
\r
2674 fd.setFilter(tr(mimeType));
\r
2675 guid = guid.substring(0,pos);
\r
2677 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2679 guid = name.substring(0, pos);
\r
2680 fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));
\r
2682 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2683 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2684 String fileName = fd.selectedFiles().get(0);
\r
2685 QFile saveFile = new QFile(fileName);
\r
2686 QFile.OpenMode mode = new QFile.OpenMode();
\r
2687 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2688 saveFile.open(mode);
\r
2689 QDataStream saveOut = new QDataStream(saveFile);
\r
2690 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2691 saveOut.writeBytes(binData.toByteArray());
\r
2697 // *************************************************************
\r
2698 // * decrypt any hidden text. We could do an XML parse, but
\r
2699 // * it is quicker here just to scan for an <img tag & do the fix
\r
2700 // * the manual way
\r
2701 // *************************************************************
\r
2702 private void removeEncryption(String id, String plainText, boolean permanent, String slot) {
\r
2704 plainText = " <table class=\"en-crypt-temp\" slot=\""
\r
2707 +"border=1 width=100%><tbody><tr><td>"
\r
2708 +plainText+"</td></tr></tbody></table>";
\r
2711 String html = browser.page().mainFrame().toHtml();
\r
2712 String text = html;
\r
2713 int imagePos = html.indexOf("<img");
\r
2715 for ( ;imagePos>0; ) {
\r
2716 // Find the end tag
\r
2717 endPos = text.indexOf(">", imagePos);
\r
2718 String tag = text.substring(imagePos-1,endPos);
\r
2719 if (tag.indexOf("id=\""+id+"\"") > -1) {
\r
2720 text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);
\r
2721 QTextCodec codec = QTextCodec.codecForName("UTF-8");
\r
2722 QByteArray unicode = codec.fromUnicode(text);
\r
2723 setContent(unicode);
\r
2727 imagePos = text.indexOf("<img", imagePos+1);
\r
2732 //****************************************************************
\r
2733 //* Focus shortcuts
\r
2734 //****************************************************************
\r
2735 @SuppressWarnings("unused")
\r
2736 private void focusTitle() {
\r
2737 titleLabel.setFocus();
\r
2739 @SuppressWarnings("unused")
\r
2740 private void focusTag() {
\r
2741 tagEdit.setFocus();
\r
2743 @SuppressWarnings("unused")
\r
2744 private void focusNote() {
\r
2745 browser.setFocus();
\r
2747 @SuppressWarnings("unused")
\r
2748 private void focusAuthor() {
\r
2749 authorLabel.setFocus();
\r
2751 @SuppressWarnings("unused")
\r
2752 private void focusUrl() {
\r
2753 urlLabel.setFocus();
\r
2757 //*****************************************************************
\r
2758 //* Set the document background color
\r
2759 //*****************************************************************
\r
2760 public void setBackgroundColor(String color) {
\r
2761 String js = "function changeBackground(color) {"
\r
2762 +"document.body.style.background = color;"
\r
2764 +"changeBackground('" +color+"');";
\r
2765 browser.page().mainFrame().evaluateJavaScript(js);
\r
2770 //****************************************************************
\r
2771 //* MicroFocus changed
\r
2772 //****************************************************************
\r
2773 private void microFocusChanged() {
\r
2774 boldButton.setDown(false);
\r
2775 italicButton.setDown(false);
\r
2776 underlineButton.setDown(false);
\r
2777 browser.openAction.setEnabled(false);
\r
2778 browser.downloadAttachment.setEnabled(false);
\r
2779 browser.downloadImage.setEnabled(false);
\r
2780 browser.rotateImageLeft.setEnabled(false);
\r
2781 browser.rotateImageRight.setEnabled(false);
\r
2782 browser.insertTableAction.setEnabled(true);
\r
2783 browser.deleteTableColumnAction.setEnabled(false);
\r
2784 browser.insertTableRowAction.setEnabled(false);
\r
2785 browser.insertTableColumnAction.setEnabled(false);
\r
2786 browser.deleteTableRowAction.setEnabled(false);
\r
2787 browser.insertLinkAction.setText(tr("Insert Hyperlink"));
\r
2788 insertHyperlink = true;
\r
2789 currentHyperlink ="";
\r
2790 insideList = false;
\r
2791 insideTable = false;
\r
2792 insideEncryption = false;
\r
2793 forceTextPaste = false;
\r
2795 String js = new String( "function getCursorPos() {"
\r
2797 +"if (window.getSelection) {"
\r
2798 +" var selObj = window.getSelection();"
\r
2799 +" var selRange = selObj.getRangeAt(0);"
\r
2800 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2801 +" while(workingNode != null) { "
\r
2802 // +" window.jambi.printNode(workingNode.nodeName);"
\r
2803 +" if (workingNode.nodeName=='TABLE') { if (workingNode.getAttribute('class').toLowerCase() == 'en-crypt-temp') window.jambi.insideEncryption(); }"
\r
2804 +" if (workingNode.nodeName=='B') window.jambi.boldActive();"
\r
2805 +" if (workingNode.nodeName=='I') window.jambi.italicActive();"
\r
2806 +" if (workingNode.nodeName=='U') window.jambi.underlineActive();"
\r
2807 +" if (workingNode.nodeName=='UL') window.jambi.setInsideList();"
\r
2808 +" if (workingNode.nodeName=='OL') window.jambi.setInsideList();"
\r
2809 +" if (workingNode.nodeName=='LI') window.jambi.setInsideList();"
\r
2810 +" if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"
\r
2811 +" 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);}}"
\r
2812 +" if (workingNode.nodeName=='SPAN') {"
\r
2813 +" if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"
\r
2815 +" workingNode = workingNode.parentNode;"
\r
2818 +"} getCursorPos();");
\r
2819 browser.page().mainFrame().evaluateJavaScript(js);
\r
2822 public void printNode(String n) {
\r
2823 System.out.println("Node Vaule: " +n);
\r
2826 public void insideEncryption() {
\r
2827 insideEncryption = true;
\r
2831 //****************************************************************
\r
2832 //* Insert a table row
\r
2833 //****************************************************************
\r
2834 public void insertTableRow() {
\r
2836 String js = new String( "function insertTableRow() {"
\r
2837 +" var selObj = window.getSelection();"
\r
2838 +" var selRange = selObj.getRangeAt(0);"
\r
2839 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2840 +" var cellCount = 0;"
\r
2841 +" while(workingNode != null) { "
\r
2842 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2843 +" row = document.createElement('TR');"
\r
2844 +" var nodes = workingNode.getElementsByTagName('td');"
\r
2845 +" for (j=0; j<nodes.length; j=j+1) {"
\r
2846 +" cell = document.createElement('TD');"
\r
2847 +" cell.innerHTML=' ';"
\r
2848 +" row.appendChild(cell);"
\r
2850 +" workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"
\r
2853 +" workingNode = workingNode.parentNode;"
\r
2855 +"} insertTableRow();");
\r
2856 browser.page().mainFrame().evaluateJavaScript(js);
\r
2860 public void insertTableColumn() {
\r
2861 String js = new String( "function insertTableColumn() {"
\r
2862 +" var selObj = window.getSelection();"
\r
2863 +" var selRange = selObj.getRangeAt(0);"
\r
2864 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2865 +" var current = 0;"
\r
2866 +" while (workingNode.nodeName.toLowerCase() != 'table' && workingNode != null) {"
\r
2867 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
2868 +" var td = workingNode;"
\r
2869 +" while (td.previousSibling != null) { "
\r
2870 +" current = current+1; td = td.previousSibling;"
\r
2873 +" workingNode = workingNode.parentNode; "
\r
2875 +" if (workingNode == null) return;"
\r
2876 +" for (var i=0; i<workingNode.rows.length; i++) { "
\r
2877 +" var cell = workingNode.rows[i].insertCell(current+1); "
\r
2878 +" cell.innerHTML = ' '; "
\r
2880 +"} insertTableColumn();");
\r
2881 browser.page().mainFrame().evaluateJavaScript(js);
\r
2885 //****************************************************************
\r
2886 //* Delete a table row
\r
2887 //****************************************************************
\r
2888 public void deleteTableRow() {
\r
2890 String js = new String( "function deleteTableRow() {"
\r
2891 +" var selObj = window.getSelection();"
\r
2892 +" var selRange = selObj.getRangeAt(0);"
\r
2893 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2894 +" var cellCount = 0;"
\r
2895 +" while(workingNode != null) { "
\r
2896 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2897 +" workingNode.parentNode.removeChild(workingNode);"
\r
2900 +" workingNode = workingNode.parentNode;"
\r
2902 +"} deleteTableRow();");
\r
2903 browser.page().mainFrame().evaluateJavaScript(js);
\r
2907 public void deleteTableColumn() {
\r
2908 String js = new String( "function deleteTableColumn() {"
\r
2909 +" var selObj = window.getSelection();"
\r
2910 +" var selRange = selObj.getRangeAt(0);"
\r
2911 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2912 +" var current = 0;"
\r
2913 +" while (workingNode.nodeName.toLowerCase() != 'table' && workingNode != null) {"
\r
2914 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
2915 +" var td = workingNode;"
\r
2916 +" while (td.previousSibling != null) { "
\r
2917 +" current = current+1; td = td.previousSibling;"
\r
2920 +" workingNode = workingNode.parentNode; "
\r
2922 +" if (workingNode == null) return;"
\r
2923 +" for (var i=0; i<workingNode.rows.length; i++) { "
\r
2924 +" workingNode.rows[i].deleteCell(current); "
\r
2926 +"} deleteTableColumn();");
\r
2927 browser.page().mainFrame().evaluateJavaScript(js);
\r
2932 public void setInsideTable() {
\r
2933 browser.insertTableRowAction.setEnabled(true);
\r
2934 browser.insertTableColumnAction.setEnabled(true);
\r
2935 browser.deleteTableRowAction.setEnabled(true);
\r
2936 browser.deleteTableColumnAction.setEnabled(true);
\r
2937 browser.insertTableAction.setEnabled(false);
\r
2938 browser.encryptAction.setEnabled(false);
\r
2939 insideTable = true;
\r
2942 public void setInsideLink(String link) {
\r
2943 browser.insertLinkAction.setText(tr("Edit Hyperlink"));
\r
2944 currentHyperlink = link;
\r
2945 insertHyperlink = false;
\r
2948 public void italicActive() {
\r
2949 italicButton.setDown(true);
\r
2951 public void boldActive() {
\r
2952 boldButton.setDown(true);
\r
2954 public void underlineActive() {
\r
2955 underlineButton.setDown(true);
\r
2957 public void forceTextPaste() {
\r
2958 forceTextPaste = true;
\r
2960 public void imageContextMenu(String f) {
\r
2961 browser.downloadImage.setEnabled(true);
\r
2962 browser.rotateImageRight.setEnabled(true);
\r
2963 browser.rotateImageLeft.setEnabled(true);
\r
2964 browser.openAction.setEnabled(true);
\r
2967 public void rotateImageRight() {
\r
2968 QWebSettings.setMaximumPagesInCache(0);
\r
2969 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2970 QImage image = new QImage(selectedFile);
\r
2971 QMatrix matrix = new QMatrix();
\r
2972 matrix.rotate( 90.0 );
\r
2973 image = image.transformed(matrix);
\r
2974 image.save(selectedFile);
\r
2975 QWebSettings.setMaximumPagesInCache(0);
\r
2976 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2977 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2980 resourceSignal.contentChanged.emit(selectedFile);
\r
2983 public void rotateImageLeft() {
\r
2984 QImage image = new QImage(selectedFile);
\r
2985 QMatrix matrix = new QMatrix();
\r
2986 matrix.rotate( -90.0 );
\r
2987 image = image.transformed(matrix);
\r
2988 image.save(selectedFile);
\r
2989 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2992 resourceSignal.contentChanged.emit(selectedFile);
\r
2994 public void resourceContextMenu(String f) {
\r
2995 browser.downloadAttachment.setEnabled(true);
\r
2996 browser.openAction.setEnabled(true);
\r
2999 public void latexContextMenu(String f) {
\r
3000 browser.downloadImage.setEnabled(true);
\r
3001 browser.rotateImageRight.setEnabled(true);
\r
3002 browser.rotateImageLeft.setEnabled(true);
\r
3003 browser.openAction.setEnabled(true);
\r
3007 //****************************************************************
\r
3008 //* Apply CSS style to specified word
\r
3009 //****************************************************************
\r
3010 /* public void applyStyleToWords(String word, String style) {
\r
3011 QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");
\r
3012 script.open(OpenModeFlag.ReadOnly);
\r
3013 String s = script.readAll().toString();
\r
3014 String js = new String(s +" findit('"+word+"', '"+style+"');");
\r
3015 browser.page().mainFrame().evaluateJavaScript(js);
\r
3016 System.out.println(getContent());
\r
3019 //****************************************************************
\r
3020 //* Someone tried to paste a resource between notes, so we need *
\r
3021 //* to do some special handling. *
\r
3022 //****************************************************************
\r
3023 private String fixInternotePaste(String text) {
\r
3024 logger.log(logger.EXTREME, "Fixing internote paste");
\r
3025 String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");
\r
3026 return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");
\r
3028 private String fixInternotePasteSearch(String text, String type, String locTag) {
\r
3030 // First, let's fix the images.
\r
3031 int startPos = text.indexOf(type);
\r
3033 for (; startPos>=0;) {
\r
3034 endPos = text.indexOf(">", startPos+1);
\r
3035 String segment = text.substring(startPos, endPos);
\r
3036 if (segment.indexOf("en-tag") > -1) {
\r
3037 String newSegment = segment;
\r
3039 int guidStartPos = segment.indexOf("guid=\"");
\r
3040 int guidEndPos = segment.indexOf("\"", guidStartPos+7);
\r
3041 String guid = segment.substring(guidStartPos+6,guidEndPos);
\r
3043 int mimeStartPos = segment.indexOf("type");
\r
3044 int mimeEndPos = segment.indexOf("\"", mimeStartPos+7);
\r
3045 String mime = segment.substring(mimeStartPos+6,mimeEndPos);
\r
3047 int srcStartPos = segment.indexOf("src");
\r
3048 int srcEndPos = segment.indexOf("\"", srcStartPos+6);
\r
3049 String src = segment.substring(srcStartPos+5,srcEndPos);
\r
3051 Calendar currentTime = new GregorianCalendar();
\r
3052 Long l = new Long(currentTime.getTimeInMillis());
\r
3053 long prevTime = l;
\r
3054 while (l==prevTime) {
\r
3055 currentTime = new GregorianCalendar();
\r
3056 l= new Long(currentTime.getTimeInMillis());
\r
3059 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
3060 // if r==null, then the image doesn't exist (it was probably cut out of another note, so
\r
3061 // we need to recereate it
\r
3063 r = createResource(src, 1, mime, false);
\r
3067 String randint = new String(Long.toString(l));
\r
3068 String extension = null;
\r
3069 if (r.getMime()!= null) {
\r
3070 extension = r.getMime().toLowerCase();
\r
3071 if (extension.indexOf("/")>-1)
\r
3072 extension = extension.substring(extension.indexOf("/")+1);
\r
3074 String newFile = randint;
\r
3075 if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")
\r
3076 if (!locTag.startsWith("src"))
\r
3077 newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();
\r
3078 r.setNoteGuid(currentNote.getGuid());
\r
3080 r.setGuid(randint);
\r
3081 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
3082 QFile f = new QFile(Global.getFileManager().getResDirPath(newFile));
\r
3083 QByteArray bin = new QByteArray(r.getData().getBody());
\r
3084 f.open(QFile.OpenModeFlag.WriteOnly);
\r
3087 newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);
\r
3088 currentNote.getResources().add(r);
\r
3090 int startSrcPos = newSegment.indexOf(locTag);
\r
3091 int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);
\r
3093 if (locTag.startsWith("src")) {
\r
3094 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
3095 newSegment = newSegment.replace(source,
\r
3096 FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath(newFile)));
\r
3098 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
3099 newSegment = newSegment.replace(source, newFile);
\r
3102 text = text.substring(0,startPos) + newSegment + text.substring(endPos);
\r
3104 startPos = text.indexOf(type, startPos+1);
\r
3110 public void nextPage(String file) {
\r
3111 logger.log(logger.EXTREME, "Starting nextPage()");
\r
3113 Integer pageNumber;
\r
3114 if (previewPageList.containsKey(file))
\r
3115 pageNumber = previewPageList.get(file)+1;
\r
3118 previewPageList.remove(file);
\r
3119 previewPageList.put(file, pageNumber);
\r
3120 PDFPreview pdfPreview = new PDFPreview();
\r
3121 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
3122 if (goodPreview) {
\r
3124 // String html = getContent();
\r
3125 QWebSettings.setMaximumPagesInCache(0);
\r
3126 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
3127 // browser.setContent(new QByteArray());
\r
3128 browser.setHtml(browser.page().mainFrame().toHtml());
\r
3130 // browser.setContent(new QByteArray(html));
\r
3131 // browser.triggerPageAction(WebAction.Reload);
\r
3132 // pdfMouseOver(selectedFile);
\r
3136 public void previousPage(String file) {
\r
3137 logger.log(logger.EXTREME, "Starting previousPage()");
\r
3139 Integer pageNumber;
\r
3140 if (previewPageList.containsKey(file))
\r
3141 pageNumber = previewPageList.get(file)-1;
\r
3144 previewPageList.remove(file);
\r
3145 previewPageList.put(file, pageNumber);
\r
3146 PDFPreview pdfPreview = new PDFPreview();
\r
3147 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
3148 if (goodPreview) {
\r
3150 // String html = getContent();
\r
3151 QWebSettings.setMaximumPagesInCache(0);
\r
3152 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
3153 browser.setHtml(browser.page().mainFrame().toHtml());
\r
3155 // browser.setContent(new QByteArray(html));
\r
3156 // browser.triggerPageAction(WebAction.Reload);
\r
3160 /* public void pdfMouseOver(String name) {
\r
3162 if (previewPageList.containsKey(selectedFile))
\r
3163 pageNumber = previewPageList.get(selectedFile)+1;
\r
3167 if (pageNumber <= 1)
\r
3168 browser.previousPageAction.setEnabled(false);
\r
3170 browser.previousPageAction.setEnabled(true);
\r
3172 PDFPreview pdf = new PDFPreview();
\r
3173 int totalPages = pdf.getPageCount(name);
\r
3174 if (previewPageList.containsKey(selectedFile))
\r
3175 pageNumber = previewPageList.get(selectedFile)+1;
\r
3178 if (totalPages > pageNumber)
\r
3179 browser.nextPageAction.setEnabled(true);
\r
3181 browser.nextPageAction.setEnabled(false);
\r
3185 public void pdfMouseOut() {
\r
3186 // browser.nextPageAction.setVisible(false);
\r
3187 // browser.previousPageAction.setVisible(false);
\r
3191 @SuppressWarnings("unused")
\r
3192 private void toggleUndoVisible(Boolean toggle) {
\r
3193 undoAction.setVisible(toggle);
\r
3194 Global.saveEditorButtonsVisible("undo", toggle);
\r
3196 @SuppressWarnings("unused")
\r
3197 private void toggleRedoVisible(Boolean toggle) {
\r
3198 redoAction.setVisible(toggle);
\r
3199 Global.saveEditorButtonsVisible("redo", toggle);
\r
3201 @SuppressWarnings("unused")
\r
3202 private void toggleCutVisible(Boolean toggle) {
\r
3203 cutAction.setVisible(toggle);
\r
3204 Global.saveEditorButtonsVisible("cut", toggle);
\r
3206 @SuppressWarnings("unused")
\r
3207 private void toggleCopyVisible(Boolean toggle) {
\r
3208 copyAction.setVisible(toggle);
\r
3209 Global.saveEditorButtonsVisible("copy", toggle);
\r
3211 @SuppressWarnings("unused")
\r
3212 private void togglePasteVisible(Boolean toggle) {
\r
3213 pasteAction.setVisible(toggle);
\r
3214 Global.saveEditorButtonsVisible("paste", toggle);
\r
3216 @SuppressWarnings("unused")
\r
3217 private void toggleBoldVisible(Boolean toggle) {
\r
3218 boldAction.setVisible(toggle);
\r
3219 Global.saveEditorButtonsVisible("bold", toggle);
\r
3221 @SuppressWarnings("unused")
\r
3222 private void toggleItalicVisible(Boolean toggle) {
\r
3223 italicAction.setVisible(toggle);
\r
3224 Global.saveEditorButtonsVisible("italic", toggle);
\r
3226 @SuppressWarnings("unused")
\r
3227 private void toggleUnderlineVisible(Boolean toggle) {
\r
3228 underlineAction.setVisible(toggle);
\r
3229 Global.saveEditorButtonsVisible("underline", toggle);
\r
3231 @SuppressWarnings("unused")
\r
3232 private void toggleStrikethroughVisible(Boolean toggle) {
\r
3233 strikethroughAction.setVisible(toggle);
\r
3234 Global.saveEditorButtonsVisible("strikethrough", toggle);
\r
3236 @SuppressWarnings("unused")
\r
3237 private void toggleLeftAlignVisible(Boolean toggle) {
\r
3238 leftAlignAction.setVisible(toggle);
\r
3239 Global.saveEditorButtonsVisible("alignLeft", toggle);
\r
3241 @SuppressWarnings("unused")
\r
3242 private void toggleRightAlignVisible(Boolean toggle) {
\r
3243 rightAlignAction.setVisible(toggle);
\r
3244 Global.saveEditorButtonsVisible("alignRight", toggle);
\r
3246 @SuppressWarnings("unused")
\r
3247 private void toggleCenterAlignVisible(Boolean toggle) {
\r
3248 centerAlignAction.setVisible(toggle);
\r
3249 Global.saveEditorButtonsVisible("alignCenter", toggle);
\r
3251 @SuppressWarnings("unused")
\r
3252 private void toggleHLineVisible(Boolean toggle) {
\r
3253 hlineAction.setVisible(toggle);
\r
3254 Global.saveEditorButtonsVisible("hline", toggle);
\r
3256 @SuppressWarnings("unused")
\r
3257 private void toggleIndentVisible(Boolean toggle) {
\r
3258 indentAction.setVisible(toggle);
\r
3259 Global.saveEditorButtonsVisible("indent", toggle);
\r
3261 @SuppressWarnings("unused")
\r
3262 private void toggleTodoVisible(Boolean toggle) {
\r
3263 todoAction.setVisible(toggle);
\r
3264 Global.saveEditorButtonsVisible("todo", toggle);
\r
3266 @SuppressWarnings("unused")
\r
3267 private void toggleOutdentVisible(Boolean toggle) {
\r
3268 outdentAction.setVisible(toggle);
\r
3269 Global.saveEditorButtonsVisible("outdent", toggle);
\r
3271 @SuppressWarnings("unused")
\r
3272 private void toggleBulletListVisible(Boolean toggle) {
\r
3273 bulletListAction.setVisible(toggle);
\r
3274 Global.saveEditorButtonsVisible("bulletList", toggle);
\r
3276 @SuppressWarnings("unused")
\r
3277 private void toggleNumberListVisible(Boolean toggle) {
\r
3278 numberListAction.setVisible(toggle);
\r
3279 Global.saveEditorButtonsVisible("numberList", toggle);
\r
3281 @SuppressWarnings("unused")
\r
3282 private void toggleFontListVisible(Boolean toggle) {
\r
3283 fontListAction.setVisible(toggle);
\r
3284 Global.saveEditorButtonsVisible("font", toggle);
\r
3286 @SuppressWarnings("unused")
\r
3287 private void toggleFontColorVisible(Boolean toggle) {
\r
3288 fontColorAction.setVisible(toggle);
\r
3289 Global.saveEditorButtonsVisible("fontColor", toggle);
\r
3291 @SuppressWarnings("unused")
\r
3292 private void toggleFontSizeVisible(Boolean toggle) {
\r
3293 fontSizeAction.setVisible(toggle);
\r
3294 Global.saveEditorButtonsVisible("fontSize", toggle);
\r
3296 @SuppressWarnings("unused")
\r
3297 private void toggleFontHilightVisible(Boolean toggle) {
\r
3298 fontHilightAction.setVisible(toggle);
\r
3299 Global.saveEditorButtonsVisible("fontHilight", toggle);
\r
3301 @SuppressWarnings("unused")
\r
3302 private void toggleSpellCheckVisible(Boolean toggle) {
\r
3303 spellCheckAction.setVisible(toggle);
\r
3304 Global.saveEditorButtonsVisible("spellCheck", toggle);
\r
3308 private void setupDictionary() {
\r
3309 File wordList = new File(Global.getFileManager().getSpellDirPath()+Locale.getDefault()+".dic");
\r
3311 dictionary = new SpellDictionaryHashMap(wordList);
\r
3312 spellChecker = new SpellChecker(dictionary);
\r
3314 File userWordList;
\r
3315 userWordList = new File(Global.getFileManager().getSpellDirPathUser()+"user.dic");
\r
3317 // Get the local user spell dictionary
\r
3319 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
3320 } catch (FileNotFoundException e) {
\r
3321 userWordList.createNewFile();
\r
3322 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
3323 } catch (IOException e) {
\r
3324 userWordList.createNewFile();
\r
3325 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
3328 spellListener = new SuggestionListener(this, spellChecker);
\r
3330 // Add the user dictionary
\r
3331 spellChecker.addSpellCheckListener(spellListener);
\r
3332 spellChecker.setUserDictionary(userDictionary);
\r
3334 } catch (FileNotFoundException e) {
\r
3335 QMessageBox.critical(this, tr("Spell Check Error"),
\r
3336 tr("Dictionary ")+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
3337 tr(".dic was not found."));
\r
3338 } catch (IOException e) {
\r
3339 QMessageBox.critical(this, tr("Spell Check Error"),
\r
3340 tr("Dictionary ")+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
3341 tr(".dic is invalid."));
\r
3346 // Invoke spell checker dialog
\r
3347 @SuppressWarnings("unused")
\r
3348 private void spellCheckClicked() {
\r
3350 if (spellChecker == null) {
\r
3351 setupDictionary();
\r
3354 // Read user settings
\r
3355 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREDIGITWORDS,
\r
3356 Global.getSpellSetting(Configuration.SPELL_IGNOREDIGITWORDS));
\r
3357 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREINTERNETADDRESSES,
\r
3358 Global.getSpellSetting(Configuration.SPELL_IGNOREINTERNETADDRESSES));
\r
3359 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREMIXEDCASE,
\r
3360 Global.getSpellSetting(Configuration.SPELL_IGNOREMIXEDCASE));
\r
3361 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREUPPERCASE,
\r
3362 Global.getSpellSetting(Configuration.SPELL_IGNOREUPPERCASE));
\r
3363 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNORESENTENCECAPITALIZATION,
\r
3364 Global.getSpellSetting(Configuration.SPELL_IGNORESENTENCECAPITALIZATION));
\r
3366 spellListener.abortSpellCheck = false;
\r
3367 spellListener.errorsFound = false;
\r
3368 String content = getBrowser().page().mainFrame().toPlainText();
\r
3369 StringWordTokenizer tokenizer = new StringWordTokenizer(content);
\r
3370 if (!tokenizer.hasMoreWords())
\r
3372 getBrowser().page().action(WebAction.MoveToStartOfDocument);
\r
3374 getBrowser().setFocus();
\r
3377 // Move to the start of page
\r
3378 KeyboardModifiers ctrl = new KeyboardModifiers(KeyboardModifier.ControlModifier.value());
\r
3379 QKeyEvent home = new QKeyEvent(Type.KeyPress, Key.Key_Home.value(), ctrl);
\r
3380 browser.keyPressEvent(home);
\r
3381 getBrowser().setFocus();
\r
3383 tokenizer = new StringWordTokenizer(content);
\r
3386 while(tokenizer.hasMoreWords()) {
\r
3387 word = tokenizer.nextWord();
\r
3388 found = getBrowser().page().findText(word);
\r
3389 if (found && !spellListener.abortSpellCheck) {
\r
3390 spellChecker.checkSpelling(new StringWordTokenizer(word));
\r
3391 getBrowser().setFocus();
\r
3395 // Go to the end of the document & finish up.
\r
3396 home = new QKeyEvent(Type.KeyPress, Key.Key_End.value(), ctrl);
\r
3397 browser.keyPressEvent(home);
\r
3398 if (!spellListener.errorsFound)
\r
3399 QMessageBox.information(this, tr("Spell Check Complete"),
\r
3400 tr("No Errors Found"));
\r
3405 @SuppressWarnings("unused")
\r
3406 private void sourceEdited() {
\r
3407 QTextCodec codec = QTextCodec.codecForLocale();
\r
3408 codec = QTextCodec.codecForName("UTF-8");
\r
3409 String content = codec.fromUnicode(sourceEdit.toHtml()).toString();
\r
3410 content = StringEscapeUtils.unescapeHtml4(removeTags(content));
\r
3411 QByteArray data = new QByteArray(sourceEditHeader+content+"</body></html>");
\r
3412 getBrowser().setContent(data);
\r
3414 if (currentNote != null && sourceEdit != null)
\r
3415 noteSignal.noteChanged.emit(currentNote.getGuid(), sourceEdit.toPlainText());
\r
3418 private void setSource() {
\r
3419 String text = getContent();
\r
3420 sourceEdit.blockSignals(true);
\r
3421 int body = text.indexOf("<body");
\r
3423 body = text.indexOf(">",body);
\r
3425 sourceEditHeader =text.substring(0, body+1);
\r
3426 text = text.substring(body+1);
\r
3429 text = text.replace("</body></html>", "");
\r
3430 sourceEdit.setPlainText(text);
\r
3431 sourceEdit.setReadOnly(!getBrowser().page().isContentEditable());
\r
3432 //syntaxHighlighter.rehighlight();
\r
3433 sourceEdit.blockSignals(false);
\r
3436 // show/hide view source window
\r
3437 public void showSource(boolean value) {
\r
3438 if (sourceEdit.isVisible())
\r
3440 sourceEdit.setVisible(value);
\r
3443 // Remove HTML tags
\r
3444 private String removeTags(String text) {
\r
3445 StringBuffer buffer = new StringBuffer(text);
\r
3446 boolean inTag = false;
\r
3447 int bodyPosition = text.indexOf("<body");
\r
3448 for (int i=buffer.length()-1; i>=0; i--) {
\r
3449 if (buffer.charAt(i) == '>')
\r
3451 if (buffer.charAt(i) == '<')
\r
3453 if (inTag || buffer.charAt(i) == '<' || i<bodyPosition)
\r
3454 buffer.deleteCharAt(i);
\r
3457 return buffer.toString();
\r