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.lang.StringUtils;
\r
43 import com.evernote.edam.limits.Constants;
\r
44 import com.evernote.edam.type.Data;
\r
45 import com.evernote.edam.type.Note;
\r
46 import com.evernote.edam.type.Notebook;
\r
47 import com.evernote.edam.type.Resource;
\r
48 import com.evernote.edam.type.ResourceAttributes;
\r
49 import com.evernote.edam.type.Tag;
\r
50 import com.swabunga.spell.engine.Configuration;
\r
51 import com.swabunga.spell.engine.SpellDictionary;
\r
52 import com.swabunga.spell.engine.SpellDictionaryHashMap;
\r
53 import com.swabunga.spell.engine.Word;
\r
54 import com.swabunga.spell.event.SpellCheckEvent;
\r
55 import com.swabunga.spell.event.SpellCheckListener;
\r
56 import com.swabunga.spell.event.SpellChecker;
\r
57 import com.swabunga.spell.event.StringWordTokenizer;
\r
58 import com.trolltech.qt.core.QByteArray;
\r
59 import com.trolltech.qt.core.QCoreApplication;
\r
60 import com.trolltech.qt.core.QDataStream;
\r
61 import com.trolltech.qt.core.QDateTime;
\r
62 import com.trolltech.qt.core.QEvent;
\r
63 import com.trolltech.qt.core.QEvent.Type;
\r
64 import com.trolltech.qt.core.QFile;
\r
65 import com.trolltech.qt.core.QFileSystemWatcher;
\r
66 import com.trolltech.qt.core.QIODevice;
\r
67 import com.trolltech.qt.core.QMimeData;
\r
68 import com.trolltech.qt.core.QTextCodec;
\r
69 import com.trolltech.qt.core.QUrl;
\r
70 import com.trolltech.qt.core.Qt;
\r
71 import com.trolltech.qt.core.Qt.Key;
\r
72 import com.trolltech.qt.core.Qt.KeyboardModifier;
\r
73 import com.trolltech.qt.core.Qt.KeyboardModifiers;
\r
74 import com.trolltech.qt.gui.QAction;
\r
75 import com.trolltech.qt.gui.QApplication;
\r
76 import com.trolltech.qt.gui.QCalendarWidget;
\r
77 import com.trolltech.qt.gui.QClipboard;
\r
78 import com.trolltech.qt.gui.QClipboard.Mode;
\r
79 import com.trolltech.qt.gui.QColor;
\r
80 import com.trolltech.qt.gui.QComboBox;
\r
81 import com.trolltech.qt.gui.QDateEdit;
\r
82 import com.trolltech.qt.gui.QDesktopServices;
\r
83 import com.trolltech.qt.gui.QFileDialog;
\r
84 import com.trolltech.qt.gui.QFileDialog.AcceptMode;
\r
85 import com.trolltech.qt.gui.QFileDialog.FileMode;
\r
86 import com.trolltech.qt.gui.QFont;
\r
87 import com.trolltech.qt.gui.QFontDatabase;
\r
88 import com.trolltech.qt.gui.QFormLayout;
\r
89 import com.trolltech.qt.gui.QGridLayout;
\r
90 import com.trolltech.qt.gui.QHBoxLayout;
\r
91 import com.trolltech.qt.gui.QIcon;
\r
92 import com.trolltech.qt.gui.QImage;
\r
93 import com.trolltech.qt.gui.QKeyEvent;
\r
94 import com.trolltech.qt.gui.QKeySequence;
\r
95 import com.trolltech.qt.gui.QLabel;
\r
96 import com.trolltech.qt.gui.QLineEdit;
\r
97 import com.trolltech.qt.gui.QListWidgetItem;
\r
98 import com.trolltech.qt.gui.QMatrix;
\r
99 import com.trolltech.qt.gui.QMessageBox;
\r
100 import com.trolltech.qt.gui.QPalette;
\r
101 import com.trolltech.qt.gui.QPalette.ColorRole;
\r
102 import com.trolltech.qt.gui.QPushButton;
\r
103 import com.trolltech.qt.gui.QShortcut;
\r
104 import com.trolltech.qt.gui.QSplitter;
\r
105 import com.trolltech.qt.gui.QTextEdit;
\r
106 import com.trolltech.qt.gui.QTextEdit.LineWrapMode;
\r
107 import com.trolltech.qt.gui.QTimeEdit;
\r
108 import com.trolltech.qt.gui.QToolButton;
\r
109 import com.trolltech.qt.gui.QToolButton.ToolButtonPopupMode;
\r
110 import com.trolltech.qt.gui.QVBoxLayout;
\r
111 import com.trolltech.qt.gui.QWidget;
\r
112 import com.trolltech.qt.network.QNetworkAccessManager;
\r
113 import com.trolltech.qt.network.QNetworkReply;
\r
114 import com.trolltech.qt.network.QNetworkReply.NetworkError;
\r
115 import com.trolltech.qt.network.QNetworkRequest;
\r
116 import com.trolltech.qt.webkit.QWebPage;
\r
117 import com.trolltech.qt.webkit.QWebPage.WebAction;
\r
118 import com.trolltech.qt.webkit.QWebSettings;
\r
119 import com.trolltech.qt.webkit.QWebView;
\r
121 import cx.fbn.nevernote.Global;
\r
122 import cx.fbn.nevernote.dialog.EnCryptDialog;
\r
123 import cx.fbn.nevernote.dialog.EnDecryptDialog;
\r
124 import cx.fbn.nevernote.dialog.GeoDialog;
\r
125 import cx.fbn.nevernote.dialog.InsertLatexImage;
\r
126 import cx.fbn.nevernote.dialog.InsertLinkDialog;
\r
127 import cx.fbn.nevernote.dialog.SpellCheck;
\r
128 import cx.fbn.nevernote.dialog.TableDialog;
\r
129 import cx.fbn.nevernote.dialog.TagAssign;
\r
130 import cx.fbn.nevernote.evernote.EnCrypt;
\r
131 import cx.fbn.nevernote.filters.FilterEditorTags;
\r
132 import cx.fbn.nevernote.signals.NoteResourceSignal;
\r
133 import cx.fbn.nevernote.signals.NoteSignal;
\r
134 import cx.fbn.nevernote.sql.DatabaseConnection;
\r
135 import cx.fbn.nevernote.utilities.ApplicationLogger;
\r
136 import cx.fbn.nevernote.utilities.FileUtils;
\r
137 import cx.fbn.nevernote.utilities.Pair;
\r
138 import cx.fbn.nevernote.xml.HtmlTagModifier;
\r
140 public class BrowserWindow extends QWidget {
\r
142 public final QLineEdit titleLabel;
\r
143 private final QLineEdit urlText;
\r
144 private final QLabel authorLabel;
\r
145 private final QLineEdit authorText;
\r
146 private final QComboBox geoBox;
\r
147 public final TagLineEdit tagEdit;
\r
148 public final QLabel tagLabel;
\r
149 private final QPushButton urlLabel;
\r
150 private final QLabel alteredLabel;
\r
151 private final QDateEdit alteredDate;
\r
152 private final QTimeEdit alteredTime;
\r
153 private final QDateEdit createdDate;
\r
154 private final QTimeEdit createdTime;
\r
155 private final QLabel subjectLabel;
\r
156 private final QDateEdit subjectDate;
\r
157 private final QTimeEdit subjectTime;
\r
158 public final QComboBox notebookBox;
\r
159 private final QLabel notebookLabel;
\r
160 private final QLabel createdLabel;
\r
161 public final QComboBox fontSize;
\r
162 public final QAction fontSizeAction;
\r
163 private boolean extendedOn;
\r
164 public boolean buttonsVisible;
\r
165 private final String iconPath;
\r
166 private final ContentView browser;
\r
167 private final QTextEdit sourceEdit;
\r
168 private String sourceEditHeader;
\r
169 Highlighter syntaxHighlighter;
\r
170 private List<Tag> allTags;
\r
171 private List<String> currentTags;
\r
172 public NoteSignal noteSignal;
\r
173 public Signal2<String,String> evernoteLinkClicked;
\r
174 private List<Notebook> notebookList;
\r
175 private Note currentNote;
\r
176 private String saveNoteTitle;
\r
177 private String saveTagList;
\r
178 private boolean insideList;
\r
179 private final DatabaseConnection conn;
\r
180 private final QCalendarWidget createdCalendarWidget;
\r
181 private final QCalendarWidget alteredCalendarWidget;
\r
182 private final QCalendarWidget subjectCalendarWidget;
\r
184 public final QPushButton undoButton;
\r
185 public final QAction undoAction;
\r
186 public final QPushButton redoButton;
\r
187 public final QAction redoAction;
\r
188 public final QPushButton cutButton;
\r
189 public final QAction cutAction;
\r
190 public final QPushButton copyButton;
\r
191 public final QAction copyAction;
\r
192 public final QPushButton pasteButton;
\r
193 public final QAction pasteAction;
\r
194 public final QPushButton boldButton;
\r
195 public final QAction boldAction;
\r
196 public final QPushButton underlineButton;
\r
197 public final QAction underlineAction;
\r
198 public final QPushButton italicButton;
\r
199 public final QAction italicAction;
\r
200 public final Signal0 focusLost;
\r
201 public final NoteResourceSignal resourceSignal;
\r
203 public QPushButton rightAlignButton;
\r
204 public final QAction rightAlignAction;
\r
205 public QPushButton leftAlignButton;
\r
206 public final QAction leftAlignAction;
\r
207 public QPushButton centerAlignButton;
\r
208 public final QAction centerAlignAction;
\r
210 public final QPushButton strikethroughButton;
\r
211 public final QAction strikethroughAction;
\r
212 public final QPushButton hlineButton;
\r
213 public final QAction hlineAction;
\r
214 public final QPushButton indentButton;
\r
215 public final QAction indentAction;
\r
216 public final QPushButton outdentButton;
\r
217 public final QAction outdentAction;
\r
218 public final QPushButton bulletListButton;
\r
219 public final QAction bulletListAction;
\r
220 public final QPushButton numberListButton;
\r
221 public final QAction numberListAction;
\r
222 public final QPushButton spellCheckButton;
\r
223 public final QAction spellCheckAction;
\r
224 public final QPushButton todoButton;
\r
225 public final QAction todoAction;
\r
227 public final QShortcut focusTitleShortcut;
\r
228 public final QShortcut focusTagShortcut;
\r
229 public final QShortcut focusNoteShortcut;
\r
230 public final QShortcut focusUrlShortcut;
\r
231 public final QShortcut focusAuthorShortcut;
\r
233 public EditorButtonBar buttonLayout;
\r
234 public final QComboBox fontList;
\r
235 public final QAction fontListAction;
\r
236 public final QToolButton fontColor;
\r
237 public final QAction fontColorAction;
\r
238 private final ColorMenu fontColorMenu;
\r
239 public final QToolButton fontHilight;
\r
240 public final QAction fontHilightAction;
\r
241 private final ColorMenu fontHilightColorMenu;
\r
242 public final QFileSystemWatcher fileWatcher;
\r
243 public int cursorPosition;
\r
244 private boolean forceTextPaste;
\r
245 private String selectedFile;
\r
246 private String currentHyperlink;
\r
247 public boolean keepPDFNavigationHidden;
\r
248 private final ApplicationLogger logger;
\r
249 SpellDictionary dictionary;
\r
250 SpellDictionary userDictionary;
\r
251 SpellChecker spellChecker;
\r
252 SuggestionListener spellListener;
\r
253 private final HashMap<String,Integer> previewPageList;
\r
254 boolean insertHyperlink;
\r
255 boolean insideTable;
\r
256 boolean insideEncryption;
\r
257 public Signal1<BrowserWindow> blockApplication;
\r
258 public Signal0 unblockApplication;
\r
259 public boolean awaitingHttpResponse;
\r
260 public long unblockTime;
\r
261 String latexGuid; // This is set if we are editing an existing LaTeX formula. Useful to track guid.
\r
264 public static class SuggestionListener implements SpellCheckListener {
\r
265 public boolean abortSpellCheck = false;
\r
266 public boolean errorsFound = false;
\r
267 private final SpellCheck spellCheckDialog;
\r
270 private final BrowserWindow parent;
\r
271 public SuggestionListener(BrowserWindow parent, SpellChecker checker) {
\r
272 this.parent = parent;
\r
273 spellCheckDialog = new SpellCheck(checker);
\r
275 public void spellingError(SpellCheckEvent event) {
\r
276 errorsFound = true;
\r
277 spellCheckDialog.setWord(event.getInvalidWord());
\r
279 @SuppressWarnings("unchecked")
\r
280 List<Word> suggestions = event.getSuggestions();
\r
281 spellCheckDialog.clearSuggestions();
\r
282 if (!suggestions.isEmpty()) {
\r
283 // spellCheckDialog.setCurrentSuggestion(suggestions.get(0).getWord());
\r
284 for (int i=0; i<suggestions.size(); i++) {
\r
285 spellCheckDialog.addSuggestion(suggestions.get(i).getWord());
\r
287 spellCheckDialog.setSelectedSuggestion(0);
\r
289 spellCheckDialog.exec();
\r
290 if (spellCheckDialog.cancelPressed()) {
\r
291 abortSpellCheck = true;
\r
295 if (spellCheckDialog.replacePressed()) {
\r
296 QClipboard clipboard = QApplication.clipboard();
\r
297 clipboard.setText(spellCheckDialog.getReplacementWord());
\r
298 parent.pasteClicked();
\r
306 public BrowserWindow(DatabaseConnection c) {
\r
307 logger = new ApplicationLogger("browser.log");
\r
308 logger.log(logger.HIGH, "Setting up browser");
\r
309 iconPath = new String("classpath:cx/fbn/nevernote/icons/");
\r
310 forceTextPaste = false;
\r
311 insertHyperlink = true;
\r
312 insideTable = false;
\r
313 insideEncryption = false;
\r
315 fileWatcher = new QFileSystemWatcher();
\r
316 // fileWatcher.fileChanged.connect(this, "fileChanged(String)");
\r
317 noteSignal = new NoteSignal();
\r
318 titleLabel = new QLineEdit();
\r
319 evernoteLinkClicked = new Signal2<String,String>();
\r
320 titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX);
\r
321 urlText = new QLineEdit();
\r
322 authorText = new QLineEdit();
\r
323 geoBox = new QComboBox();
\r
324 urlLabel = new QPushButton();
\r
325 urlLabel.clicked.connect(this, "sourceUrlClicked()");
\r
326 authorLabel = new QLabel();
\r
329 focusLost = new Signal0();
\r
331 tagEdit = new TagLineEdit(allTags);
\r
332 tagLabel = new QLabel(tr("Tags:"));
\r
333 tagEdit.focusLost.connect(this, "modifyTagsTyping()");
\r
335 createdCalendarWidget = new QCalendarWidget();
\r
336 createdDate = new QDateEdit();
\r
337 createdDate.setDisplayFormat(Global.getDateFormat());
\r
338 createdDate.setCalendarPopup(true);
\r
339 createdDate.setCalendarWidget(createdCalendarWidget);
\r
340 createdTime = new QTimeEdit();
\r
341 createdDate.dateChanged.connect(this, "createdChanged()");
\r
342 createdTime.timeChanged.connect(this, "createdChanged()");
\r
344 alteredCalendarWidget = new QCalendarWidget();
\r
345 alteredDate = new QDateEdit();
\r
346 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
347 alteredDate.setCalendarPopup(true);
\r
348 alteredDate.setCalendarWidget(alteredCalendarWidget);
\r
349 alteredTime = new QTimeEdit();
\r
350 alteredLabel = new QLabel(tr("Altered:"));
\r
351 alteredDate.dateChanged.connect(this, "alteredChanged()");
\r
352 alteredTime.timeChanged.connect(this, "alteredChanged()");
\r
354 subjectCalendarWidget = new QCalendarWidget();
\r
355 subjectDate = new QDateEdit();
\r
356 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
357 subjectDate.setCalendarPopup(true);
\r
358 subjectDate.setCalendarWidget(subjectCalendarWidget);
\r
359 subjectTime = new QTimeEdit();
\r
360 subjectLabel = new QLabel(tr("Subject Date:"));
\r
361 subjectDate.dateChanged.connect(this, "subjectDateTimeChanged()");
\r
362 subjectTime.timeChanged.connect(this, "subjectDateTimeChanged()");
\r
363 authorText.textChanged.connect(this, "authorChanged()");
\r
364 urlText.textChanged.connect(this, "sourceUrlChanged()");
\r
366 notebookBox = new QComboBox();
\r
367 notebookLabel = new QLabel(tr("Notebook"));
\r
368 createdLabel = new QLabel(tr("Created:"));
\r
369 // selectedText = new String();
\r
371 urlLabel.setVisible(false);
\r
372 urlText.setVisible(false);
\r
373 authorLabel.setVisible(false);
\r
375 geoBox.setVisible(false);
\r
376 geoBox.addItem(new QIcon(iconPath+"globe.png"), "");
\r
377 geoBox.addItem(new String(tr("Set")));
\r
378 geoBox.addItem(new String(tr("Clear")));
\r
379 geoBox.addItem(new String(tr("View On Map")));
\r
380 geoBox.activated.connect(this, "geoBoxChanged()");
\r
382 authorText.setVisible(false);
\r
383 createdDate.setVisible(false);
\r
384 alteredLabel.setVisible(false);
\r
385 //notebookBox.setVisible(false);
\r
386 notebookLabel.setVisible(false);
\r
387 createdLabel.setVisible(false);
\r
388 createdTime.setVisible(false);
\r
389 alteredDate.setVisible(false);
\r
390 alteredTime.setVisible(false);
\r
391 subjectLabel.setVisible(false);
\r
392 subjectDate.setVisible(false);
\r
393 subjectTime.setVisible(false);
\r
394 extendedOn = false;
\r
395 buttonsVisible = true;
\r
396 setAcceptDrops(true);
\r
398 browser = new ContentView(this);
\r
400 browser.page().setLinkDelegationPolicy(
\r
401 QWebPage.LinkDelegationPolicy.DelegateAllLinks);
\r
402 browser.linkClicked.connect(this, "linkClicked(QUrl)");
\r
403 currentHyperlink = "";
\r
405 //Setup the source editor
\r
406 sourceEdit = new QTextEdit(this);
\r
407 sourceEdit.setVisible(false);
\r
408 sourceEdit.setTabChangesFocus(true);
\r
409 sourceEdit.setLineWrapMode(LineWrapMode.NoWrap);
\r
410 QFont font = new QFont();
\r
411 font.setFamily("Courier");
\r
412 font.setFixedPitch(true);
\r
413 font.setPointSize(10);
\r
414 sourceEdit.setFont(font);
\r
415 syntaxHighlighter = new Highlighter(sourceEdit.document());
\r
416 sourceEdit.textChanged.connect(this, "sourceEdited()");
\r
418 QVBoxLayout v = new QVBoxLayout();
\r
419 QFormLayout notebookLayout = new QFormLayout();
\r
420 QGridLayout dateLayout = new QGridLayout();
\r
421 titleLabel.setReadOnly(false);
\r
422 titleLabel.editingFinished.connect(this, "titleEdited()");
\r
423 browser.page().contentsChanged.connect(this, "contentChanged()");
\r
424 browser.page().selectionChanged.connect(this, "selectionChanged()");
\r
425 browser.page().mainFrame().javaScriptWindowObjectCleared.connect(this,
\r
426 "exposeToJavascript()");
\r
428 notebookBox.activated.connect(this, "notebookChanged()");
\r
429 resourceSignal = new NoteResourceSignal();
\r
431 QHBoxLayout tagLayout = new QHBoxLayout();
\r
432 v.addWidget(titleLabel, 0);
\r
433 notebookLayout.addRow(notebookLabel, notebookBox);
\r
434 tagLayout.addLayout(notebookLayout, 0);
\r
435 tagLayout.stretch(4);
\r
436 tagLayout.addWidget(tagLabel, 0);
\r
437 tagLayout.addWidget(tagEdit, 1);
\r
438 v.addLayout(tagLayout);
\r
440 QHBoxLayout urlLayout = new QHBoxLayout();
\r
441 urlLayout.addWidget(urlLabel, 0);
\r
442 urlLayout.addWidget(urlText, 0);
\r
443 v.addLayout(urlLayout);
\r
445 QHBoxLayout authorLayout = new QHBoxLayout();
\r
446 authorLayout.addWidget(authorLabel, 0);
\r
447 authorLayout.addWidget(authorText, 0);
\r
448 authorLayout.addWidget(geoBox);
\r
449 v.addLayout(authorLayout);
\r
451 dateLayout.addWidget(createdLabel, 0, 0);
\r
452 dateLayout.addWidget(createdDate, 0, 1);
\r
453 dateLayout.addWidget(createdTime, 0, 2);
\r
454 dateLayout.setColumnStretch(9, 100);
\r
455 dateLayout.addWidget(alteredLabel, 0, 3);
\r
456 dateLayout.addWidget(alteredDate, 0, 4);
\r
457 dateLayout.addWidget(alteredTime, 0, 5);
\r
458 dateLayout.addWidget(subjectLabel, 0, 6);
\r
459 dateLayout.addWidget(subjectDate, 0, 7);
\r
460 dateLayout.addWidget(subjectTime, 0, 8);
\r
461 v.addLayout(dateLayout, 0);
\r
463 undoButton = newEditorButton("undo", tr("Undo Change"));
\r
464 redoButton = newEditorButton("redo", tr("Redo Change"));
\r
465 cutButton = newEditorButton("cut", tr("Cut"));
\r
466 copyButton = newEditorButton("copy", tr("Copy"));
\r
467 pasteButton = newEditorButton("paste", tr("Paste"));
\r
468 boldButton = newEditorButton("bold", tr("Bold"));
\r
469 underlineButton = newEditorButton("underline", tr("Underline"));
\r
470 italicButton = newEditorButton("italic", tr("Italic"));
\r
472 rightAlignButton = newEditorButton("justifyRight", tr("Right Align"));
\r
473 leftAlignButton = newEditorButton("justifyLeft", tr("Left Align"));
\r
474 centerAlignButton = newEditorButton("justifyCenter", tr("Center Align"));
\r
476 strikethroughButton = newEditorButton("strikethrough", tr("Strikethrough"));
\r
477 hlineButton = newEditorButton("hline", tr("Insert Horizontal Line"));
\r
478 indentButton = newEditorButton("indent", tr("Shift Right"));
\r
479 outdentButton = newEditorButton("outdent", tr("Shift Left"));
\r
480 bulletListButton = newEditorButton("bulletList", tr("Bullet List"));
\r
481 numberListButton = newEditorButton("numberList", tr("Number List"));
\r
482 spellCheckButton = newEditorButton("spellCheck", tr("Spell Check"));
\r
483 todoButton = newEditorButton("todo", tr("To-do"));
\r
486 buttonLayout = new EditorButtonBar();
\r
487 v.addWidget(buttonLayout);
\r
489 undoAction = buttonLayout.addWidget(undoButton);
\r
490 buttonLayout.toggleUndoVisible.triggered.connect(this, "toggleUndoVisible(Boolean)");
\r
491 redoAction = buttonLayout.addWidget(redoButton);
\r
492 buttonLayout.toggleRedoVisible.triggered.connect(this, "toggleRedoVisible(Boolean)");
\r
494 buttonLayout.addWidget(newSeparator());
\r
495 cutAction = buttonLayout.addWidget(cutButton);
\r
496 buttonLayout.toggleCutVisible.triggered.connect(this, "toggleCutVisible(Boolean)");
\r
497 copyAction = buttonLayout.addWidget(copyButton);
\r
498 buttonLayout.toggleCopyVisible.triggered.connect(this, "toggleCopyVisible(Boolean)");
\r
499 pasteAction = buttonLayout.addWidget(pasteButton);
\r
500 buttonLayout.togglePasteVisible.triggered.connect(this, "togglePasteVisible(Boolean)");
\r
502 buttonLayout.addWidget(newSeparator());
\r
503 boldAction = buttonLayout.addWidget(boldButton);
\r
504 buttonLayout.toggleBoldVisible.triggered.connect(this, "toggleBoldVisible(Boolean)");
\r
505 italicAction = buttonLayout.addWidget(italicButton);
\r
506 buttonLayout.toggleItalicVisible.triggered.connect(this, "toggleItalicVisible(Boolean)");
\r
507 underlineAction = buttonLayout.addWidget(underlineButton);
\r
508 buttonLayout.toggleUnderlineVisible.triggered.connect(this, "toggleUnderlineVisible(Boolean)");
\r
509 strikethroughAction = buttonLayout.addWidget(strikethroughButton);
\r
510 buttonLayout.toggleStrikethroughVisible.triggered.connect(this, "toggleStrikethroughVisible(Boolean)");
\r
513 buttonLayout.addWidget(newSeparator());
\r
514 leftAlignAction = buttonLayout.addWidget(leftAlignButton);
\r
515 buttonLayout.toggleLeftAlignVisible.triggered.connect(this, "toggleLeftAlignVisible(Boolean)");
\r
516 centerAlignAction = buttonLayout.addWidget(centerAlignButton);
\r
517 buttonLayout.toggleCenterAlignVisible.triggered.connect(this, "toggleCenterAlignVisible(Boolean)");
\r
518 rightAlignAction = buttonLayout.addWidget(rightAlignButton);
\r
519 buttonLayout.toggleRightAlignVisible.triggered.connect(this, "toggleRightAlignVisible(Boolean)");
\r
521 buttonLayout.addWidget(newSeparator());
\r
522 hlineAction = buttonLayout.addWidget(hlineButton);
\r
523 buttonLayout.toggleHLineVisible.triggered.connect(this, "toggleHLineVisible(Boolean)");
\r
525 indentAction = buttonLayout.addWidget(indentButton);
\r
526 buttonLayout.toggleIndentVisible.triggered.connect(this, "toggleIndentVisible(Boolean)");
\r
527 outdentAction = buttonLayout.addWidget(outdentButton);
\r
528 buttonLayout.toggleOutdentVisible.triggered.connect(this, "toggleOutdentVisible(Boolean)");
\r
529 bulletListAction = buttonLayout.addWidget(bulletListButton);
\r
530 buttonLayout.toggleBulletListVisible.triggered.connect(this, "toggleBulletListVisible(Boolean)");
\r
531 numberListAction = buttonLayout.addWidget(numberListButton);
\r
532 buttonLayout.toggleNumberListVisible.triggered.connect(this, "toggleNumberListVisible(Boolean)");
\r
534 // Setup the font & font size combo boxes
\r
535 buttonLayout.addWidget(newSeparator());
\r
536 fontList = new QComboBox();
\r
537 fontSize = new QComboBox();
\r
538 fontList.setToolTip("Font");
\r
539 fontSize.setToolTip("Font Size");
\r
540 fontList.activated.connect(this, "fontChanged(String)");
\r
541 fontSize.activated.connect(this, "fontSizeChanged(String)");
\r
542 fontListAction = buttonLayout.addWidget(fontList);
\r
543 buttonLayout.toggleFontVisible.triggered.connect(this, "toggleFontListVisible(Boolean)");
\r
544 fontSizeAction = buttonLayout.addWidget(fontSize);
\r
545 buttonLayout.toggleFontSizeVisible.triggered.connect(this, "toggleFontSizeVisible(Boolean)");
\r
546 QFontDatabase fonts = new QFontDatabase();
\r
547 List<String> fontFamilies = fonts.families();
\r
548 for (int i = 0; i < fontFamilies.size(); i++) {
\r
549 fontList.addItem(fontFamilies.get(i));
\r
551 loadFontSize(fontFamilies.get(i));
\r
555 // buttonLayout.addWidget(newSeparator(), 0);
\r
556 fontColor = newToolButton("fontColor", tr("Font Color"));
\r
557 fontColorMenu = new ColorMenu(this);
\r
558 fontColor.setMenu(fontColorMenu.getMenu());
\r
559 fontColor.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
560 fontColor.setAutoRaise(false);
\r
561 fontColorMenu.getMenu().triggered.connect(this, "fontColorClicked()");
\r
562 fontColorAction = buttonLayout.addWidget(fontColor);
\r
563 buttonLayout.toggleFontColorVisible.triggered.connect(this, "toggleFontColorVisible(Boolean)");
\r
564 fontHilight = newToolButton("fontHilight", tr("Font Hilight Color"));
\r
565 fontHilight.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
566 fontHilight.setAutoRaise(false);
\r
567 fontHilightColorMenu = new ColorMenu(this);
\r
568 fontHilightColorMenu.setDefault(QColor.yellow);
\r
569 fontHilight.setMenu(fontHilightColorMenu.getMenu());
\r
570 fontHilightColorMenu.getMenu().triggered.connect(this, "fontHilightClicked()");
\r
571 fontHilightAction = buttonLayout.addWidget(fontHilight);
\r
572 fontHilightColorMenu.setDefault(QColor.yellow);
\r
573 buttonLayout.toggleFontHilight.triggered.connect(this, "toggleFontHilightVisible(Boolean)");
\r
575 spellCheckAction = buttonLayout.addWidget(spellCheckButton);
\r
576 buttonLayout.toggleNumberListVisible.triggered.connect(this, "spellCheckClicked()");
\r
577 buttonLayout.toggleSpellCheck.triggered.connect(this, "toggleSpellCheckVisible(Boolean)");
\r
579 todoAction = buttonLayout.addWidget(todoButton);
\r
580 buttonLayout.toggleNumberListVisible.triggered.connect(this, "todoClicked()");
\r
581 buttonLayout.toggleTodo.triggered.connect(this, "toggleTodoVisible(Boolean)");
\r
583 // Setup the source browser);
\r
585 // buttonLayout.addWidget(new QLabel(), 1);
\r
586 QSplitter editSplitter = new QSplitter(this);
\r
587 editSplitter.addWidget(browser);
\r
588 editSplitter.setOrientation(Qt.Orientation.Vertical);
\r
589 editSplitter.addWidget(sourceEdit);
\r
593 // v.addWidget(browser, 1);
\r
594 // v.addWidget(sourceEdit);
\r
595 v.addWidget(editSplitter);
\r
598 browser.downloadAttachmentRequested.connect(this,
\r
599 "downloadAttachment(QNetworkRequest)");
\r
600 browser.downloadImageRequested.connect(this,
\r
601 "downloadImage(QNetworkRequest)");
\r
602 setTabOrder(notebookBox, tagEdit);
\r
603 setTabOrder(tagEdit, browser);
\r
605 focusNoteShortcut = new QShortcut(this);
\r
606 setupShortcut(focusNoteShortcut, "Focus_Note");
\r
607 focusNoteShortcut.activated.connect(this, "focusNote()");
\r
608 focusTitleShortcut = new QShortcut(this);
\r
609 setupShortcut(focusTitleShortcut, "Focus_Title");
\r
610 focusTitleShortcut.activated.connect(this, "focusTitle()");
\r
611 focusTagShortcut = new QShortcut(this);
\r
612 setupShortcut(focusTagShortcut, "Focus_Tag");
\r
613 focusTagShortcut.activated.connect(this, "focusTag()");
\r
614 focusAuthorShortcut = new QShortcut(this);
\r
615 setupShortcut(focusAuthorShortcut, "Focus_Author");
\r
616 focusAuthorShortcut.activated.connect(this, "focusAuthor()");
\r
617 focusUrlShortcut = new QShortcut(this);
\r
618 setupShortcut(focusUrlShortcut, "Focus_Url");
\r
619 focusUrlShortcut.activated.connect(this, "focusUrl()");
\r
621 browser.page().mainFrame().setTextSizeMultiplier(Global.getTextSizeMultiplier());
\r
622 browser.page().mainFrame().setZoomFactor(Global.getZoomFactor());
\r
624 previewPageList = new HashMap<String,Integer>();
\r
626 browser.page().microFocusChanged.connect(this, "microFocusChanged()");
\r
630 QPalette pal = new QPalette();
\r
631 pal.setColor(ColorRole.Text, QColor.black);
\r
632 titleLabel.setPalette(pal);
\r
633 authorText.setPalette(pal);
\r
634 authorLabel.setPalette(pal);
\r
635 urlLabel.setPalette(pal);
\r
636 urlText.setPalette(pal);
\r
637 createdDate.setPalette(pal);
\r
638 createdTime.setPalette(pal);
\r
639 alteredDate.setPalette(pal);
\r
640 alteredTime.setPalette(pal);
\r
641 subjectDate.setPalette(pal);
\r
642 subjectTime.setPalette(pal);
\r
643 tagEdit.setPalette(pal);
\r
644 notebookBox.setPalette(pal);
\r
646 blockApplication = new Signal1<BrowserWindow>();
\r
647 unblockApplication = new Signal0();
\r
649 logger.log(logger.HIGH, "Browser setup complete");
\r
654 private void setupShortcut(QShortcut action, String text) {
\r
655 if (!Global.shortcutKeys.containsAction(text))
\r
657 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
\r
663 // Getter for the QWebView
\r
664 public QWebView getBrowser() {
\r
668 // Block signals while loading data or things are flagged as dirty by
\r
670 public void loadingData(boolean val) {
\r
671 logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val);
\r
672 notebookBox.blockSignals(val);
\r
673 browser.page().blockSignals(val);
\r
674 browser.page().mainFrame().blockSignals(val);
\r
675 titleLabel.blockSignals(val);
\r
676 alteredDate.blockSignals(val);
\r
677 alteredTime.blockSignals(val);
\r
678 createdTime.blockSignals(val);
\r
679 createdDate.blockSignals(val);
\r
680 subjectDate.blockSignals(val);
\r
681 subjectTime.blockSignals(val);
\r
682 urlText.blockSignals(val);
\r
683 authorText.blockSignals(val);
\r
685 exposeToJavascript();
\r
686 logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val);
\r
690 public void setReadOnly(boolean v) {
\r
692 titleLabel.setEnabled(!v);
\r
693 notebookBox.setEnabled(!v);
\r
694 tagEdit.setEnabled(!v);
\r
695 authorLabel.setEnabled(!v);
\r
696 geoBox.setEnabled(!v);
\r
697 urlText.setEnabled(!v);
\r
698 createdDate.setEnabled(!v);
\r
699 subjectDate.setEnabled(!v);
\r
700 alteredDate.setEnabled(!v);
\r
701 authorText.setEnabled(!v);
\r
702 createdTime.setEnabled(!v);
\r
703 alteredTime.setEnabled(!v);
\r
704 subjectTime.setEnabled(!v);
\r
705 getBrowser().setEnabled(true);
\r
706 // getBrowser().setEnabled(!v);
\r
709 // expose this class to Javascript on the web page
\r
710 private void exposeToJavascript() {
\r
711 browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this);
\r
714 // Custom event queue
\r
716 public boolean event(QEvent e) {
\r
717 if (e.type().equals(QEvent.Type.FocusOut)) {
\r
718 logger.log(logger.EXTREME, "Focus lost");
\r
721 return super.event(e);
\r
724 // clear out browser
\r
725 public void clear() {
\r
726 logger.log(logger.EXTREME, "Entering BrowserWindow.clear()");
\r
728 setContent(new QByteArray());
\r
729 tagEdit.setText("");
\r
730 tagEdit.tagCompleter.reset();
\r
731 urlLabel.setText(tr("Source URL:"));
\r
732 titleLabel.setText("");
\r
733 logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()");
\r
736 public void setContent(QByteArray data) {
\r
737 sourceEdit.blockSignals(true);
\r
738 browser.setContent(data);
\r
739 setSource(getBrowser().page().mainFrame().toHtml());
\r
741 // get/set current note
\r
742 public void setNote(Note n) {
\r
746 saveNoteTitle = n.getTitle();
\r
750 public Note getNote() {
\r
751 return currentNote;
\r
754 // New Editor Button
\r
755 private QPushButton newEditorButton(String name, String toolTip) {
\r
756 QPushButton button = new QPushButton();
\r
757 // QIcon icon = new QIcon(iconPath + name + ".gif");
\r
758 QIcon icon = new QIcon(iconPath + name + ".png");
\r
759 button.setIcon(icon);
\r
760 button.setToolTip(toolTip);
\r
761 button.clicked.connect(this, name + "Clicked()");
\r
764 // New Editor Button
\r
765 private QToolButton newToolButton(String name, String toolTip) {
\r
766 QToolButton button = new QToolButton();
\r
767 // QIcon icon = new QIcon(iconPath + name + ".gif");
\r
768 QIcon icon = new QIcon(iconPath + name + ".png");
\r
769 button.setIcon(icon);
\r
770 button.setToolTip(toolTip);
\r
771 button.clicked.connect(this, name + "Clicked()");
\r
776 private QLabel newSeparator() {
\r
777 return new QLabel(" ");
\r
780 // Set the title in the window
\r
781 public void setTitle(String t) {
\r
782 titleLabel.setText(t);
\r
787 // Return the current text title
\r
788 public String getTitle() {
\r
789 return titleLabel.text();
\r
792 // Set the tag name string
\r
793 public void setTag(String t) {
\r
795 tagEdit.setText(t);
\r
796 tagEdit.tagCompleter.reset();
\r
799 // Set the source URL
\r
800 public void setUrl(String t) {
\r
801 urlLabel.setText(tr("Source URL:\t"));
\r
802 urlText.setText(t);
\r
805 // The user want's to launch a web browser on the source of the URL
\r
806 public void sourceUrlClicked() {
\r
807 // Make sure we have a valid URL
\r
808 if (urlText.text().trim().equals(""))
\r
811 String url = urlText.text();
\r
812 if (!url.toLowerCase().startsWith(tr("http://")))
\r
813 url = tr("http://") +url;
\r
815 if (!QDesktopServices.openUrl(new QUrl(url))) {
\r
816 logger.log(logger.LOW, "Error opening file :" +url);
\r
820 public void setAuthor(String t) {
\r
821 authorLabel.setText(tr("Author:\t"));
\r
822 authorText.setText(t);
\r
825 // Set the creation date
\r
826 public void setCreation(long date) {
\r
827 QDateTime dt = new QDateTime();
\r
828 dt.setTime_t((int) (date / 1000));
\r
829 createdDate.setDateTime(dt);
\r
830 createdTime.setDateTime(dt);
\r
831 createdDate.setDisplayFormat(Global.getDateFormat());
\r
832 createdTime.setDisplayFormat(Global.getTimeFormat());
\r
835 // Set the creation date
\r
836 public void setAltered(long date) {
\r
837 QDateTime dt = new QDateTime();
\r
838 dt.setTime_t((int) (date / 1000));
\r
839 alteredDate.setDateTime(dt);
\r
840 alteredTime.setDateTime(dt);
\r
841 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
842 alteredTime.setDisplayFormat(Global.getTimeFormat());
\r
845 // Set the subject date
\r
846 public void setSubjectDate(long date) {
\r
847 QDateTime dt = new QDateTime();
\r
848 dt.setTime_t((int) (date / 1000));
\r
849 subjectDate.setDateTime(dt);
\r
850 subjectTime.setDateTime(dt);
\r
851 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
852 subjectTime.setDisplayFormat(Global.getTimeFormat());
\r
855 // Toggle the extended attribute information
\r
856 public void toggleInformation() {
\r
858 extendedOn = false;
\r
862 urlLabel.setVisible(extendedOn);
\r
863 urlText.setVisible(extendedOn);
\r
864 authorText.setVisible(extendedOn);
\r
865 geoBox.setVisible(extendedOn);
\r
866 authorLabel.setVisible(extendedOn);
\r
867 createdDate.setVisible(extendedOn);
\r
868 createdTime.setVisible(extendedOn);
\r
869 createdLabel.setVisible(extendedOn);
\r
870 alteredLabel.setVisible(extendedOn);
\r
871 alteredDate.setVisible(extendedOn);
\r
872 alteredTime.setVisible(extendedOn);
\r
873 //notebookBox.setVisible(extendedOn);
\r
874 notebookLabel.setVisible(extendedOn);
\r
875 subjectLabel.setVisible(extendedOn);
\r
876 subjectDate.setVisible(extendedOn);
\r
877 subjectTime.setVisible(extendedOn);
\r
880 public void hideButtons() {
\r
882 undoButton.parentWidget().setVisible(false);
\r
883 buttonsVisible = false;
\r
887 // Is the extended view on?
\r
888 public boolean isExtended() {
\r
892 // Listener for when a link is clicked
\r
893 @SuppressWarnings("unused")
\r
894 private void openFile() {
\r
895 logger.log(logger.EXTREME, "Starting openFile()");
\r
896 File fileHandle = new File(selectedFile);
\r
897 URI fileURL = fileHandle.toURI();
\r
898 String localURL = fileURL.toString();
\r
899 QUrl url = new QUrl(localURL);
\r
900 QFile file = new QFile(selectedFile);
\r
902 logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName());
\r
903 fileWatcher.addPath(file.fileName());
\r
905 if (!QDesktopServices.openUrl(url)) {
\r
906 logger.log(logger.LOW, "Error opening file :" +url);
\r
911 // Listener for when a link is clicked
\r
912 @SuppressWarnings("unused")
\r
913 private void linkClicked(QUrl url) {
\r
914 logger.log(logger.EXTREME, "URL Clicked: " +url.toString());
\r
915 if (url.toString().startsWith("latex:")) {
\r
916 int position = url.toString().lastIndexOf(".");
\r
917 String guid = url.toString().substring(0,position);
\r
918 position = guid.lastIndexOf("/");
\r
919 guid = guid.substring(position+1);
\r
923 if (url.toString().startsWith("evernote:/view/")) {
\r
924 StringTokenizer tokens = new StringTokenizer(url.toString().replace("evernote:/view/", ""), "/");
\r
925 tokens.nextToken();
\r
926 tokens.nextToken();
\r
927 String sid = tokens.nextToken();
\r
928 String lid = tokens.nextToken();
\r
930 // Emit that we want to switch to a new note
\r
931 evernoteLinkClicked.emit(sid, lid);
\r
935 if (url.toString().startsWith("nnres://")) {
\r
936 logger.log(logger.EXTREME, "URL is NN resource");
\r
937 if (url.toString().endsWith("/vnd.evernote.ink")) {
\r
938 logger.log(logger.EXTREME, "Unable to open ink note");
\r
939 QMessageBox.information(this, tr("Unable Open"), tr("This is an ink note.\n"+
\r
940 "Ink notes are not supported since Evernote has not\n published any specifications on them\n" +
\r
941 "and I'm too lazy to figure them out by myself."));
\r
944 String fullName = url.toString().substring(8);
\r
945 int index = fullName.indexOf(".");
\r
949 type = fullName.substring(index+1);
\r
950 guid = fullName.substring(0,index);
\r
952 index = guid.indexOf(Global.attachmentNameDelimeter);
\r
954 guid = guid.substring(0,index);
\r
956 List<Resource> resList = currentNote.getResources();
\r
957 Resource res = null;
\r
958 for (int i=0; i<resList.size(); i++) {
\r
959 if (resList.get(i).getGuid().equals(guid)) {
\r
960 res = resList.get(i);
\r
965 String resGuid = Global.resourceMap.get(guid);
\r
966 if (resGuid != null)
\r
967 res = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, true);
\r
971 if (res.getAttributes() != null &&
\r
972 res.getAttributes().getFileName() != null &&
\r
973 !res.getAttributes().getFileName().trim().equals(""))
\r
974 fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();
\r
976 fileName = res.getGuid()+"."+type;
\r
977 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
978 QFile.OpenMode mode = new QFile.OpenMode();
\r
979 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
980 boolean openResult = file.open(mode);
\r
981 logger.log(logger.EXTREME, "File opened:" +openResult);
\r
982 QDataStream out = new QDataStream(file);
\r
983 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);
\r
984 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
986 logger.log(logger.EXTREME, "Writing resource");
\r
987 out.writeBytes(binData.toByteArray());
\r
990 String whichOS = System.getProperty("os.name");
\r
991 if (whichOS.contains("Windows"))
\r
992 url.setUrl("file:///"+file.fileName());
\r
994 url.setUrl("file://"+file.fileName());
\r
995 // fileWatcher.removePath(file.fileName());
\r
996 logger.log(logger.EXTREME, "Adding file watcher " +file.fileName());
\r
997 fileWatcher.addPath(file.fileName());
\r
999 // If we can't open it, then prompt the user to save it.
\r
1000 if (!QDesktopServices.openUrl(url)) {
\r
1001 logger.log(logger.EXTREME, "We can't handle this. Where do we put it?");
\r
1002 QFileDialog dialog = new QFileDialog();
\r
1004 if (dialog.exec()!=0) {
\r
1005 List<String> fileNames = dialog.selectedFiles(); //gets all selected filenames
\r
1006 if (fileNames.size() == 0)
\r
1008 String sf = fileNames.get(0);
\r
1009 QFile saveFile = new QFile(sf);
\r
1010 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
1011 saveFile.open(mode);
\r
1012 QDataStream saveOut = new QDataStream(saveFile);
\r
1013 saveOut.writeBytes(binData.toByteArray());
\r
1021 logger.log(logger.EXTREME, "Launching URL");
\r
1022 QDesktopServices.openUrl(url);
\r
1025 // Listener for when BOLD is clicked
\r
1026 @SuppressWarnings("unused")
\r
1027 private void undoClicked() {
\r
1028 browser.page().triggerAction(WebAction.Undo);
\r
1029 browser.setFocus();
\r
1032 // Listener for when BOLD is clicked
\r
1033 @SuppressWarnings("unused")
\r
1034 private void redoClicked() {
\r
1035 browser.page().triggerAction(WebAction.Redo);
\r
1036 browser.setFocus();
\r
1039 // Listener for when BOLD is clicked
\r
1040 @SuppressWarnings("unused")
\r
1041 private void boldClicked() {
\r
1042 browser.page().triggerAction(WebAction.ToggleBold);
\r
1043 microFocusChanged();
\r
1044 browser.setFocus();
\r
1047 // Listener for when Italics is clicked
\r
1048 @SuppressWarnings("unused")
\r
1049 private void italicClicked() {
\r
1050 browser.page().triggerAction(WebAction.ToggleItalic);
\r
1051 microFocusChanged();
\r
1052 browser.setFocus();
\r
1055 // Listener for when UNDERLINE is clicked
\r
1056 @SuppressWarnings("unused")
\r
1057 private void underlineClicked() {
\r
1058 browser.page().triggerAction(WebAction.ToggleUnderline);
\r
1059 microFocusChanged();
\r
1060 browser.setFocus();
\r
1063 // Listener for when Strikethrough is clicked
\r
1064 @SuppressWarnings("unused")
\r
1065 private void strikethroughClicked() {
\r
1066 browser.page().mainFrame().evaluateJavaScript(
\r
1067 "document.execCommand('strikeThrough', false, '');");
\r
1068 browser.setFocus();
\r
1071 // Listener for when cut is clicked
\r
1072 @SuppressWarnings("unused")
\r
1073 private void cutClicked() {
\r
1074 browser.page().triggerAction(WebAction.Cut);
\r
1075 browser.setFocus();
\r
1078 // Listener when COPY is clicked
\r
1079 @SuppressWarnings("unused")
\r
1080 private void copyClicked() {
\r
1081 browser.page().triggerAction(WebAction.Copy);
\r
1082 browser.setFocus();
\r
1085 // Listener when PASTE is clicked
\r
1086 public void pasteClicked() {
\r
1087 logger.log(logger.EXTREME, "Paste Clicked");
\r
1088 if (forceTextPaste) {
\r
1089 pasteWithoutFormattingClicked();
\r
1092 QClipboard clipboard = QApplication.clipboard();
\r
1093 QMimeData mime = clipboard.mimeData();
\r
1095 // String x = mime.html();
\r
1097 if (mime.hasImage()) {
\r
1098 logger.log(logger.EXTREME, "Image paste found");
\r
1099 browser.setFocus();
\r
1100 insertImage(mime);
\r
1101 browser.setFocus();
\r
1105 if (mime.hasUrls()) {
\r
1106 logger.log(logger.EXTREME, "URL paste found");
\r
1107 if (!mime.text().startsWith("evernote:")) {
\r
1108 handleNoteLink(mime);
\r
1111 browser.setFocus();
\r
1116 String text = mime.html();
\r
1117 if (text.contains("en-tag") && mime.hasHtml()) {
\r
1118 logger.log(logger.EXTREME, "Intra-note paste found");
\r
1119 text = fixInternotePaste(text);
\r
1120 mime.setHtml(text);
\r
1121 clipboard.setMimeData(mime);
\r
1124 logger.log(logger.EXTREME, "Final paste choice encountered");
\r
1125 browser.page().triggerAction(WebAction.Paste);
\r
1126 browser.setFocus();
\r
1130 // Paste text without formatting
\r
1131 private void pasteWithoutFormattingClicked() {
\r
1132 logger.log(logger.EXTREME, "Paste without format clipped");
\r
1133 QClipboard clipboard = QApplication.clipboard();
\r
1134 QMimeData mime = clipboard.mimeData();
\r
1135 if (!mime.hasText())
\r
1137 String text = mime.text();
\r
1138 clipboard.clear();
\r
1139 clipboard.setText(text, Mode.Clipboard);
\r
1140 browser.page().triggerAction(WebAction.Paste);
\r
1142 // This is done because pasting into an encryption block
\r
1143 // can cause multiple cells (which can't happen). It
\r
1144 // just goes through the table, extracts the data, &
\r
1145 // puts it back as one table cell.
\r
1146 if (insideEncryption) {
\r
1147 String js = new String( "function fixEncryption() { "
\r
1148 +" var selObj = window.getSelection();"
\r
1149 +" var selRange = selObj.getRangeAt(0);"
\r
1150 +" var workingNode = window.getSelection().anchorNode;"
\r
1151 +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
\r
1152 +" workingNode = workingNode.parentNode;"
\r
1154 +" workingNode.innerHTML = window.jambi.fixEncryptionPaste(workingNode.innerHTML);"
\r
1155 +"} fixEncryption();");
\r
1156 browser.page().mainFrame().evaluateJavaScript(js);
\r
1160 // This basically removes all the table tags and returns just the contents.
\r
1161 // This is called by JavaScript to fix encryption pastes.
\r
1162 public String fixEncryptionPaste(String data) {
\r
1163 data = data.replace("<tbody>", "");
\r
1164 data = data.replace("</tbody>", "");
\r
1165 data = data.replace("<tr>", "");
\r
1166 data = data.replace("</tr>", "");
\r
1167 data = data.replace("<td>", "");
\r
1168 data = data.replace("</td>", "<br>");
\r
1169 data = data.replace("<br><br>", "<br>");
\r
1171 return "<tbody><tr><td>"+data+"</td></tr></tbody>";
\r
1174 // insert date/time
\r
1175 @SuppressWarnings("unused")
\r
1176 private void insertDateTime() {
\r
1177 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
\r
1178 String dateTimeFormat = new String(fmt);
\r
1179 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
\r
1180 Calendar cal = Calendar.getInstance();
\r
1182 browser.page().mainFrame().evaluateJavaScript(
\r
1183 "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");
\r
1185 browser.setFocus();
\r
1189 // Listener when Left is clicked
\r
1190 @SuppressWarnings("unused")
\r
1191 private void justifyLeftClicked() {
\r
1192 browser.page().mainFrame().evaluateJavaScript(
\r
1193 "document.execCommand('JustifyLeft', false, '');");
\r
1194 browser.setFocus();
\r
1197 // Listener when Center is clicked
\r
1198 @SuppressWarnings("unused")
\r
1199 private void justifyCenterClicked() {
\r
1200 browser.page().mainFrame().evaluateJavaScript(
\r
1201 "document.execCommand('JustifyCenter', false, '');");
\r
1202 browser.setFocus();
\r
1205 // Listener when Left is clicked
\r
1206 @SuppressWarnings("unused")
\r
1207 private void justifyRightClicked() {
\r
1208 browser.page().mainFrame().evaluateJavaScript(
\r
1209 "document.execCommand('JustifyRight', false, '');");
\r
1210 browser.setFocus();
\r
1213 // Listener when HLINE is clicked
\r
1214 @SuppressWarnings("unused")
\r
1215 private void hlineClicked() {
\r
1216 browser.page().mainFrame().evaluateJavaScript(
\r
1217 "document.execCommand('insertHorizontalRule', false, '');");
\r
1218 browser.setFocus();
\r
1221 // Listener when outdent is clicked
\r
1222 private void outdentClicked() {
\r
1223 browser.page().mainFrame().evaluateJavaScript(
\r
1224 "document.execCommand('outdent', false, '');");
\r
1225 browser.setFocus();
\r
1228 // Listener when a bullet list is clicked
\r
1229 @SuppressWarnings("unused")
\r
1230 private void bulletListClicked() {
\r
1231 browser.page().mainFrame().evaluateJavaScript(
\r
1232 "document.execCommand('InsertUnorderedList', false, '');");
\r
1233 browser.setFocus();
\r
1236 // Listener when a bullet list is clicked
\r
1237 @SuppressWarnings("unused")
\r
1238 private void numberListClicked() {
\r
1239 browser.page().mainFrame().evaluateJavaScript(
\r
1240 "document.execCommand('InsertOrderedList', false, '');");
\r
1241 browser.setFocus();
\r
1244 // Listener when indent is clicked
\r
1245 private void indentClicked() {
\r
1246 browser.page().mainFrame().evaluateJavaScript(
\r
1247 "document.execCommand('indent', false, '');");
\r
1248 browser.setFocus();
\r
1251 // Listener when the font name is changed
\r
1252 @SuppressWarnings("unused")
\r
1253 private void fontChanged(String font) {
\r
1254 browser.page().mainFrame().evaluateJavaScript(
\r
1255 "document.execCommand('fontName',false,'" + font + "');");
\r
1256 browser.setFocus();
\r
1259 // Listener when a font size is changed
\r
1260 @SuppressWarnings("unused")
\r
1261 private void fontSizeChanged(String font) {
\r
1262 String text = browser.selectedText();
\r
1263 if (text.trim().equalsIgnoreCase(""))
\r
1266 String selectedText = browser.selectedText();
\r
1267 String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";
\r
1268 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1269 browser.page().mainFrame().evaluateJavaScript(script);
\r
1270 /* browser.page().mainFrame().evaluateJavaScript(
\r
1271 "document.execCommand('fontSize',false,'"
\r
1274 browser.setFocus();
\r
1277 // Load the font combo box based upon the font selected
\r
1278 private void loadFontSize(String name) {
\r
1279 QFontDatabase db = new QFontDatabase();
\r
1281 List<Integer> points = db.pointSizes(name);
\r
1282 for (int i=0; i<points.size(); i++) {
\r
1283 fontSize.addItem(points.get(i).toString());
\r
1286 fontSize.addItem("x-small");
\r
1287 fontSize.addItem("small");
\r
1288 fontSize.addItem("medium");
\r
1289 fontSize.addItem("large");
\r
1290 fontSize.addItem("x-large");
\r
1291 fontSize.addItem("xx-large");
\r
1292 fontSize.addItem("xxx-large");
\r
1296 // Listener when a font size is changed
\r
1297 @SuppressWarnings("unused")
\r
1298 private void fontColorClicked() {
\r
1299 // QColorDialog dialog = new QColorDialog();
\r
1300 // QColor color = QColorDialog.getColor();
\r
1301 QColor color = fontColorMenu.getColor();
\r
1302 if (color.isValid())
\r
1303 browser.page().mainFrame().evaluateJavaScript(
\r
1304 "document.execCommand('foreColor',false,'" + color.name()
\r
1306 browser.setFocus();
\r
1309 // Listener for when a background color change is requested
\r
1310 @SuppressWarnings("unused")
\r
1311 private void fontHilightClicked() {
\r
1312 // QColorDialog dialog = new QColorDialog();
\r
1313 // QColor color = QColorDialog.getColor();
\r
1314 QColor color = fontHilightColorMenu.getColor();
\r
1315 if (color.isValid())
\r
1316 browser.page().mainFrame().evaluateJavaScript(
\r
1317 "document.execCommand('backColor',false,'" + color.name()
\r
1319 browser.setFocus();
\r
1322 // Listener for when a background color change is requested
\r
1323 @SuppressWarnings("unused")
\r
1324 private void superscriptClicked() {
\r
1325 browser.page().mainFrame().evaluateJavaScript(
\r
1326 "document.execCommand('superscript');");
\r
1327 browser.setFocus();
\r
1330 // Listener for when a background color change is requested
\r
1331 @SuppressWarnings("unused")
\r
1332 private void subscriptClicked() {
\r
1333 browser.page().mainFrame().evaluateJavaScript(
\r
1334 "document.execCommand('subscript');");
\r
1335 browser.setFocus();
\r
1337 // Insert a to-do checkbox
\r
1338 @SuppressWarnings("unused")
\r
1339 private void todoClicked() {
\r
1340 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1341 String script_start = new String(
\r
1342 "document.execCommand('insertHtml', false, '");
\r
1343 String script_end = new String("');");
\r
1344 String todo = new String(
\r
1345 "<input TYPE=\"CHECKBOX\" value=\"false\" " +
\r
1346 "onMouseOver=\"style.cursor=\\'hand\\'\" " +
\r
1347 "onClick=\"value=checked; window.jambi.contentChanged(); \" />");
\r
1348 browser.page().mainFrame().evaluateJavaScript(
\r
1349 script_start + todo + script_end);
\r
1350 browser.setFocus();
\r
1353 // Encrypt the selected text
\r
1354 @SuppressWarnings("unused")
\r
1355 private void encryptText() {
\r
1356 String text = browser.selectedText();
\r
1357 if (text.trim().equalsIgnoreCase(""))
\r
1359 text = new String(text.replaceAll("\n", "<br/>"));
\r
1361 EnCryptDialog dialog = new EnCryptDialog();
\r
1363 if (!dialog.okPressed()) {
\r
1367 EnCrypt crypt = new EnCrypt();
\r
1368 String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);
\r
1369 String decrypted = crypt.decrypt(encrypted, dialog.getPassword().trim(), 64);
\r
1371 if (encrypted.trim().equals("")) {
\r
1372 QMessageBox.information(this, tr("Error"), tr("Error Encrypting String"));
\r
1375 StringBuffer buffer = new StringBuffer(encrypted.length() + 100);
\r
1376 buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""
\r
1377 + dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");
\r
1378 buffer.append("contentEditable=\"false\" alt=\"");
\r
1379 buffer.append(encrypted);
\r
1380 buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png") +"\""));
\r
1381 Global.cryptCounter++;
\r
1382 buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");
\r
1383 buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");
\r
1384 buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString()
\r
1385 +"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&apos;")+"\\');\"");
\r
1386 buffer.append("style=\"display:block\" />");
\r
1388 String script_start = new String(
\r
1389 "document.execCommand('insertHtml', false, '");
\r
1390 String script_end = new String("');");
\r
1391 browser.page().mainFrame().evaluateJavaScript(
\r
1392 script_start + buffer.toString() + script_end);
\r
1396 // Insert a hyperlink
\r
1397 public void insertLink() {
\r
1398 logger.log(logger.EXTREME, "Inserting link");
\r
1399 String text = browser.selectedText();
\r
1400 if (text.trim().equalsIgnoreCase(""))
\r
1403 InsertLinkDialog dialog = new InsertLinkDialog(insertHyperlink);
\r
1404 if (currentHyperlink != null && currentHyperlink != "") {
\r
1405 dialog.setUrl(currentHyperlink);
\r
1408 if (!dialog.okPressed()) {
\r
1409 logger.log(logger.EXTREME, "Insert link canceled");
\r
1413 // Take care of inserting new links
\r
1414 if (insertHyperlink) {
\r
1415 String selectedText = browser.selectedText();
\r
1416 if (dialog.getUrl().trim().equals(""))
\r
1418 logger.log(logger.EXTREME, "Inserting link on text "+selectedText);
\r
1419 logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim());
\r
1420 String dUrl = StringUtils.replace(dialog.getUrl().trim(), "'", "\\'");
\r
1421 String url = "<a href=\"" +dUrl
\r
1422 +"\" title=" +dUrl
\r
1423 +" >"+selectedText +"</a>";
\r
1424 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1425 browser.page().mainFrame().evaluateJavaScript(script);
\r
1429 // Edit existing links
\r
1430 String js = new String( "function getCursorPos() {"
\r
1432 +"if (window.getSelection) {"
\r
1433 +" var selObj = window.getSelection();"
\r
1434 +" var selRange = selObj.getRangeAt(0);"
\r
1435 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1436 +" while(workingNode != null) { "
\r
1437 +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');"
\r
1438 +" workingNode = workingNode.parentNode;"
\r
1441 +"} getCursorPos();");
\r
1442 browser.page().mainFrame().evaluateJavaScript(js);
\r
1444 if (!dialog.getUrl().trim().equals("")) {
\r
1450 js = new String( "function getCursorPos() {"
\r
1452 +"if (window.getSelection) {"
\r
1453 +" var selObj = window.getSelection();"
\r
1454 +" var selRange = selObj.getRangeAt(0);"
\r
1455 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1456 +" while(workingNode != null) { "
\r
1457 +" if (workingNode.nodeName.toLowerCase()=='a') { "
\r
1458 +" workingNode.removeAttribute('href');"
\r
1459 +" workingNode.removeAttribute('title');"
\r
1460 +" var text = document.createTextNode(workingNode.innerText);"
\r
1461 +" workingNode.parentNode.insertBefore(text, workingNode);"
\r
1462 +" workingNode.parentNode.removeChild(workingNode);"
\r
1464 +" workingNode = workingNode.parentNode;"
\r
1467 +"} getCursorPos();");
\r
1468 browser.page().mainFrame().evaluateJavaScript(js);
\r
1476 // Insert a hyperlink
\r
1477 public void insertLatex() {
\r
1480 public void editLatex(String guid) {
\r
1481 logger.log(logger.EXTREME, "Inserting latex");
\r
1482 String text = browser.selectedText();
\r
1483 if (text.trim().equalsIgnoreCase(" ") || text.trim().equalsIgnoreCase("")) {
\r
1484 InsertLatexImage dialog = new InsertLatexImage();
\r
1485 if (guid != null) {
\r
1486 String formula = conn.getNoteTable().noteResourceTable.getNoteSourceUrl(guid).replace("http://latex.codecogs.com/gif.latex?", "");
\r
1487 dialog.setFormula(formula);
\r
1490 if (!dialog.okPressed()) {
\r
1491 logger.log(logger.EXTREME, "Edit LaTex canceled");
\r
1494 text = dialog.getFormula().trim();
\r
1496 blockApplication.emit(this);
\r
1497 logger.log(logger.EXTREME, "Inserting LaTeX formula:" +text);
\r
1499 text = StringUtils.replace(text, "'", "\\'");
\r
1500 String url = "http://latex.codecogs.com/gif.latex?" +text;
\r
1501 logger.log(logger.EXTREME, "Sending request to codecogs --> " + url);
\r
1502 QNetworkAccessManager manager = new QNetworkAccessManager(this);
\r
1503 manager.finished.connect(this, "insertLatexImageReady(QNetworkReply)");
\r
1504 unblockTime = new GregorianCalendar().getTimeInMillis()+5000;
\r
1505 awaitingHttpResponse = true;
\r
1506 manager.get(new QNetworkRequest(new QUrl(url)));
\r
1509 public void insertLatexImageReady(QNetworkReply reply) {
\r
1510 logger.log(logger.EXTREME, "Response received from CodeCogs");
\r
1511 if (reply.error() != NetworkError.NoError)
\r
1515 if (!awaitingHttpResponse)
\r
1518 awaitingHttpResponse = false;
\r
1519 QUrl replyUrl = reply.url();
\r
1520 QByteArray image = reply.readAll();
\r
1522 logger.log(logger.EXTREME, "New image size: " +image.size());
\r
1524 Resource newRes = null;
\r
1527 if (latexGuid == null) {
\r
1528 logger.log(logger.EXTREME, "Creating temporary gif");
\r
1529 path = Global.getFileManager().getResDirPath("latex-temp.gif");
\r
1530 tfile = new QFile(path);
\r
1531 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1532 logger.log(logger.EXTREME, "File Open: " +tfile.errorString());
\r
1533 tfile.write(image);
\r
1534 logger.log(logger.EXTREME, "Bytes writtes: "+tfile.size());
\r
1536 logger.log(logger.EXTREME, "Creating resource");
\r
1538 if (currentNote.getResources() != null || currentNote.getResources().size() > 0)
\r
1539 sequence = currentNote.getResources().size();
\r
1540 newRes = createResource(path,sequence ,"image/gif", false);
\r
1541 QImage pix = new QImage();
\r
1542 pix.loadFromData(image);
\r
1543 newRes.setHeight(new Integer(pix.height()).shortValue());
\r
1544 newRes.setWidth(new Integer(pix.width()).shortValue());
\r
1545 logger.log(logger.EXTREME, "Renaming temporary file to " +newRes.getGuid()+".gif");
\r
1546 path = Global.getFileManager().getResDirPath(newRes.getGuid()+".gif");
\r
1547 tfile.rename(path);
\r
1549 newRes = conn.getNoteTable().noteResourceTable.getNoteResource(latexGuid, false);
\r
1550 path = Global.getFileManager().getResDirPath(newRes.getGuid()+".gif");
\r
1551 tfile = new QFile(path);
\r
1552 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1553 tfile.write(image);
\r
1555 newRes.getData().setBody(image.toByteArray());
\r
1556 // Calculate the new hash value
\r
1559 logger.log(logger.EXTREME, "Generating MD5");
\r
1561 md = MessageDigest.getInstance("MD5");
\r
1562 md.update(image.toByteArray());
\r
1563 byte[] hash = md.digest();
\r
1564 newRes.getData().setBodyHash(hash);
\r
1565 } catch (NoSuchAlgorithmException e) {
\r
1566 e.printStackTrace();
\r
1568 QImage pix = new QImage();
\r
1569 pix.loadFromData(image);
\r
1570 newRes.setHeight(new Integer(pix.height()).shortValue());
\r
1571 newRes.setWidth(new Integer(pix.width()).shortValue());
\r
1572 conn.getNoteTable().noteResourceTable.updateNoteResource(newRes, true);
\r
1575 logger.log(logger.EXTREME, "Setting source: " +replyUrl.toString());
\r
1576 newRes.getAttributes().setSourceURL(replyUrl.toString());
\r
1577 conn.getNoteTable().noteResourceTable.updateNoteSourceUrl(newRes.getGuid(), replyUrl.toString(), true);
\r
1579 for(int i=0; i<currentNote.getResourcesSize(); i++) {
\r
1580 if (currentNote.getResources().get(i).getGuid().equals(newRes.getGuid())) {
\r
1581 currentNote.getResources().remove(i);
\r
1582 i=currentNote.getResourcesSize();
\r
1585 currentNote.getResources().add(newRes);
\r
1588 // do the actual insert into the note. We only do this on new formulas.
\r
1589 if (latexGuid == null) {
\r
1590 StringBuffer buffer = new StringBuffer(100);
\r
1591 String formula = replyUrl.toString().toLowerCase().replace("http://latex.codecogs.com/gif.latex?", "");
\r
1592 buffer.append("<a href=\"latex://"+path.replace("\\", "/")+"\" title=\""+formula+"\""
\r
1594 buffer.append(path.replace("\\", "/"));
\r
1595 buffer.append("\" en-tag=\"en-latex\" type=\"image/gif\""
\r
1596 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1597 +" guid=\"" +newRes.getGuid() +"\""
\r
1600 String script_start = new String("document.execCommand('insertHTML', false, '");
\r
1601 String script_end = new String("');");
\r
1602 browser.page().mainFrame().evaluateJavaScript(
\r
1603 script_start + buffer + script_end);
\r
1605 HtmlTagModifier modifier = new HtmlTagModifier(getContent());
\r
1606 modifier.modifyLatexTagHash(newRes);
\r
1607 String newContent = modifier.getHtml();
\r
1608 setContent(new QByteArray(newContent));
\r
1611 logger.log(logger.EXTREME, "New HTML set\n" +browser.page().currentFrame().toHtml());
\r
1612 QWebSettings.setMaximumPagesInCache(0);
\r
1613 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
1615 browser.page().mainFrame().setHtml(browser.page().mainFrame().toHtml());
\r
1618 // resourceSignal.contentChanged.emit(path);
\r
1620 unblockApplication.emit();
\r
1628 public void insertTable() {
\r
1629 TableDialog dialog = new TableDialog();
\r
1631 if (!dialog.okPressed()) {
\r
1635 int cols = dialog.getCols();
\r
1636 int rows = dialog.getRows();
\r
1637 int width = dialog.getWidth();
\r
1638 boolean percent = dialog.isPercent();
\r
1640 String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();
\r
1642 newHTML = newHTML +"%";
\r
1643 newHTML = newHTML + "\"><tbody>";
\r
1645 for (int i=0; i<rows; i++) {
\r
1646 newHTML = newHTML +"<tr>";
\r
1647 for (int j=0; j<cols; j++) {
\r
1648 newHTML = newHTML +"<td> </td>";
\r
1650 newHTML = newHTML +"</tr>";
\r
1652 newHTML = newHTML+"</tbody></table>";
\r
1654 String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";
\r
1655 browser.page().mainFrame().evaluateJavaScript(script);
\r
1659 // Text content changed
\r
1660 @SuppressWarnings("unused")
\r
1661 private void selectionChanged() {
\r
1662 browser.encryptAction.setEnabled(true);
\r
1663 browser.insertLinkAction.setEnabled(true);
\r
1664 String scriptStart = "var selection_text = (window.getSelection()).toString();"
\r
1665 + "var range = (window.getSelection()).getRangeAt(0);"
\r
1666 + "var parent_html = range.commonAncestorContainer.innerHTML;"
\r
1667 + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"
\r
1668 + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"
\r
1669 + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"
\r
1670 + "var start = parent_html.indexOf(first_text);"
\r
1671 + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"
\r
1672 + "var value = parent_html.substring(start,end);"
\r
1673 + "window.jambi.saveSelectedText(value);" ;
\r
1674 browser.page().mainFrame().evaluateJavaScript(scriptStart);
\r
1678 public void saveSelectedText(String text) {
\r
1679 boolean enabled = true;
\r
1680 if (text.trim().length() == 0)
\r
1682 if (text.indexOf("en-tag=\"en-crypt\"") >= 0)
\r
1684 if (text.indexOf("<img en-tag=\"en-media\"") >= 0)
\r
1686 if (text.indexOf("<a en-tag=\"en-media\"") >= 0)
\r
1688 if (text.indexOf("<input ") >= 0)
\r
1691 browser.encryptAction.setEnabled(enabled);
\r
1692 browser.insertLinkAction.setEnabled(enabled);
\r
1693 // selectedText = text;
\r
1696 // Decrypt clicked text
\r
1697 public void decryptText(String id, String text, String hint) {
\r
1698 EnCrypt crypt = new EnCrypt();
\r
1699 String plainText = null;
\r
1700 Calendar currentTime = new GregorianCalendar();
\r
1701 Long l = new Long(currentTime.getTimeInMillis());
\r
1702 String slot = new String(Long.toString(l));
\r
1704 // First, try to decrypt with any keys we already have
\r
1705 for (int i=0; i<Global.passwordRemember.size(); i++) {
\r
1706 plainText = crypt.decrypt(text, Global.passwordRemember.get(i).getFirst(), 64);
\r
1707 if (plainText != null) {
\r
1708 slot = new String(Long.toString(l));
\r
1709 Global.passwordSafe.put(slot, Global.passwordRemember.get(i));
\r
1710 removeEncryption(id, plainText, false, slot);
\r
1716 EnDecryptDialog dialog = new EnDecryptDialog();
\r
1717 dialog.setHint(hint);
\r
1718 while (plainText == null || !dialog.okPressed()) {
\r
1720 if (!dialog.okPressed()) {
\r
1723 plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);
\r
1724 if (plainText == null) {
\r
1725 QMessageBox.warning(this, tr("Incorrect Password"), tr("The password entered is not correct"));
\r
1728 Pair<String,String> passwordPair = new Pair<String,String>();
\r
1729 passwordPair.setFirst(dialog.getPassword());
\r
1730 passwordPair.setSecond(dialog.getHint());
\r
1731 Global.passwordSafe.put(slot, passwordPair);
\r
1732 // removeEncryption(id, plainText.replaceAll("\n", "<br/>"), dialog.permanentlyDecrypt(), slot);
\r
1733 removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);
\r
1734 if (dialog.rememberPassword()) {
\r
1735 Pair<String, String> pair = new Pair<String,String>();
\r
1736 pair.setFirst(dialog.getPassword());
\r
1737 pair.setSecond(dialog.getHint());
\r
1738 Global.passwordRemember.add(pair);
\r
1743 // Get the editor tag line
\r
1744 public TagLineEdit getTagLine() {
\r
1748 // Modify a note's tags
\r
1749 @SuppressWarnings("unused")
\r
1750 private void modifyTags() {
\r
1751 TagAssign tagWindow = new TagAssign(allTags, currentTags, !conn.getNotebookTable().isLinked(currentNote.getNotebookGuid()));
\r
1753 if (tagWindow.okClicked()) {
\r
1754 currentTags.clear();
\r
1755 StringBuffer tagDisplay = new StringBuffer();
\r
1757 List<QListWidgetItem> newTags = tagWindow.getTagList()
\r
1759 for (int i = 0; i < newTags.size(); i++) {
\r
1760 currentTags.add(newTags.get(i).text());
\r
1761 tagDisplay.append(newTags.get(i).text());
\r
1762 if (i < newTags.size() - 1) {
\r
1763 tagDisplay.append(Global.tagDelimeter + " ");
\r
1766 tagEdit.setText(tagDisplay.toString());
\r
1767 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1771 // Tag line has been modified by typing text
\r
1772 @SuppressWarnings("unused")
\r
1773 private void modifyTagsTyping() {
\r
1774 String completionText = "";
\r
1775 if (tagEdit.currentCompleterSelection != null && !tagEdit.currentCompleterSelection.equals("")) {
\r
1776 completionText = tagEdit.currentCompleterSelection;
\r
1777 tagEdit.currentCompleterSelection = "";
\r
1780 if (tagEdit.text().equalsIgnoreCase(saveTagList))
\r
1783 // We know something has changed...
\r
1784 String oldTagArray[] = saveTagList.split(Global.tagDelimeter);
\r
1785 String newTagArray[];
\r
1786 if (!completionText.equals("")) {
\r
1787 String before = tagEdit.text().substring(0,tagEdit.cursorPosition());
\r
1788 int lastDelimiter = before.lastIndexOf(Global.tagDelimeter);
\r
1789 if (lastDelimiter > 0)
\r
1790 before = before.substring(0,before.lastIndexOf(Global.tagDelimeter));
\r
1793 String after = tagEdit.text().substring(tagEdit.cursorPosition());
\r
1794 newTagArray = (before+Global.tagDelimeter+completionText+Global.tagDelimeter+after).split(Global.tagDelimeter);
\r
1797 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1800 // Remove any traling or leading blanks
\r
1801 for (int i=0; i<newTagArray.length; i++)
\r
1802 newTagArray[i] = newTagArray[i].trim().replaceAll("^\\s+", "");;
\r
1804 // Remove any potential duplicates from the new list
\r
1805 for (int i=0; i<newTagArray.length; i++) {
\r
1806 boolean foundOnce = false;
\r
1807 for (int j=0; j<newTagArray.length; j++) {
\r
1808 if (newTagArray[j].equalsIgnoreCase(newTagArray[i])) {
\r
1812 newTagArray[j] = "";
\r
1817 List<String> newTagList = new ArrayList<String>();
\r
1818 List<String> oldTagList = new ArrayList<String>();
\r
1820 for (int i = 0; i < oldTagArray.length; i++)
\r
1821 if (!oldTagArray[i].trim().equals(""))
\r
1822 oldTagList.add(oldTagArray[i]);
\r
1823 for (int i = 0; i < newTagArray.length; i++)
\r
1824 if (!newTagArray[i].trim().equals(""))
\r
1825 newTagList.add(newTagArray[i]);
\r
1827 if (conn.getNotebookTable().isLinked(currentNote.getNotebookGuid())) {
\r
1828 for (int i=newTagList.size()-1; i>=0; i--) {
\r
1829 boolean found = false;
\r
1830 for (int j=0; j<allTags.size(); j++) {
\r
1831 if (allTags.get(j).getName().equalsIgnoreCase(newTagList.get(i))) {
\r
1837 newTagList.remove(i);
\r
1841 // Let's cleanup the appearance of the tag list
\r
1842 Collections.sort(newTagList);
\r
1843 String newDisplay = "";
\r
1844 for (int i=0; i<newTagList.size(); i++) {
\r
1845 newDisplay = newDisplay+newTagList.get(i);
\r
1846 if (i<newTagList.size()-1)
\r
1847 newDisplay = newDisplay+Global.tagDelimeter +" ";
\r
1849 tagEdit.blockSignals(true);
\r
1850 tagEdit.setText(newDisplay);
\r
1851 tagEdit.blockSignals(false);
\r
1853 // We now have lists of the new & old. Remove duplicates. If all
\r
1854 // are removed from both then nothing has really changed
\r
1855 for (int i = newTagList.size() - 1; i >= 0; i--) {
\r
1856 String nTag = newTagList.get(i);
\r
1857 for (int j = oldTagList.size() - 1; j >= 0; j--) {
\r
1858 String oTag = oldTagList.get(j);
\r
1859 if (oTag.equalsIgnoreCase(nTag)) {
\r
1860 oldTagList.remove(j);
\r
1861 newTagList.remove(i);
\r
1867 if (oldTagList.size() != 0 || newTagList.size() != 0) {
\r
1868 currentTags.clear();
\r
1869 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1870 for (int i = 0; i < newTagArray.length; i++)
\r
1871 if (!newTagArray[i].trim().equals(""))
\r
1872 currentTags.add(newTagArray[i].trim());
\r
1874 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1879 // Tab button was pressed
\r
1880 public void tabPressed() {
\r
1881 if (insideEncryption)
\r
1883 if (!insideList && !insideTable) {
\r
1884 String script_start = new String(
\r
1885 "document.execCommand('insertHtml', false, ' ');");
\r
1886 browser.page().mainFrame().evaluateJavaScript(script_start);
\r
1892 if (insideTable) {
\r
1893 String js = new String( "function getCursorPosition() { "
\r
1894 +" var selObj = window.getSelection();"
\r
1895 +" var selRange = selObj.getRangeAt(0);"
\r
1896 +" var workingNode = window.getSelection().anchorNode;"
\r
1897 +" var rowCount = 0;"
\r
1898 +" var colCount = 0;"
\r
1899 +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
\r
1900 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
1901 +" rowCount = rowCount+1;"
\r
1903 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
1904 +" colCount = colCount+1;"
\r
1906 +" if (workingNode.previousSibling != null)"
\r
1907 +" workingNode = workingNode.previousSibling;"
\r
1909 +" workingNode = workingNode.parentNode;"
\r
1911 +" var nodes = workingNode.getElementsByTagName('tr');"
\r
1912 +" var tableRows = nodes.length;"
\r
1913 +" nodes = nodes[0].getElementsByTagName('td');"
\r
1914 +" var tableColumns = nodes.length;"
\r
1915 +" window.jambi.setTableCursorPositionTab(rowCount, colCount, tableRows, tableColumns);"
\r
1916 +"} getCursorPosition();");
\r
1917 browser.page().mainFrame().evaluateJavaScript(js);
\r
1921 // If a user presses tab from within a table
\r
1922 public void setTableCursorPositionTab(int currentRow, int currentCol, int tableRows, int tableColumns) {
\r
1923 if (tableRows == currentRow && currentCol == tableColumns) {
\r
1926 KeyboardModifiers modifiers = new KeyboardModifiers(KeyboardModifier.NoModifier);
\r
1927 QKeyEvent right = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Right.value(), modifiers);
\r
1928 QKeyEvent end = new QKeyEvent(Type.KeyPress, Qt.Key.Key_End.value(), modifiers);
\r
1929 QKeyEvent end2 = new QKeyEvent(Type.KeyPress, Qt.Key.Key_End.value(), modifiers);
\r
1930 getBrowser().focusWidget();
\r
1931 QCoreApplication.postEvent(getBrowser(), end);
\r
1932 QCoreApplication.postEvent(getBrowser(), right);
\r
1933 QCoreApplication.postEvent(getBrowser(), end2);
\r
1936 public void backtabPressed() {
\r
1937 if (insideEncryption)
\r
1941 if (insideTable) {
\r
1942 String js = new String( "function getCursorPosition() { "
\r
1943 +" var selObj = window.getSelection();"
\r
1944 +" var selRange = selObj.getRangeAt(0);"
\r
1945 +" var workingNode = window.getSelection().anchorNode;"
\r
1946 +" var rowCount = 0;"
\r
1947 +" var colCount = 0;"
\r
1948 +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
\r
1949 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
1950 +" rowCount = rowCount+1;"
\r
1952 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
1953 +" colCount = colCount+1;"
\r
1955 +" if (workingNode.previousSibling != null)"
\r
1956 +" workingNode = workingNode.previousSibling;"
\r
1958 +" workingNode = workingNode.parentNode;"
\r
1960 +" var nodes = workingNode.getElementsByTagName('tr');"
\r
1961 +" var tableRows = nodes.length;"
\r
1962 +" nodes = nodes[0].getElementsByTagName('td');"
\r
1963 +" var tableColumns = nodes.length;"
\r
1964 +" window.jambi.setTableCursorPositionBackTab(rowCount, colCount, tableRows, tableColumns);"
\r
1965 +"} getCursorPosition();");
\r
1966 browser.page().mainFrame().evaluateJavaScript(js);
\r
1971 // If a user presses backtab from within a table
\r
1972 public void setTableCursorPositionBackTab(int currentRow, int currentCol, int tableRows, int tableColumns) {
\r
1973 if (currentRow == 1 && currentCol == 1) {
\r
1976 KeyboardModifiers modifiers = new KeyboardModifiers(KeyboardModifier.NoModifier);
\r
1977 QKeyEvent left = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Left.value(), modifiers);
\r
1978 QKeyEvent home = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Home.value(), modifiers);
\r
1979 getBrowser().focusWidget();
\r
1980 QCoreApplication.postEvent(getBrowser(), home);
\r
1981 QCoreApplication.postEvent(getBrowser(), left);
\r
1985 public void setInsideList() {
\r
1986 insideList = true;
\r
1989 // The title has been edited
\r
1990 @SuppressWarnings("unused")
\r
1991 private void titleEdited() {
\r
1992 // If we don't have a good note, or if the current title
\r
1993 // matches the old title then we don't need to do anything
\r
1994 if (currentNote == null)
\r
1996 if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))
\r
1999 // If we have a real change, we need to save it.
\r
2000 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text());
\r
2001 currentNote.setTitle(titleLabel.text());
\r
2002 saveNoteTitle = titleLabel.text();
\r
2006 // Set the list of note tags
\r
2007 public void setAllTags(List<Tag> l) {
\r
2009 tagEdit.setTagList(l);
\r
2012 // Setter for the current tags
\r
2013 public void setCurrentTags(List<String> s) {
\r
2017 // Save the list of notebooks
\r
2018 public void setNotebookList(List<Notebook> n) {
\r
2020 loadNotebookList();
\r
2023 // Load the notebook list and select the current notebook
\r
2024 private void loadNotebookList() {
\r
2025 if (notebookBox.count() != 0)
\r
2026 notebookBox.clear();
\r
2027 if (notebookList == null)
\r
2030 for (int i = 0; i < notebookList.size(); i++) {
\r
2031 notebookBox.addItem(notebookList.get(i).getName());
\r
2032 if (currentNote != null) {
\r
2033 if (currentNote.getNotebookGuid().equals(
\r
2034 notebookList.get(i).getGuid())) {
\r
2035 notebookBox.setCurrentIndex(i);
\r
2042 // Set the notebook for a note
\r
2043 public void setNotebook(String notebook) {
\r
2044 currentNote.setNotebookGuid(notebook);
\r
2045 loadNotebookList();
\r
2048 // Get the contents of the editor
\r
2049 public String getContent() {
\r
2050 return browser.page().currentFrame().toHtml();
\r
2053 // The note contents have changed
\r
2054 public void contentChanged() {
\r
2055 String content = getContent();
\r
2056 setSource(content);
\r
2059 noteSignal.noteChanged.emit(currentNote.getGuid(), content);
\r
2062 // The notebook selection has changed
\r
2063 @SuppressWarnings("unused")
\r
2064 private void notebookChanged() {
\r
2065 boolean changed = false;
\r
2066 String n = notebookBox.currentText();
\r
2067 for (int i = 0; i < notebookList.size(); i++) {
\r
2068 if (n.equals(notebookList.get(i).getName())) {
\r
2069 if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {
\r
2070 String guid = conn.getNotebookTable().findNotebookByName(n);
\r
2071 if (conn.getNotebookTable().isLinked(guid)) {
\r
2072 tagEdit.setText("");
\r
2073 noteSignal.tagsChanged.emit(currentNote.getGuid(), new ArrayList<String>());
\r
2074 FilterEditorTags t = new FilterEditorTags(conn, logger);
\r
2075 setAllTags(t.getValidTags(currentNote));
\r
2077 currentNote.setNotebookGuid(notebookList.get(i).getGuid());
\r
2080 i = notebookList.size();
\r
2084 // If the notebook changed, signal the update
\r
2086 noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote
\r
2087 .getNotebookGuid());
\r
2090 // Check the note title
\r
2091 private void checkNoteTitle() {
\r
2092 String text = browser.page().currentFrame().toPlainText();
\r
2093 if (saveNoteTitle.trim().equals("") || saveNoteTitle.trim().equals("Untitled Note")) {
\r
2094 int newLine = text.indexOf("\n");
\r
2095 if (newLine > 0) {
\r
2096 text = text.substring(0, newLine);
\r
2097 if (text.trim().equals(""))
\r
2098 text = tr("Untitled Note");
\r
2099 titleLabel.setText(text);
\r
2101 if (text.length() > Constants.EDAM_NOTE_TITLE_LEN_MAX)
\r
2102 titleLabel.setText(text.substring(0, Constants.EDAM_NOTE_TITLE_LEN_MAX));
\r
2104 titleLabel.blockSignals(true);
\r
2105 if (text.trim().equals(""))
\r
2106 titleLabel.setText(tr("Untitled Note"));
\r
2108 titleLabel.setText(text);
\r
2109 titleLabel.blockSignals(false);
\r
2112 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel
\r
2117 // Return the note contents so we can email them
\r
2118 public String getContentsToEmail() {
\r
2119 return browser.page().currentFrame().toPlainText().trim();
\r
2121 * int body = browser.page().currentFrame().toHtml().indexOf("<body>");
\r
2122 * String temp = browser.page().currentFrame().toHtml(); if (body == -1)
\r
2123 * temp = "<html><body><b>Test</b></body></html>"; else temp =
\r
2124 * "<html>"+temp.substring(body); return temp; // return
\r
2125 * urlEncode(browser.page().currentFrame().toHtml());
\r
2129 // Insert an image into the editor
\r
2130 private void insertImage(QMimeData mime) {
\r
2131 logger.log(logger.EXTREME, "Entering insertImage");
\r
2132 QImage img = (QImage) mime.imageData();
\r
2133 String script_start = new String(
\r
2134 "document.execCommand('insertHTML', false, '");
\r
2135 String script_end = new String("');");
\r
2137 long now = new Date().getTime();
\r
2138 String path = Global.getFileManager().getResDirPath(
\r
2139 (new Long(now).toString()) + ".jpg");
\r
2141 // This block is just a hack to make sure we wait at least 1ms so we
\r
2143 // have collisions on image names
\r
2144 long i = new Date().getTime();
\r
2146 i = new Date().getTime();
\r
2148 // Open the file & write the data
\r
2149 QFile tfile = new QFile(path);
\r
2150 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
2151 if (!img.save(tfile)) {
\r
2157 Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);
\r
2158 if (newRes == null)
\r
2160 currentNote.getResources().add(newRes);
\r
2162 // do the actual insert into the note
\r
2163 StringBuffer buffer = new StringBuffer(100);
\r
2164 buffer.append("<img src=\"");
\r
2165 buffer.append(tfile.fileName());
\r
2166 buffer.append("\" en-tag=en-media type=\"image/jpeg\""
\r
2167 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
2168 +" guid=\"" +newRes.getGuid() +"\""
\r
2169 +" onContextMenu=\"window.jambi.imageContextMenu(&." +tfile.fileName() +"&.);\""
\r
2172 browser.page().mainFrame().evaluateJavaScript(
\r
2173 script_start + buffer + script_end);
\r
2178 // Handle pasting of a note-to-note link
\r
2179 private void handleNoteLink(QMimeData mime) {
\r
2180 for (int i=0; i<mime.urls().size(); i++) {
\r
2181 StringTokenizer tokens = new StringTokenizer(mime.urls().get(i).toString().replace("evernote:///view/", ""), "/");
\r
2182 tokens.nextToken();
\r
2183 tokens.nextToken();
\r
2184 String sid = tokens.nextToken();
\r
2185 String lid = tokens.nextToken();
\r
2187 if (!sid.equals(currentNote.getGuid()) && !lid.equals(currentNote.getGuid())) {
\r
2189 Note note = conn.getNoteTable().getNote(sid, false, false, false, false, false);
\r
2191 note = conn.getNoteTable().getNote(lid, false, false, false, false, false);
\r
2196 // If we've gotten this far, we have a bunch of values. We need to build the link.
\r
2197 StringBuffer url = new StringBuffer(100);
\r
2198 String script_start = new String(
\r
2199 "document.execCommand('insertHtml', false, '");
\r
2200 String script_end = new String("');");
\r
2202 url.append("<a href=\""+mime.urls().get(i).toString() +"\" style=\"color:#69aa35\">");
\r
2203 url.append(note.getTitle());
\r
2204 url.append("</a>");
\r
2205 if (mime.urls().size() > 1)
\r
2206 url.append(" ");
\r
2207 browser.page().mainFrame().evaluateJavaScript(
\r
2208 script_start + url + script_end);
\r
2213 // Handle URLs that are trying to be pasted
\r
2214 public void handleUrls(QMimeData mime) {
\r
2215 logger.log(logger.EXTREME, "Starting handleUrls");
\r
2216 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
2218 List<QUrl> urlList = mime.urls();
\r
2219 String url = new String();
\r
2220 String script_start = new String(
\r
2221 "document.execCommand('createLink', false, '");
\r
2222 String script_end = new String("');");
\r
2224 for (int i = 0; i < urlList.size(); i++) {
\r
2225 url = urlList.get(i).toString();
\r
2226 // Find out what type of file we have
\r
2227 String mimeType = fileNameMap.getContentTypeFor(url);
\r
2229 // If null returned, we need to guess at the file type
\r
2230 if (mimeType == null)
\r
2231 mimeType = "application/"
\r
2232 + url.substring(url.lastIndexOf(".") + 1);
\r
2234 // Check if we have an image or some other type of file
\r
2235 if (url.substring(0, 5).equalsIgnoreCase("file:")
\r
2236 && mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
2237 handleLocalImageURLPaste(mime, mimeType);
\r
2240 String[] type = mimeType.split("/");
\r
2241 boolean valid = validAttachment(type[1]);
\r
2242 boolean smallEnough = checkFileAttachmentSize(url);
\r
2243 if (smallEnough && valid
\r
2244 && url.substring(0, 5).equalsIgnoreCase("file:")
\r
2245 && !mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
2246 handleLocalAttachment(mime, mimeType);
\r
2249 browser.page().mainFrame().evaluateJavaScript(
\r
2250 script_start + url + script_end);
\r
2255 // If a URL being pasted is an image URL, then attach the image
\r
2256 private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {
\r
2257 List<QUrl> urlList = mime.urls();
\r
2258 String url = new String();
\r
2259 String script_start_image = new String(
\r
2260 "document.execCommand('insertHtml', false, '");
\r
2261 String script_end = new String("');");
\r
2262 StringBuffer buffer;
\r
2264 // Copy the image over into the resource directory and create a new resource
\r
2265 // record for each url pasted
\r
2266 for (int i = 0; i < urlList.size(); i++) {
\r
2267 url = urlList.get(i).toString();
\r
2269 Resource newRes = createResource(url, i, mimeType, false);
\r
2270 if (newRes == null)
\r
2272 currentNote.getResources().add(newRes);
\r
2273 buffer = new StringBuffer(100);
\r
2275 // Open the file & write the data
\r
2276 String fileName = Global.getFileManager().getResDirPath(newRes.getGuid());
\r
2277 QFile tfile = new QFile(fileName);
\r
2278 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
2279 tfile.write(newRes.getData().getBody());
\r
2281 buffer.append(script_start_image);
\r
2282 buffer.append("<img src=\"" + FileUtils.toForwardSlashedPath(fileName));
\r
2283 // if (mimeType.equalsIgnoreCase("image/jpg"))
\r
2284 // mimeType = "image/jpeg";
\r
2285 buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""
\r
2286 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
2287 +" guid=\"" +newRes.getGuid() +"\""
\r
2288 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
2290 buffer.append(script_end);
\r
2291 browser.page().mainFrame().evaluateJavaScript(buffer.toString());
\r
2297 // If a URL being pasted is a local file URL, then attach the file
\r
2298 private void handleLocalAttachment(QMimeData mime, String mimeType) {
\r
2299 logger.log(logger.EXTREME, "Attaching local file");
\r
2300 List<QUrl> urlList = mime.urls();
\r
2301 String script_start = new String(
\r
2302 "document.execCommand('insertHtml', false, '");
\r
2303 String script_end = new String("');");
\r
2304 StringBuffer buffer;
\r
2306 String[] type = mimeType.split("/");
\r
2307 String icon = findIcon(type[1]);
\r
2308 if (icon.equals("attachment.png"))
\r
2309 icon = findIcon(type[0]);
\r
2310 buffer = new StringBuffer(100);
\r
2312 for (int i = 0; i < urlList.size(); i++) {
\r
2313 String url = urlList.get(i).toString();
\r
2315 // Start building the HTML
\r
2316 if (icon.equals("attachment.png"))
\r
2317 icon = findIcon(url.substring(url.lastIndexOf(".")+1));
\r
2318 String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));
\r
2320 logger.log(logger.EXTREME, "Creating resource ");
\r
2321 Resource newRes = createResource(url, i, mimeType, true);
\r
2322 if (newRes == null)
\r
2324 logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());
\r
2325 currentNote.getResources().add(newRes);
\r
2327 String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();
\r
2328 // If we have a PDF, we need to setup the preview.
\r
2329 if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {
\r
2330 logger.log(logger.EXTREME, "Setting up PDF preview");
\r
2331 if (newRes.getAttributes() != null &&
\r
2332 newRes.getAttributes().getFileName() != null &&
\r
2333 !newRes.getAttributes().getFileName().trim().equals(""))
\r
2334 fileName = newRes.getGuid()+Global.attachmentNameDelimeter+
\r
2335 newRes.getAttributes().getFileName();
\r
2337 fileName = newRes.getGuid()+".pdf";
\r
2338 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
2339 QFile.OpenMode mode = new QFile.OpenMode();
\r
2340 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2342 QDataStream out = new QDataStream(file);
\r
2343 // Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);
\r
2344 QByteArray binData = new QByteArray(newRes.getData().getBody());
\r
2345 // resBinary = null;
\r
2346 out.writeBytes(binData.toByteArray());
\r
2349 PDFPreview pdfPreview = new PDFPreview();
\r
2350 if (pdfPreview.setupPreview(Global.getFileManager().getResDirPath(fileName), "pdf",0)) {
\r
2351 imageURL = file.fileName() + ".png";
\r
2355 logger.log(logger.EXTREME, "Generating link tags");
\r
2356 buffer.delete(0, buffer.length());
\r
2357 buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");
\r
2358 buffer.append(" onContextMenu=\"window.jambi.imageContextMenu('")
\r
2359 .append(Global.getFileManager().getResDirPath(fileName))
\r
2360 .append("');\" "); buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");
\r
2361 buffer.append("<img src=\"" + imageURL + "\" title=\"" +newRes.getAttributes().getFileName());
\r
2362 buffer.append("\"></img>");
\r
2363 buffer.append("</a>");
\r
2364 browser.page().mainFrame().evaluateJavaScript(
\r
2365 script_start + buffer.toString() + script_end);
\r
2370 private Resource createResource(String url, int sequence, String mime, boolean attachment) {
\r
2371 logger.log(logger.EXTREME, "Inside create resource");
\r
2372 QFile resourceFile;
\r
2373 String urlTest = new QUrl(url).toLocalFile();
\r
2374 if (!urlTest.equals(""))
\r
2376 url = url.replace("/", File.separator);
\r
2377 logger.log(logger.EXTREME, "Reading from file to create resource");
\r
2378 resourceFile = new QFile(url);
\r
2379 resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));
\r
2380 // logger.log(logger.EXTREME, "Error opening file "+url.toString() +": "+resourceFile.errorString());
\r
2381 byte[] fileData = resourceFile.readAll().toByteArray();
\r
2382 resourceFile.close();
\r
2383 if (fileData.length == 0)
\r
2387 logger.log(logger.EXTREME, "Generating MD5");
\r
2388 md = MessageDigest.getInstance("MD5");
\r
2389 md.update(fileData);
\r
2390 byte[] hash = md.digest();
\r
2392 Resource r = new Resource();
\r
2393 Calendar time = new GregorianCalendar();
\r
2394 long prevTime = time.getTimeInMillis();
\r
2395 while (prevTime == time.getTimeInMillis()) {
\r
2396 time = new GregorianCalendar();
\r
2398 r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());
\r
2399 r.setNoteGuid(currentNote.getGuid());
\r
2401 r.setActive(true);
\r
2402 r.setUpdateSequenceNum(0);
\r
2403 r.setWidth((short) 0);
\r
2404 r.setHeight((short) 0);
\r
2405 r.setDuration((short) 0);
\r
2407 Data d = new Data();
\r
2408 d.setBody(fileData);
\r
2409 d.setBodyIsSet(true);
\r
2410 d.setBodyHash(hash);
\r
2411 d.setBodyHashIsSet(true);
\r
2413 d.setSize(fileData.length);
\r
2415 int fileNamePos = url.lastIndexOf(File.separator);
\r
2416 if (fileNamePos == -1)
\r
2417 fileNamePos = url.lastIndexOf("/");
\r
2418 String fileName = url.substring(fileNamePos+1);
\r
2419 ResourceAttributes a = new ResourceAttributes();
\r
2421 a.setAltitudeIsSet(false);
\r
2422 a.setLongitude(0);
\r
2423 a.setLongitudeIsSet(false);
\r
2425 a.setLatitudeIsSet(false);
\r
2426 a.setCameraMake("");
\r
2427 a.setCameraMakeIsSet(false);
\r
2428 a.setCameraModel("");
\r
2429 a.setCameraModelIsSet(false);
\r
2430 a.setAttachment(attachment);
\r
2431 a.setAttachmentIsSet(true);
\r
2432 a.setClientWillIndex(false);
\r
2433 a.setClientWillIndexIsSet(true);
\r
2434 a.setRecoType("");
\r
2435 a.setRecoTypeIsSet(false);
\r
2436 a.setSourceURL(url);
\r
2437 a.setSourceURLIsSet(true);
\r
2438 a.setTimestamp(0);
\r
2439 a.setTimestampIsSet(false);
\r
2440 a.setFileName(fileName);
\r
2441 a.setFileNameIsSet(true);
\r
2442 r.setAttributes(a);
\r
2444 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
2445 logger.log(logger.EXTREME, "Resource created");
\r
2447 } catch (NoSuchAlgorithmException e1) {
\r
2448 e1.printStackTrace();
\r
2454 // find the appropriate icon for an attachment
\r
2455 private String findIcon(String appl) {
\r
2456 appl = appl.toLowerCase();
\r
2457 File f = Global.getFileManager().getImageDirFile(appl + ".png");
\r
2459 return appl+".png";
\r
2460 return "attachment.png";
\r
2463 // Check if the account supports this type of attachment
\r
2464 private boolean validAttachment(String type) {
\r
2465 if (Global.isPremium())
\r
2467 if (type.equalsIgnoreCase("JPG"))
\r
2469 if (type.equalsIgnoreCase("PNG"))
\r
2471 if (type.equalsIgnoreCase("GIF"))
\r
2473 if (type.equalsIgnoreCase("MP3"))
\r
2475 if (type.equalsIgnoreCase("WAV"))
\r
2477 if (type.equalsIgnoreCase("AMR"))
\r
2479 if (type.equalsIgnoreCase("PDF"))
\r
2481 String error = tr("Non-premium accounts can only attach JPG, PNG, GIF, MP3, WAV, AMR, or PDF files.");
\r
2482 QMessageBox.information(this, tr("Non-Premium Account"), error);
\r
2487 // Check the file attachment to be sure it isn't over 25 mb
\r
2488 private boolean checkFileAttachmentSize(String url) {
\r
2489 String fileName = url.substring(8);
\r
2490 QFile resourceFile = new QFile(fileName);
\r
2491 resourceFile.open(new QIODevice.OpenMode(
\r
2492 QIODevice.OpenModeFlag.ReadOnly));
\r
2493 long size = resourceFile.size();
\r
2494 resourceFile.close();
\r
2495 size = size / 1024 / 1024;
\r
2496 if (size < 50 && Global.isPremium())
\r
2501 String error = tr("A file attachment may not exceed 25MB.");
\r
2502 QMessageBox.information(this, tr("Attachment Size"), error);
\r
2507 @SuppressWarnings("unused")
\r
2508 private void createdChanged() {
\r
2509 QDateTime dt = new QDateTime();
\r
2510 dt.setDate(createdDate.date());
\r
2511 dt.setTime(createdTime.time());
\r
2512 noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);
\r
2516 @SuppressWarnings("unused")
\r
2517 private void alteredChanged() {
\r
2518 QDateTime dt = new QDateTime();
\r
2519 dt.setDate(alteredDate.date());
\r
2520 dt.setTime(alteredTime.time());
\r
2521 noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);
\r
2524 @SuppressWarnings("unused")
\r
2525 private void subjectDateTimeChanged() {
\r
2526 QDateTime dt = new QDateTime();
\r
2527 dt.setDate(subjectDate.date());
\r
2528 dt.setTime(subjectTime.time());
\r
2529 noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);
\r
2533 @SuppressWarnings("unused")
\r
2534 private void sourceUrlChanged() {
\r
2535 noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());
\r
2538 @SuppressWarnings("unused")
\r
2539 private void authorChanged() {
\r
2540 noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());
\r
2543 @SuppressWarnings("unused")
\r
2544 private void geoBoxChanged() {
\r
2545 int index = geoBox.currentIndex();
\r
2546 geoBox.setCurrentIndex(0);
\r
2548 GeoDialog box = new GeoDialog();
\r
2549 box.setLongitude(currentNote.getAttributes().getLongitude());
\r
2550 box.setLatitude(currentNote.getAttributes().getLatitude());
\r
2551 box.setAltitude(currentNote.getAttributes().getAltitude());
\r
2553 if (!box.okPressed())
\r
2555 double alt = box.getAltitude();
\r
2556 double lat = box.getLatitude();
\r
2557 double lon = box.getLongitude();
\r
2558 if (alt != currentNote.getAttributes().getAltitude() ||
\r
2559 lon != currentNote.getAttributes().getLongitude() ||
\r
2560 lat != currentNote.getAttributes().getLatitude()) {
\r
2561 noteSignal.geoChanged.emit(currentNote.getGuid(), lon, lat, alt);
\r
2562 currentNote.getAttributes().setAltitude(alt);
\r
2563 currentNote.getAttributes().setLongitude(lon);
\r
2564 currentNote.getAttributes().setLatitude(lat);
\r
2569 noteSignal.geoChanged.emit(currentNote.getGuid(), 0.0, 0.0, 0.0);
\r
2570 currentNote.getAttributes().setAltitude(0.0);
\r
2571 currentNote.getAttributes().setLongitude(0.0);
\r
2572 currentNote.getAttributes().setLatitude(0.0);
\r
2575 if (index == 3 || index == 0) {
\r
2576 QDesktopServices.openUrl(new QUrl("http://maps.google.com/maps?z=6&q="+currentNote.getAttributes().getLatitude() +"," +currentNote.getAttributes().getLongitude()));
\r
2580 // ************************************************************
\r
2581 // * User chose to save an attachment. Pares out the request *
\r
2582 // * into a guid & file. Save the result. *
\r
2583 // ************************************************************
\r
2584 public void downloadAttachment(QNetworkRequest request) {
\r
2586 QFileDialog fd = new QFileDialog(this);
\r
2587 fd.setFileMode(FileMode.AnyFile);
\r
2588 fd.setConfirmOverwrite(true);
\r
2589 fd.setWindowTitle(tr("Save File"));
\r
2590 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2591 fd.setDirectory(System.getProperty("user.home"));
\r
2592 String name = request.url().toString();
\r
2594 int pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2596 guid = name.substring(0, pos).replace("nnres://", "");
\r
2597 name = name.substring(pos +Global.attachmentNameDelimeter.length());
\r
2598 fd.selectFile(name);
\r
2599 pos = name.lastIndexOf('.');
\r
2601 String mimeType = "(*." + name.substring(pos + 1)
\r
2602 + ");; All Files (*)";
\r
2603 fd.setFilter(tr(mimeType));
\r
2609 // Strip URL prefix and base dir
\r
2610 guid = guid.replace("nnres://", "")
\r
2611 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2612 guid = guid.replace("file://", "").replace("/", "")
\r
2613 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2615 pos = guid.lastIndexOf('.');
\r
2617 guid = guid.substring(0,pos);
\r
2618 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2619 name = name.replace('\\', '/');
\r
2620 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2621 QFile saveFile = new QFile(fd.selectedFiles().get(0));
\r
2622 QFile.OpenMode mode = new QFile.OpenMode();
\r
2623 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2624 saveFile.open(mode);
\r
2625 QDataStream saveOut = new QDataStream(saveFile);
\r
2626 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2627 saveOut.writeBytes(binData.toByteArray());
\r
2634 // ************************************************************
\r
2635 // * User chose to save an attachment. Pares out the request *
\r
2636 // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!
\r
2637 // ************************************************************
\r
2638 public void downloadImage(QNetworkRequest request) {
\r
2639 QFileDialog fd = new QFileDialog(this);
\r
2640 fd.setFileMode(FileMode.AnyFile);
\r
2641 fd.setConfirmOverwrite(true);
\r
2642 fd.setWindowTitle(tr("Save File"));
\r
2643 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2644 fd.setDirectory(System.getProperty("user.home"));
\r
2645 String name = request.url().toString();
\r
2646 name = name.replace("nnres://", "");
\r
2647 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
\r
2648 name = name.replace(dPath, "");
\r
2649 int pos = name.lastIndexOf('.');
\r
2650 String guid = name;
\r
2652 String mimeType = "(*." + name.substring(pos + 1)
\r
2653 + ");; All Files (*)";
\r
2654 fd.setFilter(tr(mimeType));
\r
2655 guid = guid.substring(0,pos);
\r
2657 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2659 guid = name.substring(0, pos);
\r
2660 fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));
\r
2662 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2663 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2664 String fileName = fd.selectedFiles().get(0);
\r
2665 QFile saveFile = new QFile(fileName);
\r
2666 QFile.OpenMode mode = new QFile.OpenMode();
\r
2667 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2668 saveFile.open(mode);
\r
2669 QDataStream saveOut = new QDataStream(saveFile);
\r
2670 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2671 saveOut.writeBytes(binData.toByteArray());
\r
2677 // *************************************************************
\r
2678 // * decrypt any hidden text. We could do an XML parse, but
\r
2679 // * it is quicker here just to scan for an <img tag & do the fix
\r
2680 // * the manual way
\r
2681 // *************************************************************
\r
2682 private void removeEncryption(String id, String plainText, boolean permanent, String slot) {
\r
2684 plainText = " <table class=\"en-crypt-temp\" slot=\""
\r
2687 +"border=1 width=100%><tbody><tr><td>"
\r
2688 +plainText+"</td></tr></tbody></table>";
\r
2691 String html = browser.page().mainFrame().toHtml();
\r
2692 String text = html;
\r
2693 int imagePos = html.indexOf("<img");
\r
2695 for ( ;imagePos>0; ) {
\r
2696 // Find the end tag
\r
2697 endPos = text.indexOf(">", imagePos);
\r
2698 String tag = text.substring(imagePos-1,endPos);
\r
2699 if (tag.indexOf("id=\""+id+"\"") > -1) {
\r
2700 text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);
\r
2701 QTextCodec codec = QTextCodec.codecForName("UTF-8");
\r
2702 QByteArray unicode = codec.fromUnicode(text);
\r
2703 setContent(unicode);
\r
2707 imagePos = text.indexOf("<img", imagePos+1);
\r
2712 //****************************************************************
\r
2713 //* Focus shortcuts
\r
2714 //****************************************************************
\r
2715 @SuppressWarnings("unused")
\r
2716 private void focusTitle() {
\r
2717 titleLabel.setFocus();
\r
2719 @SuppressWarnings("unused")
\r
2720 private void focusTag() {
\r
2721 tagEdit.setFocus();
\r
2723 @SuppressWarnings("unused")
\r
2724 private void focusNote() {
\r
2725 browser.setFocus();
\r
2727 @SuppressWarnings("unused")
\r
2728 private void focusAuthor() {
\r
2729 authorLabel.setFocus();
\r
2731 @SuppressWarnings("unused")
\r
2732 private void focusUrl() {
\r
2733 urlLabel.setFocus();
\r
2737 //*****************************************************************
\r
2738 //* Set the document background color
\r
2739 //*****************************************************************
\r
2740 public void setBackgroundColor(String color) {
\r
2741 String js = "function changeBackground(color) {"
\r
2742 +"document.body.style.background = color;"
\r
2744 +"changeBackground('" +color+"');";
\r
2745 browser.page().mainFrame().evaluateJavaScript(js);
\r
2750 //****************************************************************
\r
2751 //* MicroFocus changed
\r
2752 //****************************************************************
\r
2753 private void microFocusChanged() {
\r
2754 boldButton.setDown(false);
\r
2755 italicButton.setDown(false);
\r
2756 underlineButton.setDown(false);
\r
2757 browser.openAction.setEnabled(false);
\r
2758 browser.downloadAttachment.setEnabled(false);
\r
2759 browser.downloadImage.setEnabled(false);
\r
2760 browser.rotateImageLeft.setEnabled(false);
\r
2761 browser.rotateImageRight.setEnabled(false);
\r
2762 browser.insertTableAction.setEnabled(true);
\r
2763 browser.deleteTableColumnAction.setEnabled(false);
\r
2764 browser.insertTableRowAction.setEnabled(false);
\r
2765 browser.insertTableColumnAction.setEnabled(false);
\r
2766 browser.deleteTableRowAction.setEnabled(false);
\r
2767 browser.insertLinkAction.setText(tr("Insert Hyperlink"));
\r
2768 insertHyperlink = true;
\r
2769 currentHyperlink ="";
\r
2770 insideList = false;
\r
2771 insideTable = false;
\r
2772 insideEncryption = false;
\r
2773 forceTextPaste = false;
\r
2775 String js = new String( "function getCursorPos() {"
\r
2777 +"if (window.getSelection) {"
\r
2778 +" var selObj = window.getSelection();"
\r
2779 +" var selRange = selObj.getRangeAt(0);"
\r
2780 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2781 +" while(workingNode != null) { "
\r
2782 // +" window.jambi.printNode(workingNode.nodeName);"
\r
2783 +" if (workingNode.nodeName=='TABLE') { if (workingNode.getAttribute('class').toLowerCase() == 'en-crypt-temp') window.jambi.insideEncryption(); }"
\r
2784 +" if (workingNode.nodeName=='B') window.jambi.boldActive();"
\r
2785 +" if (workingNode.nodeName=='I') window.jambi.italicActive();"
\r
2786 +" if (workingNode.nodeName=='U') window.jambi.underlineActive();"
\r
2787 +" if (workingNode.nodeName=='UL') window.jambi.setInsideList();"
\r
2788 +" if (workingNode.nodeName=='OL') window.jambi.setInsideList();"
\r
2789 +" if (workingNode.nodeName=='LI') window.jambi.setInsideList();"
\r
2790 +" if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"
\r
2791 +" 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
2792 +" if (workingNode.nodeName=='SPAN') {"
\r
2793 +" if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"
\r
2795 +" workingNode = workingNode.parentNode;"
\r
2798 +"} getCursorPos();");
\r
2799 browser.page().mainFrame().evaluateJavaScript(js);
\r
2802 public void printNode(String n) {
\r
2803 System.out.println("Node Vaule: " +n);
\r
2806 public void insideEncryption() {
\r
2807 insideEncryption = true;
\r
2811 //****************************************************************
\r
2812 //* Insert a table row
\r
2813 //****************************************************************
\r
2814 public void insertTableRow() {
\r
2816 String js = new String( "function insertTableRow() {"
\r
2817 +" var selObj = window.getSelection();"
\r
2818 +" var selRange = selObj.getRangeAt(0);"
\r
2819 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2820 +" var cellCount = 0;"
\r
2821 +" while(workingNode != null) { "
\r
2822 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2823 +" row = document.createElement('TR');"
\r
2824 +" var nodes = workingNode.getElementsByTagName('td');"
\r
2825 +" for (j=0; j<nodes.length; j=j+1) {"
\r
2826 +" cell = document.createElement('TD');"
\r
2827 +" cell.innerHTML=' ';"
\r
2828 +" row.appendChild(cell);"
\r
2830 +" workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"
\r
2833 +" workingNode = workingNode.parentNode;"
\r
2835 +"} insertTableRow();");
\r
2836 browser.page().mainFrame().evaluateJavaScript(js);
\r
2840 public void insertTableColumn() {
\r
2841 String js = new String( "function insertTableColumn() {"
\r
2842 +" var selObj = window.getSelection();"
\r
2843 +" var selRange = selObj.getRangeAt(0);"
\r
2844 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2845 +" var current = 0;"
\r
2846 +" while (workingNode.nodeName.toLowerCase() != 'table' && workingNode != null) {"
\r
2847 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
2848 +" var td = workingNode;"
\r
2849 +" while (td.previousSibling != null) { "
\r
2850 +" current = current+1; td = td.previousSibling;"
\r
2853 +" workingNode = workingNode.parentNode; "
\r
2855 +" if (workingNode == null) return;"
\r
2856 +" for (var i=0; i<workingNode.rows.length; i++) { "
\r
2857 +" var cell = workingNode.rows[i].insertCell(current+1); "
\r
2858 +" cell.innerHTML = ' '; "
\r
2860 +"} insertTableColumn();");
\r
2861 browser.page().mainFrame().evaluateJavaScript(js);
\r
2865 //****************************************************************
\r
2866 //* Delete a table row
\r
2867 //****************************************************************
\r
2868 public void deleteTableRow() {
\r
2870 String js = new String( "function deleteTableRow() {"
\r
2871 +" var selObj = window.getSelection();"
\r
2872 +" var selRange = selObj.getRangeAt(0);"
\r
2873 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2874 +" var cellCount = 0;"
\r
2875 +" while(workingNode != null) { "
\r
2876 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2877 +" workingNode.parentNode.removeChild(workingNode);"
\r
2880 +" workingNode = workingNode.parentNode;"
\r
2882 +"} deleteTableRow();");
\r
2883 browser.page().mainFrame().evaluateJavaScript(js);
\r
2887 public void deleteTableColumn() {
\r
2888 String js = new String( "function deleteTableColumn() {"
\r
2889 +" var selObj = window.getSelection();"
\r
2890 +" var selRange = selObj.getRangeAt(0);"
\r
2891 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2892 +" var current = 0;"
\r
2893 +" while (workingNode.nodeName.toLowerCase() != 'table' && workingNode != null) {"
\r
2894 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
2895 +" var td = workingNode;"
\r
2896 +" while (td.previousSibling != null) { "
\r
2897 +" current = current+1; td = td.previousSibling;"
\r
2900 +" workingNode = workingNode.parentNode; "
\r
2902 +" if (workingNode == null) return;"
\r
2903 +" for (var i=0; i<workingNode.rows.length; i++) { "
\r
2904 +" workingNode.rows[i].deleteCell(current); "
\r
2906 +"} deleteTableColumn();");
\r
2907 browser.page().mainFrame().evaluateJavaScript(js);
\r
2912 public void setInsideTable() {
\r
2913 browser.insertTableRowAction.setEnabled(true);
\r
2914 browser.insertTableColumnAction.setEnabled(true);
\r
2915 browser.deleteTableRowAction.setEnabled(true);
\r
2916 browser.deleteTableColumnAction.setEnabled(true);
\r
2917 browser.insertTableAction.setEnabled(false);
\r
2918 browser.encryptAction.setEnabled(false);
\r
2919 insideTable = true;
\r
2922 public void setInsideLink(String link) {
\r
2923 browser.insertLinkAction.setText(tr("Edit Hyperlink"));
\r
2924 currentHyperlink = link;
\r
2925 insertHyperlink = false;
\r
2928 public void italicActive() {
\r
2929 italicButton.setDown(true);
\r
2931 public void boldActive() {
\r
2932 boldButton.setDown(true);
\r
2934 public void underlineActive() {
\r
2935 underlineButton.setDown(true);
\r
2937 public void forceTextPaste() {
\r
2938 forceTextPaste = true;
\r
2940 public void imageContextMenu(String f) {
\r
2941 browser.downloadImage.setEnabled(true);
\r
2942 browser.rotateImageRight.setEnabled(true);
\r
2943 browser.rotateImageLeft.setEnabled(true);
\r
2944 browser.openAction.setEnabled(true);
\r
2947 public void rotateImageRight() {
\r
2948 QWebSettings.setMaximumPagesInCache(0);
\r
2949 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2950 QImage image = new QImage(selectedFile);
\r
2951 QMatrix matrix = new QMatrix();
\r
2952 matrix.rotate( 90.0 );
\r
2953 image = image.transformed(matrix);
\r
2954 image.save(selectedFile);
\r
2955 QWebSettings.setMaximumPagesInCache(0);
\r
2956 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2957 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2960 resourceSignal.contentChanged.emit(selectedFile);
\r
2963 public void rotateImageLeft() {
\r
2964 QImage image = new QImage(selectedFile);
\r
2965 QMatrix matrix = new QMatrix();
\r
2966 matrix.rotate( -90.0 );
\r
2967 image = image.transformed(matrix);
\r
2968 image.save(selectedFile);
\r
2969 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2972 resourceSignal.contentChanged.emit(selectedFile);
\r
2974 public void resourceContextMenu(String f) {
\r
2975 browser.downloadAttachment.setEnabled(true);
\r
2976 browser.openAction.setEnabled(true);
\r
2979 public void latexContextMenu(String f) {
\r
2980 browser.downloadImage.setEnabled(true);
\r
2981 browser.rotateImageRight.setEnabled(true);
\r
2982 browser.rotateImageLeft.setEnabled(true);
\r
2983 browser.openAction.setEnabled(true);
\r
2987 //****************************************************************
\r
2988 //* Apply CSS style to specified word
\r
2989 //****************************************************************
\r
2990 /* public void applyStyleToWords(String word, String style) {
\r
2991 QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");
\r
2992 script.open(OpenModeFlag.ReadOnly);
\r
2993 String s = script.readAll().toString();
\r
2994 String js = new String(s +" findit('"+word+"', '"+style+"');");
\r
2995 browser.page().mainFrame().evaluateJavaScript(js);
\r
2996 System.out.println(getContent());
\r
2999 //****************************************************************
\r
3000 //* Someone tried to paste a resource between notes, so we need *
\r
3001 //* to do some special handling. *
\r
3002 //****************************************************************
\r
3003 private String fixInternotePaste(String text) {
\r
3004 logger.log(logger.EXTREME, "Fixing internote paste");
\r
3005 String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");
\r
3006 return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");
\r
3008 private String fixInternotePasteSearch(String text, String type, String locTag) {
\r
3010 // First, let's fix the images.
\r
3011 int startPos = text.indexOf(type);
\r
3013 for (; startPos>=0;) {
\r
3014 endPos = text.indexOf(">", startPos+1);
\r
3015 String segment = text.substring(startPos, endPos);
\r
3016 if (segment.indexOf("en-tag") > -1) {
\r
3017 String newSegment = segment;
\r
3019 int guidStartPos = segment.indexOf("guid=\"");
\r
3020 int guidEndPos = segment.indexOf("\"", guidStartPos+7);
\r
3021 String guid = segment.substring(guidStartPos+6,guidEndPos);
\r
3023 int mimeStartPos = segment.indexOf("type");
\r
3024 int mimeEndPos = segment.indexOf("\"", mimeStartPos+7);
\r
3025 String mime = segment.substring(mimeStartPos+6,mimeEndPos);
\r
3027 int srcStartPos = segment.indexOf("src");
\r
3028 int srcEndPos = segment.indexOf("\"", srcStartPos+6);
\r
3029 String src = segment.substring(srcStartPos+5,srcEndPos);
\r
3031 Calendar currentTime = new GregorianCalendar();
\r
3032 Long l = new Long(currentTime.getTimeInMillis());
\r
3033 long prevTime = l;
\r
3034 while (l==prevTime) {
\r
3035 currentTime = new GregorianCalendar();
\r
3036 l= new Long(currentTime.getTimeInMillis());
\r
3039 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
3040 // if r==null, then the image doesn't exist (it was probably cut out of another note, so
\r
3041 // we need to recereate it
\r
3043 r = createResource(src, 1, mime, false);
\r
3047 String randint = new String(Long.toString(l));
\r
3048 String extension = null;
\r
3049 if (r.getMime()!= null) {
\r
3050 extension = r.getMime().toLowerCase();
\r
3051 if (extension.indexOf("/")>-1)
\r
3052 extension = extension.substring(extension.indexOf("/")+1);
\r
3054 String newFile = randint;
\r
3055 if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")
\r
3056 if (!locTag.startsWith("src"))
\r
3057 newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();
\r
3058 r.setNoteGuid(currentNote.getGuid());
\r
3060 r.setGuid(randint);
\r
3061 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
3062 QFile f = new QFile(Global.getFileManager().getResDirPath(newFile));
\r
3063 QByteArray bin = new QByteArray(r.getData().getBody());
\r
3064 f.open(QFile.OpenModeFlag.WriteOnly);
\r
3067 newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);
\r
3068 currentNote.getResources().add(r);
\r
3070 int startSrcPos = newSegment.indexOf(locTag);
\r
3071 int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);
\r
3073 if (locTag.startsWith("src")) {
\r
3074 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
3075 newSegment = newSegment.replace(source,
\r
3076 FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath(newFile)));
\r
3078 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
3079 newSegment = newSegment.replace(source, newFile);
\r
3082 text = text.substring(0,startPos) + newSegment + text.substring(endPos);
\r
3084 startPos = text.indexOf(type, startPos+1);
\r
3090 public void nextPage(String file) {
\r
3091 logger.log(logger.EXTREME, "Starting nextPage()");
\r
3093 Integer pageNumber;
\r
3094 if (previewPageList.containsKey(file))
\r
3095 pageNumber = previewPageList.get(file)+1;
\r
3098 previewPageList.remove(file);
\r
3099 previewPageList.put(file, pageNumber);
\r
3100 PDFPreview pdfPreview = new PDFPreview();
\r
3101 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
3102 if (goodPreview) {
\r
3104 // String html = getContent();
\r
3105 QWebSettings.setMaximumPagesInCache(0);
\r
3106 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
3107 // browser.setContent(new QByteArray());
\r
3108 browser.setHtml(browser.page().mainFrame().toHtml());
\r
3110 // browser.setContent(new QByteArray(html));
\r
3111 // browser.triggerPageAction(WebAction.Reload);
\r
3112 // pdfMouseOver(selectedFile);
\r
3116 public void previousPage(String file) {
\r
3117 logger.log(logger.EXTREME, "Starting previousPage()");
\r
3119 Integer pageNumber;
\r
3120 if (previewPageList.containsKey(file))
\r
3121 pageNumber = previewPageList.get(file)-1;
\r
3124 previewPageList.remove(file);
\r
3125 previewPageList.put(file, pageNumber);
\r
3126 PDFPreview pdfPreview = new PDFPreview();
\r
3127 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
3128 if (goodPreview) {
\r
3130 // String html = getContent();
\r
3131 QWebSettings.setMaximumPagesInCache(0);
\r
3132 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
3133 browser.setHtml(browser.page().mainFrame().toHtml());
\r
3135 // browser.setContent(new QByteArray(html));
\r
3136 // browser.triggerPageAction(WebAction.Reload);
\r
3140 /* public void pdfMouseOver(String name) {
\r
3142 if (previewPageList.containsKey(selectedFile))
\r
3143 pageNumber = previewPageList.get(selectedFile)+1;
\r
3147 if (pageNumber <= 1)
\r
3148 browser.previousPageAction.setEnabled(false);
\r
3150 browser.previousPageAction.setEnabled(true);
\r
3152 PDFPreview pdf = new PDFPreview();
\r
3153 int totalPages = pdf.getPageCount(name);
\r
3154 if (previewPageList.containsKey(selectedFile))
\r
3155 pageNumber = previewPageList.get(selectedFile)+1;
\r
3158 if (totalPages > pageNumber)
\r
3159 browser.nextPageAction.setEnabled(true);
\r
3161 browser.nextPageAction.setEnabled(false);
\r
3165 public void pdfMouseOut() {
\r
3166 // browser.nextPageAction.setVisible(false);
\r
3167 // browser.previousPageAction.setVisible(false);
\r
3171 @SuppressWarnings("unused")
\r
3172 private void toggleUndoVisible(Boolean toggle) {
\r
3173 undoAction.setVisible(toggle);
\r
3174 Global.saveEditorButtonsVisible("undo", toggle);
\r
3176 @SuppressWarnings("unused")
\r
3177 private void toggleRedoVisible(Boolean toggle) {
\r
3178 redoAction.setVisible(toggle);
\r
3179 Global.saveEditorButtonsVisible("redo", toggle);
\r
3181 @SuppressWarnings("unused")
\r
3182 private void toggleCutVisible(Boolean toggle) {
\r
3183 cutAction.setVisible(toggle);
\r
3184 Global.saveEditorButtonsVisible("cut", toggle);
\r
3186 @SuppressWarnings("unused")
\r
3187 private void toggleCopyVisible(Boolean toggle) {
\r
3188 copyAction.setVisible(toggle);
\r
3189 Global.saveEditorButtonsVisible("copy", toggle);
\r
3191 @SuppressWarnings("unused")
\r
3192 private void togglePasteVisible(Boolean toggle) {
\r
3193 pasteAction.setVisible(toggle);
\r
3194 Global.saveEditorButtonsVisible("paste", toggle);
\r
3196 @SuppressWarnings("unused")
\r
3197 private void toggleBoldVisible(Boolean toggle) {
\r
3198 boldAction.setVisible(toggle);
\r
3199 Global.saveEditorButtonsVisible("bold", toggle);
\r
3201 @SuppressWarnings("unused")
\r
3202 private void toggleItalicVisible(Boolean toggle) {
\r
3203 italicAction.setVisible(toggle);
\r
3204 Global.saveEditorButtonsVisible("italic", toggle);
\r
3206 @SuppressWarnings("unused")
\r
3207 private void toggleUnderlineVisible(Boolean toggle) {
\r
3208 underlineAction.setVisible(toggle);
\r
3209 Global.saveEditorButtonsVisible("underline", toggle);
\r
3211 @SuppressWarnings("unused")
\r
3212 private void toggleStrikethroughVisible(Boolean toggle) {
\r
3213 strikethroughAction.setVisible(toggle);
\r
3214 Global.saveEditorButtonsVisible("strikethrough", toggle);
\r
3216 @SuppressWarnings("unused")
\r
3217 private void toggleLeftAlignVisible(Boolean toggle) {
\r
3218 leftAlignAction.setVisible(toggle);
\r
3219 Global.saveEditorButtonsVisible("alignLeft", toggle);
\r
3221 @SuppressWarnings("unused")
\r
3222 private void toggleRightAlignVisible(Boolean toggle) {
\r
3223 rightAlignAction.setVisible(toggle);
\r
3224 Global.saveEditorButtonsVisible("alignRight", toggle);
\r
3226 @SuppressWarnings("unused")
\r
3227 private void toggleCenterAlignVisible(Boolean toggle) {
\r
3228 centerAlignAction.setVisible(toggle);
\r
3229 Global.saveEditorButtonsVisible("alignCenter", toggle);
\r
3231 @SuppressWarnings("unused")
\r
3232 private void toggleHLineVisible(Boolean toggle) {
\r
3233 hlineAction.setVisible(toggle);
\r
3234 Global.saveEditorButtonsVisible("hline", toggle);
\r
3236 @SuppressWarnings("unused")
\r
3237 private void toggleIndentVisible(Boolean toggle) {
\r
3238 indentAction.setVisible(toggle);
\r
3239 Global.saveEditorButtonsVisible("indent", toggle);
\r
3241 @SuppressWarnings("unused")
\r
3242 private void toggleTodoVisible(Boolean toggle) {
\r
3243 todoAction.setVisible(toggle);
\r
3244 Global.saveEditorButtonsVisible("todo", toggle);
\r
3246 @SuppressWarnings("unused")
\r
3247 private void toggleOutdentVisible(Boolean toggle) {
\r
3248 outdentAction.setVisible(toggle);
\r
3249 Global.saveEditorButtonsVisible("outdent", toggle);
\r
3251 @SuppressWarnings("unused")
\r
3252 private void toggleBulletListVisible(Boolean toggle) {
\r
3253 bulletListAction.setVisible(toggle);
\r
3254 Global.saveEditorButtonsVisible("bulletList", toggle);
\r
3256 @SuppressWarnings("unused")
\r
3257 private void toggleNumberListVisible(Boolean toggle) {
\r
3258 numberListAction.setVisible(toggle);
\r
3259 Global.saveEditorButtonsVisible("numberList", toggle);
\r
3261 @SuppressWarnings("unused")
\r
3262 private void toggleFontListVisible(Boolean toggle) {
\r
3263 fontListAction.setVisible(toggle);
\r
3264 Global.saveEditorButtonsVisible("font", toggle);
\r
3266 @SuppressWarnings("unused")
\r
3267 private void toggleFontColorVisible(Boolean toggle) {
\r
3268 fontColorAction.setVisible(toggle);
\r
3269 Global.saveEditorButtonsVisible("fontColor", toggle);
\r
3271 @SuppressWarnings("unused")
\r
3272 private void toggleFontSizeVisible(Boolean toggle) {
\r
3273 fontSizeAction.setVisible(toggle);
\r
3274 Global.saveEditorButtonsVisible("fontSize", toggle);
\r
3276 @SuppressWarnings("unused")
\r
3277 private void toggleFontHilightVisible(Boolean toggle) {
\r
3278 fontHilightAction.setVisible(toggle);
\r
3279 Global.saveEditorButtonsVisible("fontHilight", toggle);
\r
3281 @SuppressWarnings("unused")
\r
3282 private void toggleSpellCheckVisible(Boolean toggle) {
\r
3283 spellCheckAction.setVisible(toggle);
\r
3284 Global.saveEditorButtonsVisible("spellCheck", toggle);
\r
3288 private void setupDictionary() {
\r
3289 File wordList = new File(Global.getFileManager().getSpellDirPath()+Locale.getDefault()+".dic");
\r
3291 dictionary = new SpellDictionaryHashMap(wordList);
\r
3292 spellChecker = new SpellChecker(dictionary);
\r
3294 File userWordList;
\r
3295 userWordList = new File(Global.getFileManager().getSpellDirPathUser()+"user.dic");
\r
3297 // Get the local user spell dictionary
\r
3299 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
3300 } catch (FileNotFoundException e) {
\r
3301 userWordList.createNewFile();
\r
3302 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
3303 } catch (IOException e) {
\r
3304 userWordList.createNewFile();
\r
3305 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
3308 spellListener = new SuggestionListener(this, spellChecker);
\r
3310 // Add the user dictionary
\r
3311 spellChecker.addSpellCheckListener(spellListener);
\r
3312 spellChecker.setUserDictionary(userDictionary);
\r
3314 } catch (FileNotFoundException e) {
\r
3315 QMessageBox.critical(this, tr("Spell Check Error"),
\r
3316 tr("Dictionary ")+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
3317 tr(".dic was not found."));
\r
3318 } catch (IOException e) {
\r
3319 QMessageBox.critical(this, tr("Spell Check Error"),
\r
3320 tr("Dictionary ")+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
3321 tr(".dic is invalid."));
\r
3326 // Invoke spell checker dialog
\r
3327 @SuppressWarnings("unused")
\r
3328 private void spellCheckClicked() {
\r
3330 if (spellChecker == null) {
\r
3331 setupDictionary();
\r
3334 // Read user settings
\r
3335 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREDIGITWORDS,
\r
3336 Global.getSpellSetting(Configuration.SPELL_IGNOREDIGITWORDS));
\r
3337 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREINTERNETADDRESSES,
\r
3338 Global.getSpellSetting(Configuration.SPELL_IGNOREINTERNETADDRESSES));
\r
3339 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREMIXEDCASE,
\r
3340 Global.getSpellSetting(Configuration.SPELL_IGNOREMIXEDCASE));
\r
3341 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREUPPERCASE,
\r
3342 Global.getSpellSetting(Configuration.SPELL_IGNOREUPPERCASE));
\r
3343 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNORESENTENCECAPITALIZATION,
\r
3344 Global.getSpellSetting(Configuration.SPELL_IGNORESENTENCECAPITALIZATION));
\r
3346 spellListener.abortSpellCheck = false;
\r
3347 spellListener.errorsFound = false;
\r
3348 String content = getBrowser().page().mainFrame().toPlainText();
\r
3349 StringWordTokenizer tokenizer = new StringWordTokenizer(content);
\r
3350 if (!tokenizer.hasMoreWords())
\r
3352 getBrowser().page().action(WebAction.MoveToStartOfDocument);
\r
3354 getBrowser().setFocus();
\r
3357 // Move to the start of page
\r
3358 KeyboardModifiers ctrl = new KeyboardModifiers(KeyboardModifier.ControlModifier.value());
\r
3359 QKeyEvent home = new QKeyEvent(Type.KeyPress, Key.Key_Home.value(), ctrl);
\r
3360 browser.keyPressEvent(home);
\r
3361 getBrowser().setFocus();
\r
3363 tokenizer = new StringWordTokenizer(content);
\r
3366 while(tokenizer.hasMoreWords()) {
\r
3367 word = tokenizer.nextWord();
\r
3368 found = getBrowser().page().findText(word);
\r
3369 if (found && !spellListener.abortSpellCheck) {
\r
3370 spellChecker.checkSpelling(new StringWordTokenizer(word));
\r
3371 getBrowser().setFocus();
\r
3375 // Go to the end of the document & finish up.
\r
3376 home = new QKeyEvent(Type.KeyPress, Key.Key_End.value(), ctrl);
\r
3377 browser.keyPressEvent(home);
\r
3378 if (!spellListener.errorsFound)
\r
3379 QMessageBox.information(this, tr("Spell Check Complete"),
\r
3380 tr("No Errors Found"));
\r
3385 @SuppressWarnings("unused")
\r
3386 private void sourceEdited() {
\r
3387 QByteArray data = new QByteArray(sourceEditHeader+sourceEdit.toPlainText()+"</body></html>");
\r
3388 getBrowser().setContent(data);
\r
3391 noteSignal.noteChanged.emit(currentNote.getGuid(), sourceEdit.toPlainText());
\r
3394 private void setSource(String text) {
\r
3395 sourceEdit.blockSignals(true);
\r
3396 int body = text.indexOf("<body");
\r
3398 body = text.indexOf(">",body);
\r
3400 sourceEditHeader =text.substring(0, body+1);
\r
3401 text = text.substring(body+1);
\r
3404 text = text.replace("</body></html>", "");
\r
3405 sourceEdit.setPlainText(text);
\r
3406 sourceEdit.setReadOnly(!getBrowser().page().isContentEditable());
\r
3407 syntaxHighlighter.rehighlight();
\r
3408 sourceEdit.blockSignals(false);
\r
3411 // show/hide view source window
\r
3412 public void showSource(boolean value) {
\r
3413 sourceEdit.setVisible(value);
\r