2 * This file is part of NixNote
\r
3 * Copyright 2009 Randy Baumgarte
\r
5 * This file may be licensed under the terms of of the
\r
6 * GNU General Public License Version 2 (the ``GPL'').
\r
8 * Software distributed under the License is distributed
\r
9 * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
\r
10 * express or implied. See the GPL for the specific language
\r
11 * governing rights and limitations.
\r
13 * You should have received a copy of the GPL along with this
\r
14 * program. If not, go to http://www.gnu.org/licenses/gpl.html
\r
15 * or write to the Free Software Foundation, Inc.,
\r
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
\r
20 package cx.fbn.nevernote.gui;
\r
22 import java.io.File;
\r
23 import java.io.FileNotFoundException;
\r
24 import java.io.IOException;
\r
25 import java.net.FileNameMap;
\r
26 import java.net.URI;
\r
27 import java.net.URLConnection;
\r
28 import java.security.MessageDigest;
\r
29 import java.security.NoSuchAlgorithmException;
\r
30 import java.text.SimpleDateFormat;
\r
31 import java.util.ArrayList;
\r
32 import java.util.Calendar;
\r
33 import java.util.Collections;
\r
34 import java.util.Date;
\r
35 import java.util.GregorianCalendar;
\r
36 import java.util.HashMap;
\r
37 import java.util.List;
\r
38 import java.util.Locale;
\r
39 import java.util.StringTokenizer;
\r
41 import org.apache.commons.lang3.StringEscapeUtils;
\r
42 import org.apache.commons.lang3.StringUtils;
\r
44 import com.evernote.edam.limits.Constants;
\r
45 import com.evernote.edam.type.Data;
\r
46 import com.evernote.edam.type.Note;
\r
47 import com.evernote.edam.type.Notebook;
\r
48 import com.evernote.edam.type.Resource;
\r
49 import com.evernote.edam.type.ResourceAttributes;
\r
50 import com.evernote.edam.type.Tag;
\r
51 import com.evernote.edam.type.User;
\r
52 import com.swabunga.spell.engine.Configuration;
\r
53 import com.swabunga.spell.engine.SpellDictionary;
\r
54 import com.swabunga.spell.engine.SpellDictionaryHashMap;
\r
55 import com.swabunga.spell.engine.Word;
\r
56 import com.swabunga.spell.event.SpellCheckEvent;
\r
57 import com.swabunga.spell.event.SpellCheckListener;
\r
58 import com.swabunga.spell.event.SpellChecker;
\r
59 import com.swabunga.spell.event.StringWordTokenizer;
\r
60 import com.trolltech.qt.core.QByteArray;
\r
61 import com.trolltech.qt.core.QCoreApplication;
\r
62 import com.trolltech.qt.core.QDataStream;
\r
63 import com.trolltech.qt.core.QDateTime;
\r
64 import com.trolltech.qt.core.QEvent;
\r
65 import com.trolltech.qt.core.QEvent.Type;
\r
66 import com.trolltech.qt.core.QFile;
\r
67 import com.trolltech.qt.core.QFileSystemWatcher;
\r
68 import com.trolltech.qt.core.QIODevice;
\r
69 import com.trolltech.qt.core.QMimeData;
\r
70 import com.trolltech.qt.core.QTextCodec;
\r
71 import com.trolltech.qt.core.QTimer;
\r
72 import com.trolltech.qt.core.QUrl;
\r
73 import com.trolltech.qt.core.Qt;
\r
74 import com.trolltech.qt.core.Qt.Key;
\r
75 import com.trolltech.qt.core.Qt.KeyboardModifier;
\r
76 import com.trolltech.qt.core.Qt.KeyboardModifiers;
\r
77 import com.trolltech.qt.gui.QAction;
\r
78 import com.trolltech.qt.gui.QApplication;
\r
79 import com.trolltech.qt.gui.QCalendarWidget;
\r
80 import com.trolltech.qt.gui.QClipboard;
\r
81 import com.trolltech.qt.gui.QClipboard.Mode;
\r
82 import com.trolltech.qt.gui.QColor;
\r
83 import com.trolltech.qt.gui.QComboBox;
\r
84 import com.trolltech.qt.gui.QDateEdit;
\r
85 import com.trolltech.qt.gui.QDesktopServices;
\r
86 import com.trolltech.qt.gui.QFileDialog;
\r
87 import com.trolltech.qt.gui.QFileDialog.AcceptMode;
\r
88 import com.trolltech.qt.gui.QFileDialog.FileMode;
\r
89 import com.trolltech.qt.gui.QFont;
\r
90 import com.trolltech.qt.gui.QFontDatabase;
\r
91 import com.trolltech.qt.gui.QFormLayout;
\r
92 import com.trolltech.qt.gui.QGridLayout;
\r
93 import com.trolltech.qt.gui.QHBoxLayout;
\r
94 import com.trolltech.qt.gui.QIcon;
\r
95 import com.trolltech.qt.gui.QImage;
\r
96 import com.trolltech.qt.gui.QKeyEvent;
\r
97 import com.trolltech.qt.gui.QKeySequence;
\r
98 import com.trolltech.qt.gui.QLabel;
\r
99 import com.trolltech.qt.gui.QLineEdit;
\r
100 import com.trolltech.qt.gui.QListWidgetItem;
\r
101 import com.trolltech.qt.gui.QMatrix;
\r
102 import com.trolltech.qt.gui.QMessageBox;
\r
103 import com.trolltech.qt.gui.QPalette;
\r
104 import com.trolltech.qt.gui.QPalette.ColorRole;
\r
105 import com.trolltech.qt.gui.QPushButton;
\r
106 import com.trolltech.qt.gui.QShortcut;
\r
107 import com.trolltech.qt.gui.QSplitter;
\r
108 import com.trolltech.qt.gui.QTextEdit;
\r
109 import com.trolltech.qt.gui.QTextEdit.LineWrapMode;
\r
110 import com.trolltech.qt.gui.QTimeEdit;
\r
111 import com.trolltech.qt.gui.QToolButton;
\r
112 import com.trolltech.qt.gui.QToolButton.ToolButtonPopupMode;
\r
113 import com.trolltech.qt.gui.QVBoxLayout;
\r
114 import com.trolltech.qt.gui.QWidget;
\r
115 import com.trolltech.qt.network.QNetworkAccessManager;
\r
116 import com.trolltech.qt.network.QNetworkReply;
\r
117 import com.trolltech.qt.network.QNetworkReply.NetworkError;
\r
118 import com.trolltech.qt.network.QNetworkRequest;
\r
119 import com.trolltech.qt.webkit.QWebPage;
\r
120 import com.trolltech.qt.webkit.QWebPage.WebAction;
\r
121 import com.trolltech.qt.webkit.QWebSettings;
\r
122 import com.trolltech.qt.webkit.QWebView;
\r
124 import cx.fbn.nevernote.Global;
\r
125 import cx.fbn.nevernote.dialog.EnCryptDialog;
\r
126 import cx.fbn.nevernote.dialog.EnDecryptDialog;
\r
127 import cx.fbn.nevernote.dialog.GeoDialog;
\r
128 import cx.fbn.nevernote.dialog.InsertLatexImage;
\r
129 import cx.fbn.nevernote.dialog.InsertLinkDialog;
\r
130 import cx.fbn.nevernote.dialog.NoteQuickLinkDialog;
\r
131 import cx.fbn.nevernote.dialog.SpellCheck;
\r
132 import cx.fbn.nevernote.dialog.TableDialog;
\r
133 import cx.fbn.nevernote.dialog.TagAssign;
\r
134 import cx.fbn.nevernote.evernote.EnCrypt;
\r
135 import cx.fbn.nevernote.filters.FilterEditorTags;
\r
136 import cx.fbn.nevernote.signals.NoteResourceSignal;
\r
137 import cx.fbn.nevernote.signals.NoteSignal;
\r
138 import cx.fbn.nevernote.sql.DatabaseConnection;
\r
139 import cx.fbn.nevernote.utilities.ApplicationLogger;
\r
140 import cx.fbn.nevernote.utilities.FileUtils;
\r
141 import cx.fbn.nevernote.utilities.Pair;
\r
142 import cx.fbn.nevernote.xml.HtmlTagModifier;
\r
144 public class BrowserWindow extends QWidget {
\r
146 public final QLineEdit titleLabel;
\r
147 private final QLineEdit urlText;
\r
148 private final QLabel authorLabel;
\r
149 private final QLineEdit authorText;
\r
150 private final QComboBox geoBox;
\r
151 public final TagLineEdit tagEdit;
\r
152 public final QLabel tagLabel;
\r
153 private final QPushButton urlLabel;
\r
154 private final QLabel alteredLabel;
\r
155 private final QDateEdit alteredDate;
\r
156 private final QTimeEdit alteredTime;
\r
157 private final QDateEdit createdDate;
\r
158 private final QTimeEdit createdTime;
\r
159 private final QLabel subjectLabel;
\r
160 private final QDateEdit subjectDate;
\r
161 private final QTimeEdit subjectTime;
\r
162 public final QComboBox notebookBox;
\r
163 private final QLabel notebookLabel;
\r
164 private final QLabel createdLabel;
\r
165 public final QComboBox fontSize;
\r
166 public final QAction fontSizeAction;
\r
167 private boolean extendedOn;
\r
168 public boolean buttonsVisible;
\r
169 private final String iconPath;
\r
170 private final ContentView browser;
\r
171 private final QTextEdit sourceEdit;
\r
172 private String sourceEditHeader;
\r
173 Highlighter syntaxHighlighter;
\r
174 private List<Tag> allTags;
\r
175 private List<String> currentTags;
\r
176 public NoteSignal noteSignal;
\r
177 public Signal2<String,String> evernoteLinkClicked;
\r
178 private List<Notebook> notebookList;
\r
179 private Note currentNote;
\r
180 private String saveNoteTitle;
\r
181 private String saveTagList;
\r
182 private boolean insideList;
\r
183 private final DatabaseConnection conn;
\r
184 private final QCalendarWidget createdCalendarWidget;
\r
185 private final QCalendarWidget alteredCalendarWidget;
\r
186 private final QCalendarWidget subjectCalendarWidget;
\r
188 public final QPushButton undoButton;
\r
189 public final QAction undoAction;
\r
190 public final QPushButton redoButton;
\r
191 public final QAction redoAction;
\r
192 public final QPushButton cutButton;
\r
193 public final QAction cutAction;
\r
194 public final QPushButton copyButton;
\r
195 public final QAction copyAction;
\r
196 public final QPushButton pasteButton;
\r
197 public final QAction pasteAction;
\r
198 public final QPushButton boldButton;
\r
199 public final QAction boldAction;
\r
200 public final QPushButton underlineButton;
\r
201 public final QAction underlineAction;
\r
202 public final QPushButton italicButton;
\r
203 public final QAction italicAction;
\r
204 public final Signal0 focusLost;
\r
205 public final NoteResourceSignal resourceSignal;
\r
207 public QPushButton rightAlignButton;
\r
208 public final QAction rightAlignAction;
\r
209 public QPushButton leftAlignButton;
\r
210 public final QAction leftAlignAction;
\r
211 public QPushButton centerAlignButton;
\r
212 public final QAction centerAlignAction;
\r
214 public final QPushButton strikethroughButton;
\r
215 public final QAction strikethroughAction;
\r
216 public final QPushButton hlineButton;
\r
217 public final QAction hlineAction;
\r
218 public final QPushButton indentButton;
\r
219 public final QAction indentAction;
\r
220 public final QPushButton outdentButton;
\r
221 public final QAction outdentAction;
\r
222 public final QPushButton bulletListButton;
\r
223 public final QAction bulletListAction;
\r
224 public final QPushButton numberListButton;
\r
225 public final QAction numberListAction;
\r
226 public final QPushButton spellCheckButton;
\r
227 public final QAction spellCheckAction;
\r
228 public final QPushButton todoButton;
\r
229 public final QAction todoAction;
\r
231 public final QShortcut focusTitleShortcut;
\r
232 public final QShortcut focusTagShortcut;
\r
233 public final QShortcut focusNoteShortcut;
\r
234 public final QShortcut focusUrlShortcut;
\r
235 public final QShortcut focusAuthorShortcut;
\r
237 public EditorButtonBar buttonLayout;
\r
238 public final QComboBox fontList;
\r
239 public final QAction fontListAction;
\r
240 public final QToolButton fontColor;
\r
241 public final QAction fontColorAction;
\r
242 private final ColorMenu fontColorMenu;
\r
243 public final QToolButton fontHilight;
\r
244 public final QAction fontHilightAction;
\r
245 private final ColorMenu fontHilightColorMenu;
\r
246 public final QFileSystemWatcher fileWatcher;
\r
247 public int cursorPosition;
\r
248 private boolean forceTextPaste;
\r
249 private String selectedFile;
\r
250 private String currentHyperlink;
\r
251 public boolean keepPDFNavigationHidden;
\r
252 private final ApplicationLogger logger;
\r
253 SpellDictionary dictionary;
\r
254 SpellDictionary userDictionary;
\r
255 SpellChecker spellChecker;
\r
256 SuggestionListener spellListener;
\r
257 private final HashMap<String,Integer> previewPageList;
\r
258 boolean insertHyperlink;
\r
259 boolean insideTable;
\r
260 boolean insideEncryption;
\r
261 public Signal1<BrowserWindow> blockApplication;
\r
262 public Signal0 unblockApplication;
\r
263 public boolean awaitingHttpResponse;
\r
264 public long unblockTime;
\r
265 private final QTimer setSourceTimer;
\r
266 String latexGuid; // This is set if we are editing an existing LaTeX formula. Useful to track guid.
\r
269 public static class SuggestionListener implements SpellCheckListener {
\r
270 public boolean abortSpellCheck = false;
\r
271 public boolean errorsFound = false;
\r
272 private final SpellCheck spellCheckDialog;
\r
275 private final BrowserWindow parent;
\r
276 public SuggestionListener(BrowserWindow parent, SpellChecker checker) {
\r
277 this.parent = parent;
\r
278 spellCheckDialog = new SpellCheck(checker);
\r
280 public void spellingError(SpellCheckEvent event) {
\r
281 errorsFound = true;
\r
282 spellCheckDialog.setWord(event.getInvalidWord());
\r
284 @SuppressWarnings("unchecked")
\r
285 List<Word> suggestions = event.getSuggestions();
\r
286 spellCheckDialog.clearSuggestions();
\r
287 if (!suggestions.isEmpty()) {
\r
288 // spellCheckDialog.setCurrentSuggestion(suggestions.get(0).getWord());
\r
289 for (int i=0; i<suggestions.size(); i++) {
\r
290 spellCheckDialog.addSuggestion(suggestions.get(i).getWord());
\r
292 spellCheckDialog.setSelectedSuggestion(0);
\r
294 spellCheckDialog.exec();
\r
295 if (spellCheckDialog.cancelPressed()) {
\r
296 abortSpellCheck = true;
\r
300 if (spellCheckDialog.replacePressed()) {
\r
301 QClipboard clipboard = QApplication.clipboard();
\r
302 clipboard.setText(spellCheckDialog.getReplacementWord());
\r
303 parent.pasteClicked();
\r
311 public BrowserWindow(DatabaseConnection c) {
\r
312 logger = new ApplicationLogger("browser.log");
\r
313 logger.log(logger.HIGH, "Setting up browser");
\r
314 iconPath = new String("classpath:cx/fbn/nevernote/icons/");
\r
315 forceTextPaste = false;
\r
316 insertHyperlink = true;
\r
317 insideTable = false;
\r
318 insideEncryption = false;
\r
320 fileWatcher = new QFileSystemWatcher();
\r
321 // fileWatcher.fileChanged.connect(this, "fileChanged(String)");
\r
322 noteSignal = new NoteSignal();
\r
323 titleLabel = new QLineEdit();
\r
324 evernoteLinkClicked = new Signal2<String,String>();
\r
325 titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX);
\r
326 urlText = new QLineEdit();
\r
327 authorText = new QLineEdit();
\r
328 geoBox = new QComboBox();
\r
329 urlLabel = new QPushButton();
\r
330 urlLabel.clicked.connect(this, "sourceUrlClicked()");
\r
331 authorLabel = new QLabel();
\r
334 focusLost = new Signal0();
\r
336 tagEdit = new TagLineEdit(allTags);
\r
337 tagLabel = new QLabel(tr("Tags:"));
\r
338 tagEdit.focusLost.connect(this, "modifyTagsTyping()");
\r
340 createdCalendarWidget = new QCalendarWidget();
\r
341 createdDate = new QDateEdit();
\r
342 createdDate.setDisplayFormat(Global.getDateFormat());
\r
343 createdDate.setCalendarPopup(true);
\r
344 createdDate.setCalendarWidget(createdCalendarWidget);
\r
345 createdTime = new QTimeEdit();
\r
346 createdDate.dateChanged.connect(this, "createdChanged()");
\r
347 createdTime.timeChanged.connect(this, "createdChanged()");
\r
349 alteredCalendarWidget = new QCalendarWidget();
\r
350 alteredDate = new QDateEdit();
\r
351 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
352 alteredDate.setCalendarPopup(true);
\r
353 alteredDate.setCalendarWidget(alteredCalendarWidget);
\r
354 alteredTime = new QTimeEdit();
\r
355 alteredLabel = new QLabel(tr("Altered:"));
\r
356 alteredDate.dateChanged.connect(this, "alteredChanged()");
\r
357 alteredTime.timeChanged.connect(this, "alteredChanged()");
\r
359 subjectCalendarWidget = new QCalendarWidget();
\r
360 subjectDate = new QDateEdit();
\r
361 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
362 subjectDate.setCalendarPopup(true);
\r
363 subjectDate.setCalendarWidget(subjectCalendarWidget);
\r
364 subjectTime = new QTimeEdit();
\r
365 subjectLabel = new QLabel(tr("Subject Date:"));
\r
366 subjectDate.dateChanged.connect(this, "subjectDateTimeChanged()");
\r
367 subjectTime.timeChanged.connect(this, "subjectDateTimeChanged()");
\r
368 authorText.textChanged.connect(this, "authorChanged()");
\r
369 urlText.textChanged.connect(this, "sourceUrlChanged()");
\r
371 notebookBox = new QComboBox();
\r
372 notebookLabel = new QLabel(tr("Notebook"));
\r
373 createdLabel = new QLabel(tr("Created:"));
\r
374 // selectedText = new String();
\r
376 urlLabel.setVisible(false);
\r
377 urlText.setVisible(false);
\r
378 authorLabel.setVisible(false);
\r
380 geoBox.setVisible(false);
\r
381 geoBox.addItem(new QIcon(iconPath+"globe.png"), "");
\r
382 geoBox.addItem(new String(tr("Set")));
\r
383 geoBox.addItem(new String(tr("Clear")));
\r
384 geoBox.addItem(new String(tr("View On Map")));
\r
385 geoBox.activated.connect(this, "geoBoxChanged()");
\r
387 authorText.setVisible(false);
\r
388 createdDate.setVisible(false);
\r
389 alteredLabel.setVisible(false);
\r
390 //notebookBox.setVisible(false);
\r
391 notebookLabel.setVisible(false);
\r
392 createdLabel.setVisible(false);
\r
393 createdTime.setVisible(false);
\r
394 alteredDate.setVisible(false);
\r
395 alteredTime.setVisible(false);
\r
396 subjectLabel.setVisible(false);
\r
397 subjectDate.setVisible(false);
\r
398 subjectTime.setVisible(false);
\r
399 extendedOn = false;
\r
400 buttonsVisible = true;
\r
401 setAcceptDrops(true);
\r
403 browser = new ContentView(this);
\r
405 browser.page().setLinkDelegationPolicy(
\r
406 QWebPage.LinkDelegationPolicy.DelegateAllLinks);
\r
407 browser.linkClicked.connect(this, "linkClicked(QUrl)");
\r
408 currentHyperlink = "";
\r
410 //Setup the source editor
\r
411 sourceEdit = new QTextEdit(this);
\r
412 sourceEdit.setVisible(false);
\r
413 sourceEdit.setTabChangesFocus(true);
\r
414 sourceEdit.setLineWrapMode(LineWrapMode.NoWrap);
\r
415 QFont font = new QFont();
\r
416 font.setFamily("Courier");
\r
417 font.setFixedPitch(true);
\r
418 font.setPointSize(10);
\r
419 sourceEdit.setFont(font);
\r
420 syntaxHighlighter = new Highlighter(sourceEdit.document());
\r
421 sourceEdit.textChanged.connect(this, "sourceEdited()");
\r
423 QVBoxLayout v = new QVBoxLayout();
\r
424 QFormLayout notebookLayout = new QFormLayout();
\r
425 QGridLayout dateLayout = new QGridLayout();
\r
426 titleLabel.setReadOnly(false);
\r
427 titleLabel.editingFinished.connect(this, "titleEdited()");
\r
428 browser.page().contentsChanged.connect(this, "contentChanged()");
\r
429 browser.page().selectionChanged.connect(this, "selectionChanged()");
\r
430 browser.page().mainFrame().javaScriptWindowObjectCleared.connect(this,
\r
431 "exposeToJavascript()");
\r
433 notebookBox.activated.connect(this, "notebookChanged()");
\r
434 resourceSignal = new NoteResourceSignal();
\r
436 QHBoxLayout tagLayout = new QHBoxLayout();
\r
437 v.addWidget(titleLabel, 0);
\r
438 notebookLayout.addRow(notebookLabel, notebookBox);
\r
439 tagLayout.addLayout(notebookLayout, 0);
\r
440 tagLayout.stretch(4);
\r
441 tagLayout.addWidget(tagLabel, 0);
\r
442 tagLayout.addWidget(tagEdit, 1);
\r
443 v.addLayout(tagLayout);
\r
445 QHBoxLayout urlLayout = new QHBoxLayout();
\r
446 urlLayout.addWidget(urlLabel, 0);
\r
447 urlLayout.addWidget(urlText, 0);
\r
448 v.addLayout(urlLayout);
\r
450 QHBoxLayout authorLayout = new QHBoxLayout();
\r
451 authorLayout.addWidget(authorLabel, 0);
\r
452 authorLayout.addWidget(authorText, 0);
\r
453 authorLayout.addWidget(geoBox);
\r
454 v.addLayout(authorLayout);
\r
456 dateLayout.addWidget(createdLabel, 0, 0);
\r
457 dateLayout.addWidget(createdDate, 0, 1);
\r
458 dateLayout.addWidget(createdTime, 0, 2);
\r
459 dateLayout.setColumnStretch(9, 100);
\r
460 dateLayout.addWidget(alteredLabel, 0, 3);
\r
461 dateLayout.addWidget(alteredDate, 0, 4);
\r
462 dateLayout.addWidget(alteredTime, 0, 5);
\r
463 dateLayout.addWidget(subjectLabel, 0, 6);
\r
464 dateLayout.addWidget(subjectDate, 0, 7);
\r
465 dateLayout.addWidget(subjectTime, 0, 8);
\r
466 v.addLayout(dateLayout, 0);
\r
468 undoButton = newEditorButton("undo", tr("Undo Change"));
\r
469 redoButton = newEditorButton("redo", tr("Redo Change"));
\r
470 cutButton = newEditorButton("cut", tr("Cut"));
\r
471 copyButton = newEditorButton("copy", tr("Copy"));
\r
472 pasteButton = newEditorButton("paste", tr("Paste"));
\r
473 boldButton = newEditorButton("bold", tr("Bold"));
\r
474 underlineButton = newEditorButton("underline", tr("Underline"));
\r
475 italicButton = newEditorButton("italic", tr("Italic"));
\r
477 rightAlignButton = newEditorButton("justifyRight", tr("Right Align"));
\r
478 leftAlignButton = newEditorButton("justifyLeft", tr("Left Align"));
\r
479 centerAlignButton = newEditorButton("justifyCenter", tr("Center Align"));
\r
481 strikethroughButton = newEditorButton("strikethrough", tr("Strikethrough"));
\r
482 hlineButton = newEditorButton("hline", tr("Insert Horizontal Line"));
\r
483 indentButton = newEditorButton("indent", tr("Shift Right"));
\r
484 outdentButton = newEditorButton("outdent", tr("Shift Left"));
\r
485 bulletListButton = newEditorButton("bulletList", tr("Bullet List"));
\r
486 numberListButton = newEditorButton("numberList", tr("Number List"));
\r
487 spellCheckButton = newEditorButton("spellCheck", tr("Spell Check"));
\r
488 todoButton = newEditorButton("todo", tr("To-do"));
\r
491 buttonLayout = new EditorButtonBar();
\r
492 v.addWidget(buttonLayout);
\r
494 undoAction = buttonLayout.addWidget(undoButton);
\r
495 buttonLayout.toggleUndoVisible.triggered.connect(this, "toggleUndoVisible(Boolean)");
\r
496 redoAction = buttonLayout.addWidget(redoButton);
\r
497 buttonLayout.toggleRedoVisible.triggered.connect(this, "toggleRedoVisible(Boolean)");
\r
499 buttonLayout.addWidget(newSeparator());
\r
500 cutAction = buttonLayout.addWidget(cutButton);
\r
501 buttonLayout.toggleCutVisible.triggered.connect(this, "toggleCutVisible(Boolean)");
\r
502 copyAction = buttonLayout.addWidget(copyButton);
\r
503 buttonLayout.toggleCopyVisible.triggered.connect(this, "toggleCopyVisible(Boolean)");
\r
504 pasteAction = buttonLayout.addWidget(pasteButton);
\r
505 buttonLayout.togglePasteVisible.triggered.connect(this, "togglePasteVisible(Boolean)");
\r
507 buttonLayout.addWidget(newSeparator());
\r
508 boldAction = buttonLayout.addWidget(boldButton);
\r
509 buttonLayout.toggleBoldVisible.triggered.connect(this, "toggleBoldVisible(Boolean)");
\r
510 italicAction = buttonLayout.addWidget(italicButton);
\r
511 buttonLayout.toggleItalicVisible.triggered.connect(this, "toggleItalicVisible(Boolean)");
\r
512 underlineAction = buttonLayout.addWidget(underlineButton);
\r
513 buttonLayout.toggleUnderlineVisible.triggered.connect(this, "toggleUnderlineVisible(Boolean)");
\r
514 strikethroughAction = buttonLayout.addWidget(strikethroughButton);
\r
515 buttonLayout.toggleStrikethroughVisible.triggered.connect(this, "toggleStrikethroughVisible(Boolean)");
\r
518 buttonLayout.addWidget(newSeparator());
\r
519 leftAlignAction = buttonLayout.addWidget(leftAlignButton);
\r
520 buttonLayout.toggleLeftAlignVisible.triggered.connect(this, "toggleLeftAlignVisible(Boolean)");
\r
521 centerAlignAction = buttonLayout.addWidget(centerAlignButton);
\r
522 buttonLayout.toggleCenterAlignVisible.triggered.connect(this, "toggleCenterAlignVisible(Boolean)");
\r
523 rightAlignAction = buttonLayout.addWidget(rightAlignButton);
\r
524 buttonLayout.toggleRightAlignVisible.triggered.connect(this, "toggleRightAlignVisible(Boolean)");
\r
526 buttonLayout.addWidget(newSeparator());
\r
527 hlineAction = buttonLayout.addWidget(hlineButton);
\r
528 buttonLayout.toggleHLineVisible.triggered.connect(this, "toggleHLineVisible(Boolean)");
\r
530 indentAction = buttonLayout.addWidget(indentButton);
\r
531 buttonLayout.toggleIndentVisible.triggered.connect(this, "toggleIndentVisible(Boolean)");
\r
532 outdentAction = buttonLayout.addWidget(outdentButton);
\r
533 buttonLayout.toggleOutdentVisible.triggered.connect(this, "toggleOutdentVisible(Boolean)");
\r
534 bulletListAction = buttonLayout.addWidget(bulletListButton);
\r
535 buttonLayout.toggleBulletListVisible.triggered.connect(this, "toggleBulletListVisible(Boolean)");
\r
536 numberListAction = buttonLayout.addWidget(numberListButton);
\r
537 buttonLayout.toggleNumberListVisible.triggered.connect(this, "toggleNumberListVisible(Boolean)");
\r
539 // Setup the font & font size combo boxes
\r
540 buttonLayout.addWidget(newSeparator());
\r
541 fontList = new QComboBox();
\r
542 fontSize = new QComboBox();
\r
543 fontList.setToolTip("Font");
\r
544 fontSize.setToolTip("Font Size");
\r
545 fontList.activated.connect(this, "fontChanged(String)");
\r
546 fontSize.activated.connect(this, "fontSizeChanged(String)");
\r
547 fontListAction = buttonLayout.addWidget(fontList);
\r
548 buttonLayout.toggleFontVisible.triggered.connect(this, "toggleFontListVisible(Boolean)");
\r
549 fontSizeAction = buttonLayout.addWidget(fontSize);
\r
550 buttonLayout.toggleFontSizeVisible.triggered.connect(this, "toggleFontSizeVisible(Boolean)");
\r
551 QFontDatabase fonts = new QFontDatabase();
\r
552 List<String> fontFamilies = fonts.families();
\r
553 for (int i = 0; i < fontFamilies.size(); i++) {
\r
554 fontList.addItem(fontFamilies.get(i));
\r
556 loadFontSize(fontFamilies.get(i));
\r
560 // buttonLayout.addWidget(newSeparator(), 0);
\r
561 fontColor = newToolButton("fontColor", tr("Font Color"));
\r
562 fontColorMenu = new ColorMenu(this);
\r
563 fontColor.setMenu(fontColorMenu.getMenu());
\r
564 fontColor.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
565 fontColor.setAutoRaise(false);
\r
566 fontColorMenu.getMenu().triggered.connect(this, "fontColorClicked()");
\r
567 fontColorAction = buttonLayout.addWidget(fontColor);
\r
568 buttonLayout.toggleFontColorVisible.triggered.connect(this, "toggleFontColorVisible(Boolean)");
\r
569 fontHilight = newToolButton("fontHilight", tr("Font Hilight Color"));
\r
570 fontHilight.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
571 fontHilight.setAutoRaise(false);
\r
572 fontHilightColorMenu = new ColorMenu(this);
\r
573 fontHilightColorMenu.setDefault(QColor.yellow);
\r
574 fontHilight.setMenu(fontHilightColorMenu.getMenu());
\r
575 fontHilightColorMenu.getMenu().triggered.connect(this, "fontHilightClicked()");
\r
576 fontHilightAction = buttonLayout.addWidget(fontHilight);
\r
577 fontHilightColorMenu.setDefault(QColor.yellow);
\r
578 buttonLayout.toggleFontHilight.triggered.connect(this, "toggleFontHilightVisible(Boolean)");
\r
580 spellCheckAction = buttonLayout.addWidget(spellCheckButton);
\r
581 buttonLayout.toggleNumberListVisible.triggered.connect(this, "spellCheckClicked()");
\r
582 buttonLayout.toggleSpellCheck.triggered.connect(this, "toggleSpellCheckVisible(Boolean)");
\r
584 todoAction = buttonLayout.addWidget(todoButton);
\r
585 buttonLayout.toggleNumberListVisible.triggered.connect(this, "todoClicked()");
\r
586 buttonLayout.toggleTodo.triggered.connect(this, "toggleTodoVisible(Boolean)");
\r
588 // Setup the source browser);
\r
590 // buttonLayout.addWidget(new QLabel(), 1);
\r
591 QSplitter editSplitter = new QSplitter(this);
\r
592 editSplitter.addWidget(browser);
\r
593 editSplitter.setOrientation(Qt.Orientation.Vertical);
\r
594 editSplitter.addWidget(sourceEdit);
\r
598 // v.addWidget(browser, 1);
\r
599 // v.addWidget(sourceEdit);
\r
600 v.addWidget(editSplitter);
\r
603 browser.downloadAttachmentRequested.connect(this,
\r
604 "downloadAttachment(QNetworkRequest)");
\r
605 browser.downloadImageRequested.connect(this,
\r
606 "downloadImage(QNetworkRequest)");
\r
607 setTabOrder(notebookBox, tagEdit);
\r
608 setTabOrder(tagEdit, browser);
\r
610 focusNoteShortcut = new QShortcut(this);
\r
611 setupShortcut(focusNoteShortcut, "Focus_Note");
\r
612 focusNoteShortcut.activated.connect(this, "focusNote()");
\r
613 focusTitleShortcut = new QShortcut(this);
\r
614 setupShortcut(focusTitleShortcut, "Focus_Title");
\r
615 focusTitleShortcut.activated.connect(this, "focusTitle()");
\r
616 focusTagShortcut = new QShortcut(this);
\r
617 setupShortcut(focusTagShortcut, "Focus_Tag");
\r
618 focusTagShortcut.activated.connect(this, "focusTag()");
\r
619 focusAuthorShortcut = new QShortcut(this);
\r
620 setupShortcut(focusAuthorShortcut, "Focus_Author");
\r
621 focusAuthorShortcut.activated.connect(this, "focusAuthor()");
\r
622 focusUrlShortcut = new QShortcut(this);
\r
623 setupShortcut(focusUrlShortcut, "Focus_Url");
\r
624 focusUrlShortcut.activated.connect(this, "focusUrl()");
\r
626 browser.page().mainFrame().setTextSizeMultiplier(Global.getTextSizeMultiplier());
\r
627 browser.page().mainFrame().setZoomFactor(Global.getZoomFactor());
\r
629 previewPageList = new HashMap<String,Integer>();
\r
631 browser.page().microFocusChanged.connect(this, "microFocusChanged()");
\r
635 QPalette pal = new QPalette();
\r
636 pal.setColor(ColorRole.Text, QColor.black);
\r
637 titleLabel.setPalette(pal);
\r
638 authorText.setPalette(pal);
\r
639 authorLabel.setPalette(pal);
\r
640 urlLabel.setPalette(pal);
\r
641 urlText.setPalette(pal);
\r
642 createdDate.setPalette(pal);
\r
643 createdTime.setPalette(pal);
\r
644 alteredDate.setPalette(pal);
\r
645 alteredTime.setPalette(pal);
\r
646 subjectDate.setPalette(pal);
\r
647 subjectTime.setPalette(pal);
\r
648 tagEdit.setPalette(pal);
\r
649 notebookBox.setPalette(pal);
\r
651 blockApplication = new Signal1<BrowserWindow>();
\r
652 unblockApplication = new Signal0();
\r
654 setSourceTimer = new QTimer();
\r
655 setSourceTimer.timeout.connect(this, "setSource()");
\r
657 logger.log(logger.HIGH, "Browser setup complete");
\r
662 private void setupShortcut(QShortcut action, String text) {
\r
663 if (!Global.shortcutKeys.containsAction(text))
\r
665 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
\r
671 // Getter for the QWebView
\r
672 public QWebView getBrowser() {
\r
676 // Block signals while loading data or things are flagged as dirty by
\r
678 public void loadingData(boolean val) {
\r
679 logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val);
\r
680 notebookBox.blockSignals(val);
\r
681 browser.page().blockSignals(val);
\r
682 browser.page().mainFrame().blockSignals(val);
\r
683 titleLabel.blockSignals(val);
\r
684 alteredDate.blockSignals(val);
\r
685 alteredTime.blockSignals(val);
\r
686 createdTime.blockSignals(val);
\r
687 createdDate.blockSignals(val);
\r
688 subjectDate.blockSignals(val);
\r
689 subjectTime.blockSignals(val);
\r
690 urlText.blockSignals(val);
\r
691 authorText.blockSignals(val);
\r
693 exposeToJavascript();
\r
694 logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val);
\r
698 public void setReadOnly(boolean v) {
\r
700 titleLabel.setEnabled(!v);
\r
701 notebookBox.setEnabled(!v);
\r
702 tagEdit.setEnabled(!v);
\r
703 authorLabel.setEnabled(!v);
\r
704 geoBox.setEnabled(!v);
\r
705 urlText.setEnabled(!v);
\r
706 createdDate.setEnabled(!v);
\r
707 subjectDate.setEnabled(!v);
\r
708 alteredDate.setEnabled(!v);
\r
709 authorText.setEnabled(!v);
\r
710 createdTime.setEnabled(!v);
\r
711 alteredTime.setEnabled(!v);
\r
712 subjectTime.setEnabled(!v);
\r
713 getBrowser().setEnabled(true);
\r
714 // getBrowser().setEnabled(!v);
\r
717 // expose this class to Javascript on the web page
\r
718 private void exposeToJavascript() {
\r
719 browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this);
\r
722 // Custom event queue
\r
724 public boolean event(QEvent e) {
\r
725 if (e.type().equals(QEvent.Type.FocusOut)) {
\r
726 logger.log(logger.EXTREME, "Focus lost");
\r
729 return super.event(e);
\r
732 // clear out browser
\r
733 public void clear() {
\r
734 logger.log(logger.EXTREME, "Entering BrowserWindow.clear()");
\r
736 setContent(new QByteArray());
\r
737 tagEdit.setText("");
\r
738 tagEdit.tagCompleter.reset();
\r
739 urlLabel.setText(tr("Source URL:"));
\r
740 titleLabel.setText("");
\r
741 logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()");
\r
744 public void setContent(QByteArray data) {
\r
745 sourceEdit.blockSignals(true);
\r
746 browser.setContent(data);
\r
749 // get/set current note
\r
750 public void setNote(Note n) {
\r
754 saveNoteTitle = n.getTitle();
\r
758 public Note getNote() {
\r
759 return currentNote;
\r
762 // New Editor Button
\r
763 private QPushButton newEditorButton(String name, String toolTip) {
\r
764 QPushButton button = new QPushButton();
\r
765 // QIcon icon = new QIcon(iconPath + name + ".gif");
\r
766 QIcon icon = new QIcon(iconPath + name + ".png");
\r
767 button.setIcon(icon);
\r
768 button.setToolTip(toolTip);
\r
769 button.clicked.connect(this, name + "Clicked()");
\r
772 // New Editor Button
\r
773 private QToolButton newToolButton(String name, String toolTip) {
\r
774 QToolButton button = new QToolButton();
\r
775 // QIcon icon = new QIcon(iconPath + name + ".gif");
\r
776 QIcon icon = new QIcon(iconPath + name + ".png");
\r
777 button.setIcon(icon);
\r
778 button.setToolTip(toolTip);
\r
779 button.clicked.connect(this, name + "Clicked()");
\r
784 private QLabel newSeparator() {
\r
785 return new QLabel(" ");
\r
788 // Set the title in the window
\r
789 public void setTitle(String t) {
\r
790 titleLabel.setText(t);
\r
795 // Return the current text title
\r
796 public String getTitle() {
\r
797 return titleLabel.text();
\r
800 // Set the tag name string
\r
801 public void setTag(String t) {
\r
803 tagEdit.setText(t);
\r
804 tagEdit.tagCompleter.reset();
\r
807 // Set the source URL
\r
808 public void setUrl(String t) {
\r
809 urlLabel.setText(tr("Source URL:\t"));
\r
810 urlText.setText(t);
\r
813 // The user want's to launch a web browser on the source of the URL
\r
814 public void sourceUrlClicked() {
\r
815 // Make sure we have a valid URL
\r
816 if (urlText.text().trim().equals(""))
\r
819 String url = urlText.text();
\r
820 if (!url.toLowerCase().startsWith(tr("http://")))
\r
821 url = tr("http://") +url;
\r
823 if (!QDesktopServices.openUrl(new QUrl(url))) {
\r
824 logger.log(logger.LOW, "Error opening file :" +url);
\r
828 public void setAuthor(String t) {
\r
829 authorLabel.setText(tr("Author:\t"));
\r
830 authorText.setText(t);
\r
833 // Set the creation date
\r
834 public void setCreation(long date) {
\r
835 QDateTime dt = new QDateTime();
\r
836 dt.setTime_t((int) (date / 1000));
\r
837 createdDate.setDateTime(dt);
\r
838 createdTime.setDateTime(dt);
\r
839 createdDate.setDisplayFormat(Global.getDateFormat());
\r
840 createdTime.setDisplayFormat(Global.getTimeFormat());
\r
843 // Set the creation date
\r
844 public void setAltered(long date) {
\r
845 QDateTime dt = new QDateTime();
\r
846 dt.setTime_t((int) (date / 1000));
\r
847 alteredDate.setDateTime(dt);
\r
848 alteredTime.setDateTime(dt);
\r
849 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
850 alteredTime.setDisplayFormat(Global.getTimeFormat());
\r
853 // Set the subject date
\r
854 public void setSubjectDate(long date) {
\r
855 QDateTime dt = new QDateTime();
\r
856 dt.setTime_t((int) (date / 1000));
\r
857 subjectDate.setDateTime(dt);
\r
858 subjectTime.setDateTime(dt);
\r
859 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
860 subjectTime.setDisplayFormat(Global.getTimeFormat());
\r
863 // Toggle the extended attribute information
\r
864 public void toggleInformation() {
\r
866 extendedOn = false;
\r
870 urlLabel.setVisible(extendedOn);
\r
871 urlText.setVisible(extendedOn);
\r
872 authorText.setVisible(extendedOn);
\r
873 geoBox.setVisible(extendedOn);
\r
874 authorLabel.setVisible(extendedOn);
\r
875 createdDate.setVisible(extendedOn);
\r
876 createdTime.setVisible(extendedOn);
\r
877 createdLabel.setVisible(extendedOn);
\r
878 alteredLabel.setVisible(extendedOn);
\r
879 alteredDate.setVisible(extendedOn);
\r
880 alteredTime.setVisible(extendedOn);
\r
881 //notebookBox.setVisible(extendedOn);
\r
882 notebookLabel.setVisible(extendedOn);
\r
883 subjectLabel.setVisible(extendedOn);
\r
884 subjectDate.setVisible(extendedOn);
\r
885 subjectTime.setVisible(extendedOn);
\r
888 public void hideButtons() {
\r
890 undoButton.parentWidget().setVisible(false);
\r
891 buttonsVisible = false;
\r
895 // Is the extended view on?
\r
896 public boolean isExtended() {
\r
900 // Listener for when a link is clicked
\r
901 @SuppressWarnings("unused")
\r
902 private void openFile() {
\r
903 logger.log(logger.EXTREME, "Starting openFile()");
\r
904 File fileHandle = new File(selectedFile);
\r
905 URI fileURL = fileHandle.toURI();
\r
906 String localURL = fileURL.toString();
\r
907 QUrl url = new QUrl(localURL);
\r
908 QFile file = new QFile(selectedFile);
\r
910 logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName());
\r
911 fileWatcher.addPath(file.fileName());
\r
913 if (!QDesktopServices.openUrl(url)) {
\r
914 logger.log(logger.LOW, "Error opening file :" +url);
\r
919 // Listener for when a link is clicked
\r
920 @SuppressWarnings("unused")
\r
921 private void linkClicked(QUrl url) {
\r
922 logger.log(logger.EXTREME, "URL Clicked: " +url.toString());
\r
923 if (url.toString().startsWith("latex:")) {
\r
924 int position = url.toString().lastIndexOf(".");
\r
925 String guid = url.toString().substring(0,position);
\r
926 position = guid.lastIndexOf("/");
\r
927 guid = guid.substring(position+1);
\r
931 if (url.toString().startsWith("evernote:/view/")) {
\r
932 StringTokenizer tokens = new StringTokenizer(url.toString().replace("evernote:/view/", ""), "/");
\r
933 tokens.nextToken();
\r
934 tokens.nextToken();
\r
935 String sid = tokens.nextToken();
\r
936 String lid = tokens.nextToken();
\r
938 // Emit that we want to switch to a new note
\r
939 evernoteLinkClicked.emit(sid, lid);
\r
943 if (url.toString().startsWith("nnres://")) {
\r
944 logger.log(logger.EXTREME, "URL is NN resource");
\r
945 if (url.toString().endsWith("/vnd.evernote.ink")) {
\r
946 logger.log(logger.EXTREME, "Unable to open ink note");
\r
947 QMessageBox.information(this, tr("Unable Open"), tr("This is an ink note.\n"+
\r
948 "Ink notes are not supported since Evernote has not\n published any specifications on them\n" +
\r
949 "and I'm too lazy to figure them out by myself."));
\r
952 String fullName = url.toString().substring(8);
\r
953 int index = fullName.indexOf(".");
\r
957 type = fullName.substring(index+1);
\r
958 guid = fullName.substring(0,index);
\r
960 index = guid.indexOf(Global.attachmentNameDelimeter);
\r
962 guid = guid.substring(0,index);
\r
964 List<Resource> resList = currentNote.getResources();
\r
965 Resource res = null;
\r
966 for (int i=0; i<resList.size(); i++) {
\r
967 if (resList.get(i).getGuid().equals(guid)) {
\r
968 res = resList.get(i);
\r
973 String resGuid = Global.resourceMap.get(guid);
\r
974 if (resGuid != null)
\r
975 res = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, true);
\r
979 if (res.getAttributes() != null &&
\r
980 res.getAttributes().getFileName() != null &&
\r
981 !res.getAttributes().getFileName().trim().equals(""))
\r
982 fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();
\r
984 fileName = res.getGuid()+"."+type;
\r
985 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
986 QFile.OpenMode mode = new QFile.OpenMode();
\r
987 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
988 boolean openResult = file.open(mode);
\r
989 logger.log(logger.EXTREME, "File opened:" +openResult);
\r
990 QDataStream out = new QDataStream(file);
\r
991 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);
\r
992 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
994 logger.log(logger.EXTREME, "Writing resource");
\r
995 out.writeBytes(binData.toByteArray());
\r
998 String whichOS = System.getProperty("os.name");
\r
999 if (whichOS.contains("Windows"))
\r
1000 url.setUrl("file:///"+file.fileName());
\r
1002 url.setUrl("file://"+file.fileName());
\r
1003 // fileWatcher.removePath(file.fileName());
\r
1004 logger.log(logger.EXTREME, "Adding file watcher " +file.fileName());
\r
1005 fileWatcher.addPath(file.fileName());
\r
1007 // If we can't open it, then prompt the user to save it.
\r
1008 if (!QDesktopServices.openUrl(url)) {
\r
1009 logger.log(logger.EXTREME, "We can't handle this. Where do we put it?");
\r
1010 QFileDialog dialog = new QFileDialog();
\r
1012 if (dialog.exec()!=0) {
\r
1013 List<String> fileNames = dialog.selectedFiles(); //gets all selected filenames
\r
1014 if (fileNames.size() == 0)
\r
1016 String sf = fileNames.get(0);
\r
1017 QFile saveFile = new QFile(sf);
\r
1018 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
1019 saveFile.open(mode);
\r
1020 QDataStream saveOut = new QDataStream(saveFile);
\r
1021 saveOut.writeBytes(binData.toByteArray());
\r
1029 logger.log(logger.EXTREME, "Launching URL");
\r
1030 QDesktopServices.openUrl(url);
\r
1033 // Listener for when BOLD is clicked
\r
1034 @SuppressWarnings("unused")
\r
1035 private void undoClicked() {
\r
1036 browser.page().triggerAction(WebAction.Undo);
\r
1037 browser.setFocus();
\r
1040 // Listener for when BOLD is clicked
\r
1041 @SuppressWarnings("unused")
\r
1042 private void redoClicked() {
\r
1043 browser.page().triggerAction(WebAction.Redo);
\r
1044 browser.setFocus();
\r
1047 // Listener for when BOLD is clicked
\r
1048 @SuppressWarnings("unused")
\r
1049 private void boldClicked() {
\r
1050 browser.page().triggerAction(WebAction.ToggleBold);
\r
1051 microFocusChanged();
\r
1052 browser.setFocus();
\r
1055 // Listener for when Italics is clicked
\r
1056 @SuppressWarnings("unused")
\r
1057 private void italicClicked() {
\r
1058 browser.page().triggerAction(WebAction.ToggleItalic);
\r
1059 microFocusChanged();
\r
1060 browser.setFocus();
\r
1063 // Listener for when UNDERLINE is clicked
\r
1064 @SuppressWarnings("unused")
\r
1065 private void underlineClicked() {
\r
1066 browser.page().triggerAction(WebAction.ToggleUnderline);
\r
1067 microFocusChanged();
\r
1068 browser.setFocus();
\r
1071 // Listener for when Strikethrough is clicked
\r
1072 @SuppressWarnings("unused")
\r
1073 private void strikethroughClicked() {
\r
1074 browser.page().mainFrame().evaluateJavaScript(
\r
1075 "document.execCommand('strikeThrough', false, '');");
\r
1076 browser.setFocus();
\r
1079 // Listener for when cut is clicked
\r
1080 @SuppressWarnings("unused")
\r
1081 private void cutClicked() {
\r
1082 browser.page().triggerAction(WebAction.Cut);
\r
1083 browser.setFocus();
\r
1086 // Listener when COPY is clicked
\r
1087 @SuppressWarnings("unused")
\r
1088 private void copyClicked() {
\r
1089 browser.page().triggerAction(WebAction.Copy);
\r
1090 browser.setFocus();
\r
1093 // Listener when PASTE is clicked
\r
1094 public void pasteClicked() {
\r
1095 logger.log(logger.EXTREME, "Paste Clicked");
\r
1096 if (forceTextPaste) {
\r
1097 pasteWithoutFormattingClicked();
\r
1100 QClipboard clipboard = QApplication.clipboard();
\r
1101 QMimeData mime = clipboard.mimeData();
\r
1103 if (mime.hasImage()) {
\r
1104 logger.log(logger.EXTREME, "Image paste found");
\r
1105 browser.setFocus();
\r
1106 insertImage(mime);
\r
1107 browser.setFocus();
\r
1111 if (mime.hasUrls()) {
\r
1112 logger.log(logger.EXTREME, "URL paste found");
\r
1113 if (mime.text().startsWith("evernote:")) {
\r
1114 handleNoteLink(mime);
\r
1117 browser.setFocus();
\r
1122 String text = mime.html();
\r
1123 if (text.contains("en-tag") && mime.hasHtml()) {
\r
1124 logger.log(logger.EXTREME, "Intra-note paste found");
\r
1125 text = fixInternotePaste(text);
\r
1126 mime.setHtml(text);
\r
1127 clipboard.setMimeData(mime);
\r
1130 logger.log(logger.EXTREME, "Final paste choice encountered");
\r
1131 browser.page().triggerAction(WebAction.Paste);
\r
1132 browser.setFocus();
\r
1136 // Paste text without formatting
\r
1137 private void pasteWithoutFormattingClicked() {
\r
1138 logger.log(logger.EXTREME, "Paste without format clipped");
\r
1139 QClipboard clipboard = QApplication.clipboard();
\r
1140 QMimeData mime = clipboard.mimeData();
\r
1141 if (!mime.hasText())
\r
1143 String text = mime.text();
\r
1144 clipboard.clear();
\r
1145 clipboard.setText(text, Mode.Clipboard);
\r
1146 browser.page().triggerAction(WebAction.Paste);
\r
1148 // This is done because pasting into an encryption block
\r
1149 // can cause multiple cells (which can't happen). It
\r
1150 // just goes through the table, extracts the data, &
\r
1151 // puts it back as one table cell.
\r
1152 if (insideEncryption) {
\r
1153 String js = new String( "function fixEncryption() { "
\r
1154 +" var selObj = window.getSelection();"
\r
1155 +" var selRange = selObj.getRangeAt(0);"
\r
1156 +" var workingNode = window.getSelection().anchorNode;"
\r
1157 +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
\r
1158 +" workingNode = workingNode.parentNode;"
\r
1160 +" workingNode.innerHTML = window.jambi.fixEncryptionPaste(workingNode.innerHTML);"
\r
1161 +"} fixEncryption();");
\r
1162 browser.page().mainFrame().evaluateJavaScript(js);
\r
1166 // This basically removes all the table tags and returns just the contents.
\r
1167 // This is called by JavaScript to fix encryption pastes.
\r
1168 public String fixEncryptionPaste(String data) {
\r
1169 data = data.replace("<tbody>", "");
\r
1170 data = data.replace("</tbody>", "");
\r
1171 data = data.replace("<tr>", "");
\r
1172 data = data.replace("</tr>", "");
\r
1173 data = data.replace("<td>", "");
\r
1174 data = data.replace("</td>", "<br>");
\r
1175 data = data.replace("<br><br>", "<br>");
\r
1177 return "<tbody><tr><td>"+data+"</td></tr></tbody>";
\r
1180 // insert date/time
\r
1181 @SuppressWarnings("unused")
\r
1182 private void insertDateTime() {
\r
1183 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
\r
1184 String dateTimeFormat = new String(fmt);
\r
1185 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
\r
1186 Calendar cal = Calendar.getInstance();
\r
1188 browser.page().mainFrame().evaluateJavaScript(
\r
1189 "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");
\r
1191 browser.setFocus();
\r
1195 // Listener when Left is clicked
\r
1196 @SuppressWarnings("unused")
\r
1197 private void justifyLeftClicked() {
\r
1198 browser.page().mainFrame().evaluateJavaScript(
\r
1199 "document.execCommand('JustifyLeft', false, '');");
\r
1200 browser.setFocus();
\r
1203 // Listener when Center is clicked
\r
1204 @SuppressWarnings("unused")
\r
1205 private void justifyCenterClicked() {
\r
1206 browser.page().mainFrame().evaluateJavaScript(
\r
1207 "document.execCommand('JustifyCenter', false, '');");
\r
1208 browser.setFocus();
\r
1211 // Listener when Left is clicked
\r
1212 @SuppressWarnings("unused")
\r
1213 private void justifyRightClicked() {
\r
1214 browser.page().mainFrame().evaluateJavaScript(
\r
1215 "document.execCommand('JustifyRight', false, '');");
\r
1216 browser.setFocus();
\r
1219 // Listener when HLINE is clicked
\r
1220 @SuppressWarnings("unused")
\r
1221 private void hlineClicked() {
\r
1222 browser.page().mainFrame().evaluateJavaScript(
\r
1223 "document.execCommand('insertHorizontalRule', false, '');");
\r
1224 browser.setFocus();
\r
1227 // Listener when outdent is clicked
\r
1228 private void outdentClicked() {
\r
1229 browser.page().mainFrame().evaluateJavaScript(
\r
1230 "document.execCommand('outdent', false, '');");
\r
1231 browser.setFocus();
\r
1234 // Listener when a bullet list is clicked
\r
1235 @SuppressWarnings("unused")
\r
1236 private void bulletListClicked() {
\r
1237 browser.page().mainFrame().evaluateJavaScript(
\r
1238 "document.execCommand('InsertUnorderedList', false, '');");
\r
1239 browser.setFocus();
\r
1242 // Listener when a bullet list is clicked
\r
1243 @SuppressWarnings("unused")
\r
1244 private void numberListClicked() {
\r
1245 browser.page().mainFrame().evaluateJavaScript(
\r
1246 "document.execCommand('InsertOrderedList', false, '');");
\r
1247 browser.setFocus();
\r
1250 // Listener when indent is clicked
\r
1251 private void indentClicked() {
\r
1252 browser.page().mainFrame().evaluateJavaScript(
\r
1253 "document.execCommand('indent', false, '');");
\r
1254 browser.setFocus();
\r
1257 // Listener when the font name is changed
\r
1258 @SuppressWarnings("unused")
\r
1259 private void fontChanged(String font) {
\r
1260 browser.page().mainFrame().evaluateJavaScript(
\r
1261 "document.execCommand('fontName',false,'" + font + "');");
\r
1262 browser.setFocus();
\r
1265 // Listener when a font size is changed
\r
1266 @SuppressWarnings("unused")
\r
1267 private void fontSizeChanged(String font) {
\r
1268 String text = browser.selectedText();
\r
1269 if (text.trim().equalsIgnoreCase(""))
\r
1272 String selectedText = browser.selectedText();
\r
1273 String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";
\r
1274 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1275 browser.page().mainFrame().evaluateJavaScript(script);
\r
1276 /* browser.page().mainFrame().evaluateJavaScript(
\r
1277 "document.execCommand('fontSize',false,'"
\r
1280 browser.setFocus();
\r
1283 // Load the font combo box based upon the font selected
\r
1284 private void loadFontSize(String name) {
\r
1285 QFontDatabase db = new QFontDatabase();
\r
1287 List<Integer> points = db.pointSizes(name);
\r
1288 for (int i=0; i<points.size(); i++) {
\r
1289 fontSize.addItem(points.get(i).toString());
\r
1292 fontSize.addItem("x-small");
\r
1293 fontSize.addItem("small");
\r
1294 fontSize.addItem("medium");
\r
1295 fontSize.addItem("large");
\r
1296 fontSize.addItem("x-large");
\r
1297 fontSize.addItem("xx-large");
\r
1298 fontSize.addItem("xxx-large");
\r
1302 // Listener when a font size is changed
\r
1303 @SuppressWarnings("unused")
\r
1304 private void fontColorClicked() {
\r
1305 // QColorDialog dialog = new QColorDialog();
\r
1306 // QColor color = QColorDialog.getColor();
\r
1307 QColor color = fontColorMenu.getColor();
\r
1308 if (color.isValid())
\r
1309 browser.page().mainFrame().evaluateJavaScript(
\r
1310 "document.execCommand('foreColor',false,'" + color.name()
\r
1312 browser.setFocus();
\r
1315 // Listener for when a background color change is requested
\r
1316 @SuppressWarnings("unused")
\r
1317 private void fontHilightClicked() {
\r
1318 // QColorDialog dialog = new QColorDialog();
\r
1319 // QColor color = QColorDialog.getColor();
\r
1320 QColor color = fontHilightColorMenu.getColor();
\r
1321 if (color.isValid())
\r
1322 browser.page().mainFrame().evaluateJavaScript(
\r
1323 "document.execCommand('backColor',false,'" + color.name()
\r
1325 browser.setFocus();
\r
1328 // Listener for when a background color change is requested
\r
1329 @SuppressWarnings("unused")
\r
1330 private void superscriptClicked() {
\r
1331 browser.page().mainFrame().evaluateJavaScript(
\r
1332 "document.execCommand('superscript');");
\r
1333 browser.setFocus();
\r
1336 // Listener for when a background color change is requested
\r
1337 @SuppressWarnings("unused")
\r
1338 private void subscriptClicked() {
\r
1339 browser.page().mainFrame().evaluateJavaScript(
\r
1340 "document.execCommand('subscript');");
\r
1341 browser.setFocus();
\r
1343 // Insert a to-do checkbox
\r
1344 @SuppressWarnings("unused")
\r
1345 private void todoClicked() {
\r
1346 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1347 String script_start = new String(
\r
1348 "document.execCommand('insertHtml', false, '");
\r
1349 String script_end = new String("');");
\r
1350 String todo = new String(
\r
1351 "<input TYPE=\"CHECKBOX\" value=\"false\" " +
\r
1352 "onMouseOver=\"style.cursor=\\'hand\\'\" " +
\r
1353 "onClick=\"value=checked; window.jambi.contentChanged(); \" />");
\r
1354 browser.page().mainFrame().evaluateJavaScript(
\r
1355 script_start + todo + script_end);
\r
1356 browser.setFocus();
\r
1359 // Encrypt the selected text
\r
1360 @SuppressWarnings("unused")
\r
1361 private void encryptText() {
\r
1362 String text = browser.selectedText();
\r
1363 if (text.trim().equalsIgnoreCase(""))
\r
1365 text = new String(text.replaceAll("\n", "<br/>"));
\r
1367 EnCryptDialog dialog = new EnCryptDialog();
\r
1369 if (!dialog.okPressed()) {
\r
1373 EnCrypt crypt = new EnCrypt();
\r
1374 String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);
\r
1375 String decrypted = crypt.decrypt(encrypted, dialog.getPassword().trim(), 64);
\r
1377 if (encrypted.trim().equals("")) {
\r
1378 QMessageBox.information(this, tr("Error"), tr("Error Encrypting String"));
\r
1381 StringBuffer buffer = new StringBuffer(encrypted.length() + 100);
\r
1382 buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""
\r
1383 + dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");
\r
1384 buffer.append("contentEditable=\"false\" alt=\"");
\r
1385 buffer.append(encrypted);
\r
1386 buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png") +"\""));
\r
1387 Global.cryptCounter++;
\r
1388 buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");
\r
1389 buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");
\r
1390 buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString()
\r
1391 +"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&apos;")+"\\');\"");
\r
1392 buffer.append("style=\"display:block\" />");
\r
1394 String script_start = new String(
\r
1395 "document.execCommand('insertHtml', false, '");
\r
1396 String script_end = new String("');");
\r
1397 browser.page().mainFrame().evaluateJavaScript(
\r
1398 script_start + buffer.toString() + script_end);
\r
1402 // Insert a Quick hyperlink
\r
1403 public void insertQuickLink() {
\r
1404 logger.log(logger.EXTREME, "Inserting link");
\r
1405 String text = browser.selectedText();
\r
1406 if (text.trim().equalsIgnoreCase(""))
\r
1409 NoteQuickLinkDialog dialog = new NoteQuickLinkDialog(logger, conn, text);
\r
1410 if (dialog.getResults().size() == 0) {
\r
1411 QMessageBox.critical(null, tr("No Matches Found") ,tr("No matching notes found."));
\r
1414 if (dialog.getResults().size() > 1) {
\r
1416 if (!dialog.okPressed) {
\r
1417 logger.log(logger.EXTREME, "Insert link canceled");
\r
1422 User user = Global.getUserInformation();
\r
1423 String dUrl = new String("evernote:///view/") + new String(user.getId() + "/" +user.getShardId() +"/"
\r
1424 +dialog.getSelectedNote()+"/"+dialog.getSelectedNote() +"/ " +"style=\"color:#69aa35\"");
\r
1426 String url = "<a title=\"" +dUrl
\r
1427 +"\" href=" +dUrl
\r
1428 +" >"+text +"</a>";
\r
1429 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1430 browser.page().mainFrame().evaluateJavaScript(script);
\r
1434 // Insert a hyperlink
\r
1435 public void insertLink() {
\r
1436 logger.log(logger.EXTREME, "Inserting link");
\r
1437 String text = browser.selectedText();
\r
1438 if (text.trim().equalsIgnoreCase(""))
\r
1441 InsertLinkDialog dialog = new InsertLinkDialog(insertHyperlink);
\r
1442 if (currentHyperlink != null && currentHyperlink != "") {
\r
1443 dialog.setUrl(currentHyperlink);
\r
1446 if (!dialog.okPressed()) {
\r
1447 logger.log(logger.EXTREME, "Insert link canceled");
\r
1451 // Take care of inserting new links
\r
1452 if (insertHyperlink) {
\r
1453 String selectedText = browser.selectedText();
\r
1454 if (dialog.getUrl().trim().equals(""))
\r
1456 logger.log(logger.EXTREME, "Inserting link on text "+selectedText);
\r
1457 logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim());
\r
1458 String dUrl = StringUtils.replace(dialog.getUrl().trim(), "'", "\\'");
\r
1459 String url = "<a href=\"" +dUrl
\r
1460 +"\" title=" +dUrl
\r
1461 +" >"+selectedText +"</a>";
\r
1462 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1463 browser.page().mainFrame().evaluateJavaScript(script);
\r
1467 // Edit existing links
\r
1468 String js = new String( "function getCursorPos() {"
\r
1470 +"if (window.getSelection) {"
\r
1471 +" var selObj = window.getSelection();"
\r
1472 +" var selRange = selObj.getRangeAt(0);"
\r
1473 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1474 +" while(workingNode != null) { "
\r
1475 +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');"
\r
1476 +" workingNode = workingNode.parentNode;"
\r
1479 +"} getCursorPos();");
\r
1480 browser.page().mainFrame().evaluateJavaScript(js);
\r
1482 if (!dialog.getUrl().trim().equals("")) {
\r
1488 js = new String( "function getCursorPos() {"
\r
1490 +"if (window.getSelection) {"
\r
1491 +" var selObj = window.getSelection();"
\r
1492 +" var selRange = selObj.getRangeAt(0);"
\r
1493 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1494 +" while(workingNode != null) { "
\r
1495 +" if (workingNode.nodeName.toLowerCase()=='a') { "
\r
1496 +" workingNode.removeAttribute('href');"
\r
1497 +" workingNode.removeAttribute('title');"
\r
1498 +" var text = document.createTextNode(workingNode.innerText);"
\r
1499 +" workingNode.parentNode.insertBefore(text, workingNode);"
\r
1500 +" workingNode.parentNode.removeChild(workingNode);"
\r
1502 +" workingNode = workingNode.parentNode;"
\r
1505 +"} getCursorPos();");
\r
1506 browser.page().mainFrame().evaluateJavaScript(js);
\r
1514 // Insert a hyperlink
\r
1515 public void insertLatex() {
\r
1518 public void editLatex(String guid) {
\r
1519 logger.log(logger.EXTREME, "Inserting latex");
\r
1520 String text = browser.selectedText();
\r
1521 if (text.trim().equalsIgnoreCase("\n") || text.trim().equalsIgnoreCase("")) {
\r
1522 InsertLatexImage dialog = new InsertLatexImage();
\r
1523 if (guid != null) {
\r
1524 String formula = conn.getNoteTable().noteResourceTable.getNoteSourceUrl(guid).replace("http://latex.codecogs.com/gif.latex?", "");
\r
1525 dialog.setFormula(formula);
\r
1528 if (!dialog.okPressed()) {
\r
1529 logger.log(logger.EXTREME, "Edit LaTex canceled");
\r
1532 text = dialog.getFormula().trim();
\r
1534 blockApplication.emit(this);
\r
1535 logger.log(logger.EXTREME, "Inserting LaTeX formula:" +text);
\r
1537 text = StringUtils.replace(text, "'", "\\'");
\r
1538 String url = "http://latex.codecogs.com/gif.latex?" +text;
\r
1539 logger.log(logger.EXTREME, "Sending request to codecogs --> " + url);
\r
1540 QNetworkAccessManager manager = new QNetworkAccessManager(this);
\r
1541 manager.finished.connect(this, "insertLatexImageReady(QNetworkReply)");
\r
1542 unblockTime = new GregorianCalendar().getTimeInMillis()+5000;
\r
1543 awaitingHttpResponse = true;
\r
1544 manager.get(new QNetworkRequest(new QUrl(url)));
\r
1547 public void insertLatexImageReady(QNetworkReply reply) {
\r
1548 logger.log(logger.EXTREME, "Response received from CodeCogs");
\r
1549 if (reply.error() != NetworkError.NoError)
\r
1553 if (!awaitingHttpResponse)
\r
1556 awaitingHttpResponse = false;
\r
1557 QUrl replyUrl = reply.url();
\r
1558 QByteArray image = reply.readAll();
\r
1560 logger.log(logger.EXTREME, "New image size: " +image.size());
\r
1562 Resource newRes = null;
\r
1565 if (latexGuid == null) {
\r
1566 logger.log(logger.EXTREME, "Creating temporary gif");
\r
1567 path = Global.getFileManager().getResDirPath("latex-temp.gif");
\r
1568 tfile = new QFile(path);
\r
1569 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1570 logger.log(logger.EXTREME, "File Open: " +tfile.errorString());
\r
1571 tfile.write(image);
\r
1572 logger.log(logger.EXTREME, "Bytes writtes: "+tfile.size());
\r
1574 logger.log(logger.EXTREME, "Creating resource");
\r
1576 if (currentNote.getResources() != null || currentNote.getResources().size() > 0)
\r
1577 sequence = currentNote.getResources().size();
\r
1578 newRes = createResource(path,sequence ,"image/gif", false);
\r
1579 QImage pix = new QImage();
\r
1580 pix.loadFromData(image);
\r
1581 newRes.setHeight(new Integer(pix.height()).shortValue());
\r
1582 newRes.setWidth(new Integer(pix.width()).shortValue());
\r
1583 logger.log(logger.EXTREME, "Renaming temporary file to " +newRes.getGuid()+".gif");
\r
1584 path = Global.getFileManager().getResDirPath(newRes.getGuid()+".gif");
\r
1585 tfile.rename(path);
\r
1587 newRes = conn.getNoteTable().noteResourceTable.getNoteResource(latexGuid, false);
\r
1588 path = Global.getFileManager().getResDirPath(newRes.getGuid()+".gif");
\r
1589 tfile = new QFile(path);
\r
1590 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1591 tfile.write(image);
\r
1593 newRes.getData().setBody(image.toByteArray());
\r
1594 // Calculate the new hash value
\r
1597 logger.log(logger.EXTREME, "Generating MD5");
\r
1599 md = MessageDigest.getInstance("MD5");
\r
1600 md.update(image.toByteArray());
\r
1601 byte[] hash = md.digest();
\r
1602 newRes.getData().setBodyHash(hash);
\r
1603 } catch (NoSuchAlgorithmException e) {
\r
1604 e.printStackTrace();
\r
1606 QImage pix = new QImage();
\r
1607 pix.loadFromData(image);
\r
1608 newRes.setHeight(new Integer(pix.height()).shortValue());
\r
1609 newRes.setWidth(new Integer(pix.width()).shortValue());
\r
1610 conn.getNoteTable().noteResourceTable.updateNoteResource(newRes, true);
\r
1613 logger.log(logger.EXTREME, "Setting source: " +replyUrl.toString());
\r
1614 newRes.getAttributes().setSourceURL(replyUrl.toString());
\r
1615 conn.getNoteTable().noteResourceTable.updateNoteSourceUrl(newRes.getGuid(), replyUrl.toString(), true);
\r
1617 for(int i=0; i<currentNote.getResourcesSize(); i++) {
\r
1618 if (currentNote.getResources().get(i).getGuid().equals(newRes.getGuid())) {
\r
1619 currentNote.getResources().remove(i);
\r
1620 i=currentNote.getResourcesSize();
\r
1623 currentNote.getResources().add(newRes);
\r
1626 // do the actual insert into the note. We only do this on new formulas.
\r
1627 if (latexGuid == null) {
\r
1628 StringBuffer buffer = new StringBuffer(100);
\r
1629 String formula = replyUrl.toString().toLowerCase().replace("http://latex.codecogs.com/gif.latex?", "");
\r
1630 buffer.append("<a href=\"latex://"+path.replace("\\", "/")+"\" title=\""+formula+"\""
\r
1632 buffer.append(path.replace("\\", "/"));
\r
1633 buffer.append("\" en-tag=\"en-latex\" type=\"image/gif\""
\r
1634 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1635 +" guid=\"" +newRes.getGuid() +"\""
\r
1638 String script_start = new String("document.execCommand('insertHTML', false, '");
\r
1639 String script_end = new String("');");
\r
1640 browser.page().mainFrame().evaluateJavaScript(
\r
1641 script_start + buffer + script_end);
\r
1643 HtmlTagModifier modifier = new HtmlTagModifier(getContent());
\r
1644 modifier.modifyLatexTagHash(newRes);
\r
1645 String newContent = modifier.getHtml();
\r
1646 setContent(new QByteArray(newContent));
\r
1649 logger.log(logger.EXTREME, "New HTML set\n" +browser.page().currentFrame().toHtml());
\r
1650 QWebSettings.setMaximumPagesInCache(0);
\r
1651 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
1653 browser.page().mainFrame().setHtml(browser.page().mainFrame().toHtml());
\r
1656 // resourceSignal.contentChanged.emit(path);
\r
1658 unblockApplication.emit();
\r
1666 public void insertTable() {
\r
1667 TableDialog dialog = new TableDialog();
\r
1669 if (!dialog.okPressed()) {
\r
1673 int cols = dialog.getCols();
\r
1674 int rows = dialog.getRows();
\r
1675 int width = dialog.getWidth();
\r
1676 boolean percent = dialog.isPercent();
\r
1678 String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();
\r
1680 newHTML = newHTML +"%";
\r
1681 newHTML = newHTML + "\"><tbody>";
\r
1683 for (int i=0; i<rows; i++) {
\r
1684 newHTML = newHTML +"<tr>";
\r
1685 for (int j=0; j<cols; j++) {
\r
1686 newHTML = newHTML +"<td> </td>";
\r
1688 newHTML = newHTML +"</tr>";
\r
1690 newHTML = newHTML+"</tbody></table>";
\r
1692 String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";
\r
1693 browser.page().mainFrame().evaluateJavaScript(script);
\r
1697 // Text content changed
\r
1698 @SuppressWarnings("unused")
\r
1699 private void selectionChanged() {
\r
1700 browser.encryptAction.setEnabled(true);
\r
1701 browser.insertLinkAction.setEnabled(true);
\r
1702 browser.insertQuickLinkAction.setEnabled(true);
\r
1703 String scriptStart = "var selection_text = (window.getSelection()).toString();"
\r
1704 + "var range = (window.getSelection()).getRangeAt(0);"
\r
1705 + "var parent_html = range.commonAncestorContainer.innerHTML;"
\r
1706 + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"
\r
1707 + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"
\r
1708 + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"
\r
1709 + "var start = parent_html.indexOf(first_text);"
\r
1710 + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"
\r
1711 + "var value = parent_html.substring(start,end);"
\r
1712 + "window.jambi.saveSelectedText(value);" ;
\r
1713 browser.page().mainFrame().evaluateJavaScript(scriptStart);
\r
1717 public void saveSelectedText(String text) {
\r
1718 boolean enabled = true;
\r
1719 if (text.trim().length() == 0)
\r
1721 if (text.indexOf("en-tag=\"en-crypt\"") >= 0)
\r
1723 if (text.indexOf("<img en-tag=\"en-media\"") >= 0)
\r
1725 if (text.indexOf("<a en-tag=\"en-media\"") >= 0)
\r
1727 if (text.indexOf("<input ") >= 0)
\r
1730 browser.encryptAction.setEnabled(enabled);
\r
1731 browser.insertLinkAction.setEnabled(enabled);
\r
1732 browser.insertQuickLinkAction.setEnabled(enabled);
\r
1733 // selectedText = text;
\r
1736 // Decrypt clicked text
\r
1737 public void decryptText(String id, String text, String hint) {
\r
1738 EnCrypt crypt = new EnCrypt();
\r
1739 String plainText = null;
\r
1740 Calendar currentTime = new GregorianCalendar();
\r
1741 Long l = new Long(currentTime.getTimeInMillis());
\r
1742 String slot = new String(Long.toString(l));
\r
1744 // First, try to decrypt with any keys we already have
\r
1745 for (int i=0; i<Global.passwordRemember.size(); i++) {
\r
1746 plainText = crypt.decrypt(text, Global.passwordRemember.get(i).getFirst(), 64);
\r
1747 if (plainText != null) {
\r
1748 slot = new String(Long.toString(l));
\r
1749 Global.passwordSafe.put(slot, Global.passwordRemember.get(i));
\r
1750 removeEncryption(id, plainText, false, slot);
\r
1756 EnDecryptDialog dialog = new EnDecryptDialog();
\r
1757 dialog.setHint(hint);
\r
1758 while (plainText == null || !dialog.okPressed()) {
\r
1760 if (!dialog.okPressed()) {
\r
1763 plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);
\r
1764 if (plainText == null) {
\r
1765 QMessageBox.warning(this, tr("Incorrect Password"), tr("The password entered is not correct"));
\r
1768 Pair<String,String> passwordPair = new Pair<String,String>();
\r
1769 passwordPair.setFirst(dialog.getPassword());
\r
1770 passwordPair.setSecond(dialog.getHint());
\r
1771 Global.passwordSafe.put(slot, passwordPair);
\r
1772 // removeEncryption(id, plainText.replaceAll("\n", "<br/>"), dialog.permanentlyDecrypt(), slot);
\r
1773 removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);
\r
1774 if (dialog.rememberPassword()) {
\r
1775 Pair<String, String> pair = new Pair<String,String>();
\r
1776 pair.setFirst(dialog.getPassword());
\r
1777 pair.setSecond(dialog.getHint());
\r
1778 Global.passwordRemember.add(pair);
\r
1783 // Get the editor tag line
\r
1784 public TagLineEdit getTagLine() {
\r
1788 // Modify a note's tags
\r
1789 @SuppressWarnings("unused")
\r
1790 private void modifyTags() {
\r
1791 TagAssign tagWindow = new TagAssign(allTags, currentTags, !conn.getNotebookTable().isLinked(currentNote.getNotebookGuid()));
\r
1793 if (tagWindow.okClicked()) {
\r
1794 currentTags.clear();
\r
1795 StringBuffer tagDisplay = new StringBuffer();
\r
1797 List<QListWidgetItem> newTags = tagWindow.getTagList()
\r
1799 for (int i = 0; i < newTags.size(); i++) {
\r
1800 currentTags.add(newTags.get(i).text());
\r
1801 tagDisplay.append(newTags.get(i).text());
\r
1802 if (i < newTags.size() - 1) {
\r
1803 tagDisplay.append(Global.tagDelimeter + " ");
\r
1806 tagEdit.setText(tagDisplay.toString());
\r
1807 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1811 // Tag line has been modified by typing text
\r
1812 @SuppressWarnings("unused")
\r
1813 private void modifyTagsTyping() {
\r
1814 String completionText = "";
\r
1815 if (tagEdit.currentCompleterSelection != null && !tagEdit.currentCompleterSelection.equals("")) {
\r
1816 completionText = tagEdit.currentCompleterSelection;
\r
1817 tagEdit.currentCompleterSelection = "";
\r
1820 if (tagEdit.text().equalsIgnoreCase(saveTagList))
\r
1823 // We know something has changed...
\r
1824 String oldTagArray[] = saveTagList.split(Global.tagDelimeter);
\r
1825 String newTagArray[];
\r
1826 if (!completionText.equals("")) {
\r
1827 String before = tagEdit.text().substring(0,tagEdit.cursorPosition());
\r
1828 int lastDelimiter = before.lastIndexOf(Global.tagDelimeter);
\r
1829 if (lastDelimiter > 0)
\r
1830 before = before.substring(0,before.lastIndexOf(Global.tagDelimeter));
\r
1833 String after = tagEdit.text().substring(tagEdit.cursorPosition());
\r
1834 newTagArray = (before+Global.tagDelimeter+completionText+Global.tagDelimeter+after).split(Global.tagDelimeter);
\r
1837 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1840 // Remove any traling or leading blanks
\r
1841 for (int i=0; i<newTagArray.length; i++)
\r
1842 newTagArray[i] = newTagArray[i].trim().replaceAll("^\\s+", "");;
\r
1844 // Remove any potential duplicates from the new list
\r
1845 for (int i=0; i<newTagArray.length; i++) {
\r
1846 boolean foundOnce = false;
\r
1847 for (int j=0; j<newTagArray.length; j++) {
\r
1848 if (newTagArray[j].equalsIgnoreCase(newTagArray[i])) {
\r
1852 newTagArray[j] = "";
\r
1857 List<String> newTagList = new ArrayList<String>();
\r
1858 List<String> oldTagList = new ArrayList<String>();
\r
1860 for (int i = 0; i < oldTagArray.length; i++)
\r
1861 if (!oldTagArray[i].trim().equals(""))
\r
1862 oldTagList.add(oldTagArray[i]);
\r
1863 for (int i = 0; i < newTagArray.length; i++)
\r
1864 if (!newTagArray[i].trim().equals(""))
\r
1865 newTagList.add(newTagArray[i]);
\r
1867 if (conn.getNotebookTable().isLinked(currentNote.getNotebookGuid())) {
\r
1868 for (int i=newTagList.size()-1; i>=0; i--) {
\r
1869 boolean found = false;
\r
1870 for (int j=0; j<allTags.size(); j++) {
\r
1871 if (allTags.get(j).getName().equalsIgnoreCase(newTagList.get(i))) {
\r
1877 newTagList.remove(i);
\r
1881 // Let's cleanup the appearance of the tag list
\r
1882 Collections.sort(newTagList);
\r
1883 String newDisplay = "";
\r
1884 for (int i=0; i<newTagList.size(); i++) {
\r
1885 newDisplay = newDisplay+newTagList.get(i);
\r
1886 if (i<newTagList.size()-1)
\r
1887 newDisplay = newDisplay+Global.tagDelimeter +" ";
\r
1889 tagEdit.blockSignals(true);
\r
1890 tagEdit.setText(newDisplay);
\r
1891 tagEdit.blockSignals(false);
\r
1893 // We now have lists of the new & old. Remove duplicates. If all
\r
1894 // are removed from both then nothing has really changed
\r
1895 for (int i = newTagList.size() - 1; i >= 0; i--) {
\r
1896 String nTag = newTagList.get(i);
\r
1897 for (int j = oldTagList.size() - 1; j >= 0; j--) {
\r
1898 String oTag = oldTagList.get(j);
\r
1899 if (oTag.equalsIgnoreCase(nTag)) {
\r
1900 oldTagList.remove(j);
\r
1901 newTagList.remove(i);
\r
1907 if (oldTagList.size() != 0 || newTagList.size() != 0) {
\r
1908 currentTags.clear();
\r
1909 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1910 for (int i = 0; i < newTagArray.length; i++)
\r
1911 if (!newTagArray[i].trim().equals(""))
\r
1912 currentTags.add(newTagArray[i].trim());
\r
1914 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1919 // Tab button was pressed
\r
1920 public void tabPressed() {
\r
1921 if (insideEncryption)
\r
1923 if (!insideList && !insideTable) {
\r
1924 String script_start = new String(
\r
1925 "document.execCommand('insertHtml', false, ' ');");
\r
1926 browser.page().mainFrame().evaluateJavaScript(script_start);
\r
1932 if (insideTable) {
\r
1933 String js = new String( "function getCursorPosition() { "
\r
1934 +" var selObj = window.getSelection();"
\r
1935 +" var selRange = selObj.getRangeAt(0);"
\r
1936 +" var workingNode = window.getSelection().anchorNode;"
\r
1937 +" var rowCount = 0;"
\r
1938 +" var colCount = 0;"
\r
1939 +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
\r
1940 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
1941 +" rowCount = rowCount+1;"
\r
1943 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
1944 +" colCount = colCount+1;"
\r
1946 +" if (workingNode.previousSibling != null)"
\r
1947 +" workingNode = workingNode.previousSibling;"
\r
1949 +" workingNode = workingNode.parentNode;"
\r
1951 +" var nodes = workingNode.getElementsByTagName('tr');"
\r
1952 +" var tableRows = nodes.length;"
\r
1953 +" nodes = nodes[0].getElementsByTagName('td');"
\r
1954 +" var tableColumns = nodes.length;"
\r
1955 +" window.jambi.setTableCursorPositionTab(rowCount, colCount, tableRows, tableColumns);"
\r
1956 +"} getCursorPosition();");
\r
1957 browser.page().mainFrame().evaluateJavaScript(js);
\r
1961 // If a user presses tab from within a table
\r
1962 public void setTableCursorPositionTab(int currentRow, int currentCol, int tableRows, int tableColumns) {
\r
1963 if (tableRows == currentRow && currentCol == tableColumns) {
\r
1966 KeyboardModifiers modifiers = new KeyboardModifiers(KeyboardModifier.NoModifier);
\r
1967 QKeyEvent right = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Right.value(), modifiers);
\r
1968 QKeyEvent end = new QKeyEvent(Type.KeyPress, Qt.Key.Key_End.value(), modifiers);
\r
1969 QKeyEvent end2 = new QKeyEvent(Type.KeyPress, Qt.Key.Key_End.value(), modifiers);
\r
1970 getBrowser().focusWidget();
\r
1971 QCoreApplication.postEvent(getBrowser(), end);
\r
1972 QCoreApplication.postEvent(getBrowser(), right);
\r
1973 QCoreApplication.postEvent(getBrowser(), end2);
\r
1976 public void backtabPressed() {
\r
1977 if (insideEncryption)
\r
1981 if (insideTable) {
\r
1982 String js = new String( "function getCursorPosition() { "
\r
1983 +" var selObj = window.getSelection();"
\r
1984 +" var selRange = selObj.getRangeAt(0);"
\r
1985 +" var workingNode = window.getSelection().anchorNode;"
\r
1986 +" var rowCount = 0;"
\r
1987 +" var colCount = 0;"
\r
1988 +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
\r
1989 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
1990 +" rowCount = rowCount+1;"
\r
1992 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
1993 +" colCount = colCount+1;"
\r
1995 +" if (workingNode.previousSibling != null)"
\r
1996 +" workingNode = workingNode.previousSibling;"
\r
1998 +" workingNode = workingNode.parentNode;"
\r
2000 +" var nodes = workingNode.getElementsByTagName('tr');"
\r
2001 +" var tableRows = nodes.length;"
\r
2002 +" nodes = nodes[0].getElementsByTagName('td');"
\r
2003 +" var tableColumns = nodes.length;"
\r
2004 +" window.jambi.setTableCursorPositionBackTab(rowCount, colCount, tableRows, tableColumns);"
\r
2005 +"} getCursorPosition();");
\r
2006 browser.page().mainFrame().evaluateJavaScript(js);
\r
2011 // If a user presses backtab from within a table
\r
2012 public void setTableCursorPositionBackTab(int currentRow, int currentCol, int tableRows, int tableColumns) {
\r
2013 if (currentRow == 1 && currentCol == 1) {
\r
2016 KeyboardModifiers modifiers = new KeyboardModifiers(KeyboardModifier.NoModifier);
\r
2017 QKeyEvent left = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Left.value(), modifiers);
\r
2018 QKeyEvent home = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Home.value(), modifiers);
\r
2019 getBrowser().focusWidget();
\r
2020 QCoreApplication.postEvent(getBrowser(), home);
\r
2021 QCoreApplication.postEvent(getBrowser(), left);
\r
2025 public void setInsideList() {
\r
2026 insideList = true;
\r
2029 // The title has been edited
\r
2030 @SuppressWarnings("unused")
\r
2031 private void titleEdited() {
\r
2032 // If we don't have a good note, or if the current title
\r
2033 // matches the old title then we don't need to do anything
\r
2034 if (currentNote == null)
\r
2036 if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))
\r
2039 // If we have a real change, we need to save it.
\r
2040 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text().trim());
\r
2041 currentNote.setTitle(titleLabel.text().trim());
\r
2042 saveNoteTitle = titleLabel.text().trim();
\r
2046 // Set the list of note tags
\r
2047 public void setAllTags(List<Tag> l) {
\r
2049 tagEdit.setTagList(l);
\r
2052 // Setter for the current tags
\r
2053 public void setCurrentTags(List<String> s) {
\r
2057 // Save the list of notebooks
\r
2058 public void setNotebookList(List<Notebook> n) {
\r
2060 loadNotebookList();
\r
2063 // Load the notebook list and select the current notebook
\r
2064 private void loadNotebookList() {
\r
2065 if (notebookBox.count() != 0)
\r
2066 notebookBox.clear();
\r
2067 if (notebookList == null)
\r
2070 for (int i = 0; i < notebookList.size(); i++) {
\r
2071 notebookBox.addItem(notebookList.get(i).getName());
\r
2072 if (currentNote != null) {
\r
2073 if (currentNote.getNotebookGuid().equals(
\r
2074 notebookList.get(i).getGuid())) {
\r
2075 notebookBox.setCurrentIndex(i);
\r
2082 // Set the notebook for a note
\r
2083 public void setNotebook(String notebook) {
\r
2084 currentNote.setNotebookGuid(notebook);
\r
2085 loadNotebookList();
\r
2088 // Get the contents of the editor
\r
2089 public String getContent() {
\r
2090 return browser.page().currentFrame().toHtml();
\r
2093 // The note contents have changed
\r
2094 public void contentChanged() {
\r
2095 String content = getContent();
\r
2097 // This puts in a 1/2 second delay
\r
2098 // before updating the source editor.
\r
2099 // It improves response when someone is doing
\r
2100 // frequent updates on a large note.
\r
2101 // If the source editor isn't visible, then there
\r
2102 // is no point to doing any of this.
\r
2103 if (sourceEdit.isVisible()) {
\r
2104 setSourceTimer.stop();
\r
2105 setSourceTimer.setInterval(500);
\r
2106 setSourceTimer.setSingleShot(true);
\r
2107 setSourceTimer.start();
\r
2111 noteSignal.noteChanged.emit(currentNote.getGuid(), content);
\r
2114 // The notebook selection has changed
\r
2115 @SuppressWarnings("unused")
\r
2116 private void notebookChanged() {
\r
2117 boolean changed = false;
\r
2118 String n = notebookBox.currentText();
\r
2119 for (int i = 0; i < notebookList.size(); i++) {
\r
2120 if (n.equals(notebookList.get(i).getName())) {
\r
2121 if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {
\r
2122 String guid = conn.getNotebookTable().findNotebookByName(n);
\r
2123 if (conn.getNotebookTable().isLinked(guid)) {
\r
2124 tagEdit.setText("");
\r
2125 noteSignal.tagsChanged.emit(currentNote.getGuid(), new ArrayList<String>());
\r
2126 FilterEditorTags t = new FilterEditorTags(conn, logger);
\r
2127 setAllTags(t.getValidTags(currentNote));
\r
2129 currentNote.setNotebookGuid(notebookList.get(i).getGuid());
\r
2132 i = notebookList.size();
\r
2136 // If the notebook changed, signal the update
\r
2138 noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote
\r
2139 .getNotebookGuid());
\r
2142 // Check the note title
\r
2143 private void checkNoteTitle() {
\r
2144 String text = browser.page().currentFrame().toPlainText();
\r
2145 if (saveNoteTitle == null)
\r
2146 saveNoteTitle = new String();
\r
2147 text = text.trim();
\r
2148 int newLine = text.indexOf("\n");
\r
2150 text = text.substring(0,newLine);
\r
2151 if (saveNoteTitle.trim().equals("") || saveNoteTitle.trim().equals("Untitled Note")) {
\r
2152 if (text.trim().equals(""))
\r
2153 text = tr("Untitled Note");
\r
2154 titleLabel.setText(text);
\r
2156 if (text.length() > Constants.EDAM_NOTE_TITLE_LEN_MAX)
\r
2157 titleLabel.setText(text.substring(0, Constants.EDAM_NOTE_TITLE_LEN_MAX));
\r
2159 titleLabel.blockSignals(true);
\r
2160 if (text.trim().equals(""))
\r
2161 titleLabel.setText(tr("Untitled Note"));
\r
2163 titleLabel.setText(text);
\r
2164 titleLabel.blockSignals(false);
\r
2167 if (currentNote != null && titleLabel != null)
\r
2168 noteSignal.titleChanged.emit(currentNote.getGuid(), text);
\r
2171 // Return the note contents so we can email them
\r
2172 public String getContentsToEmail() {
\r
2173 return browser.page().currentFrame().toPlainText().trim();
\r
2175 * int body = browser.page().currentFrame().toHtml().indexOf("<body>");
\r
2176 * String temp = browser.page().currentFrame().toHtml(); if (body == -1)
\r
2177 * temp = "<html><body><b>Test</b></body></html>"; else temp =
\r
2178 * "<html>"+temp.substring(body); return temp; // return
\r
2179 * urlEncode(browser.page().currentFrame().toHtml());
\r
2183 // Insert an image into the editor
\r
2184 private void insertImage(QMimeData mime) {
\r
2185 logger.log(logger.EXTREME, "Entering insertImage");
\r
2186 QImage img = (QImage) mime.imageData();
\r
2187 String script_start = new String(
\r
2188 "document.execCommand('insertHTML', false, '");
\r
2189 String script_end = new String("');");
\r
2191 long now = new Date().getTime();
\r
2192 String path = Global.getFileManager().getResDirPath(
\r
2193 (new Long(now).toString()) + ".jpg");
\r
2195 // This block is just a hack to make sure we wait at least 1ms so we
\r
2197 // have collisions on image names
\r
2198 long i = new Date().getTime();
\r
2200 i = new Date().getTime();
\r
2202 // Open the file & write the data
\r
2203 QFile tfile = new QFile(path);
\r
2204 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
2205 if (!img.save(tfile)) {
\r
2211 Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);
\r
2212 if (newRes == null)
\r
2214 currentNote.getResources().add(newRes);
\r
2216 // do the actual insert into the note
\r
2217 StringBuffer buffer = new StringBuffer(100);
\r
2218 buffer.append("<img src=\"");
\r
2219 buffer.append(tfile.fileName());
\r
2220 buffer.append("\" en-tag=en-media type=\"image/jpeg\""
\r
2221 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
2222 +" guid=\"" +newRes.getGuid() +"\""
\r
2223 +" onContextMenu=\"window.jambi.imageContextMenu(&." +tfile.fileName() +"&.);\""
\r
2226 browser.page().mainFrame().evaluateJavaScript(
\r
2227 script_start + buffer + script_end);
\r
2232 // Handle pasting of a note-to-note link
\r
2233 private void handleNoteLink(QMimeData mime) {
\r
2234 for (int i=0; i<mime.urls().size(); i++) {
\r
2235 StringTokenizer tokens = new StringTokenizer(mime.urls().get(i).toString().replace("evernote:///view/", ""), "/");
\r
2236 tokens.nextToken();
\r
2237 tokens.nextToken();
\r
2238 String sid = tokens.nextToken();
\r
2239 String lid = tokens.nextToken();
\r
2241 if (!sid.equals(currentNote.getGuid()) && !lid.equals(currentNote.getGuid())) {
\r
2243 Note note = conn.getNoteTable().getNote(sid, false, false, false, false, false);
\r
2245 note = conn.getNoteTable().getNote(lid, false, false, false, false, false);
\r
2250 // If we've gotten this far, we have a bunch of values. We need to build the link.
\r
2251 StringBuffer url = new StringBuffer(100);
\r
2252 String script_start = new String(
\r
2253 "document.execCommand('insertHtml', false, '");
\r
2254 String script_end = new String("');");
\r
2256 url.append("<a href=\""+mime.urls().get(i).toString() +"\" style=\"color:#69aa35\">");
\r
2257 url.append(note.getTitle());
\r
2258 url.append("</a>");
\r
2259 if (mime.urls().size() > 1)
\r
2260 url.append(" ");
\r
2261 browser.page().mainFrame().evaluateJavaScript(
\r
2262 script_start + url + script_end);
\r
2267 // Handle URLs that are trying to be pasted
\r
2268 public void handleUrls(QMimeData mime) {
\r
2269 logger.log(logger.EXTREME, "Starting handleUrls");
\r
2270 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
2272 List<QUrl> urlList = mime.urls();
\r
2273 String url = new String();
\r
2274 String script_start = new String(
\r
2275 "document.execCommand('createLink', false, '");
\r
2276 String script_end = new String("');");
\r
2278 for (int i = 0; i < urlList.size(); i++) {
\r
2279 url = urlList.get(i).toString();
\r
2280 // Find out what type of file we have
\r
2281 String mimeType = fileNameMap.getContentTypeFor(url);
\r
2283 // If null returned, we need to guess at the file type
\r
2284 if (mimeType == null)
\r
2285 mimeType = "application/"
\r
2286 + url.substring(url.lastIndexOf(".") + 1);
\r
2288 // Check if we have an image or some other type of file
\r
2289 if (url.substring(0, 5).equalsIgnoreCase("file:")
\r
2290 && mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
2291 handleLocalImageURLPaste(mime, mimeType);
\r
2295 boolean smallEnough = checkFileAttachmentSize(url);
\r
2297 && url.substring(0, 5).equalsIgnoreCase("file:")
\r
2298 && !mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
2299 handleLocalAttachment(mime, mimeType);
\r
2302 browser.page().mainFrame().evaluateJavaScript(
\r
2303 script_start + url + script_end);
\r
2308 // If a URL being pasted is an image URL, then attach the image
\r
2309 private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {
\r
2310 List<QUrl> urlList = mime.urls();
\r
2311 String url = new String();
\r
2312 String script_start_image = new String(
\r
2313 "document.execCommand('insertHtml', false, '");
\r
2314 String script_end = new String("');");
\r
2315 StringBuffer buffer;
\r
2317 // Copy the image over into the resource directory and create a new resource
\r
2318 // record for each url pasted
\r
2319 for (int i = 0; i < urlList.size(); i++) {
\r
2320 url = urlList.get(i).toString();
\r
2322 Resource newRes = createResource(url, i, mimeType, false);
\r
2323 if (newRes == null)
\r
2325 currentNote.getResources().add(newRes);
\r
2326 buffer = new StringBuffer(100);
\r
2328 // Open the file & write the data
\r
2329 String fileName = Global.getFileManager().getResDirPath(newRes.getGuid());
\r
2330 QFile tfile = new QFile(fileName);
\r
2331 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
2332 tfile.write(newRes.getData().getBody());
\r
2334 buffer.append(script_start_image);
\r
2335 buffer.append("<img src=\"" + FileUtils.toForwardSlashedPath(fileName));
\r
2336 // if (mimeType.equalsIgnoreCase("image/jpg"))
\r
2337 // mimeType = "image/jpeg";
\r
2338 buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""
\r
2339 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
2340 +" guid=\"" +newRes.getGuid() +"\""
\r
2341 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
2343 buffer.append(script_end);
\r
2344 browser.page().mainFrame().evaluateJavaScript(buffer.toString());
\r
2350 // If a URL being pasted is a local file URL, then attach the file
\r
2351 private void handleLocalAttachment(QMimeData mime, String mimeType) {
\r
2352 logger.log(logger.EXTREME, "Attaching local file");
\r
2353 List<QUrl> urlList = mime.urls();
\r
2354 String script_start = new String(
\r
2355 "document.execCommand('insertHtml', false, '");
\r
2356 String script_end = new String("');");
\r
2357 StringBuffer buffer;
\r
2359 String[] type = mimeType.split("/");
\r
2360 String icon = findIcon(type[1]);
\r
2361 if (icon.equals("attachment.png"))
\r
2362 icon = findIcon(type[0]);
\r
2363 buffer = new StringBuffer(100);
\r
2365 for (int i = 0; i < urlList.size(); i++) {
\r
2366 String url = urlList.get(i).toString();
\r
2368 // Start building the HTML
\r
2369 if (icon.equals("attachment.png"))
\r
2370 icon = findIcon(url.substring(url.lastIndexOf(".")+1));
\r
2371 String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));
\r
2373 logger.log(logger.EXTREME, "Creating resource ");
\r
2374 Resource newRes = createResource(url, i, mimeType, true);
\r
2375 if (newRes == null)
\r
2377 logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());
\r
2378 currentNote.getResources().add(newRes);
\r
2380 String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();
\r
2381 // If we have a PDF, we need to setup the preview.
\r
2382 if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {
\r
2383 logger.log(logger.EXTREME, "Setting up PDF preview");
\r
2384 if (newRes.getAttributes() != null &&
\r
2385 newRes.getAttributes().getFileName() != null &&
\r
2386 !newRes.getAttributes().getFileName().trim().equals(""))
\r
2387 fileName = newRes.getGuid()+Global.attachmentNameDelimeter+
\r
2388 newRes.getAttributes().getFileName();
\r
2390 fileName = newRes.getGuid()+".pdf";
\r
2391 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
2392 QFile.OpenMode mode = new QFile.OpenMode();
\r
2393 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2395 QDataStream out = new QDataStream(file);
\r
2396 // Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);
\r
2397 QByteArray binData = new QByteArray(newRes.getData().getBody());
\r
2398 // resBinary = null;
\r
2399 out.writeBytes(binData.toByteArray());
\r
2402 PDFPreview pdfPreview = new PDFPreview();
\r
2403 if (pdfPreview.setupPreview(Global.getFileManager().getResDirPath(fileName), "pdf",0)) {
\r
2404 imageURL = file.fileName() + ".png";
\r
2408 logger.log(logger.EXTREME, "Generating link tags");
\r
2409 buffer.delete(0, buffer.length());
\r
2410 buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");
\r
2411 buffer.append(" onContextMenu=\"window.jambi.imageContextMenu('")
\r
2412 .append(Global.getFileManager().getResDirPath(fileName))
\r
2413 .append("');\" ");
\r
2414 buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");
\r
2415 buffer.append("<img src=\"" + imageURL + "\" title=\"" +newRes.getAttributes().getFileName());
\r
2416 buffer.append("\"></img>");
\r
2417 buffer.append("</a>");
\r
2418 browser.page().mainFrame().evaluateJavaScript(
\r
2419 script_start + buffer.toString() + script_end);
\r
2424 private Resource createResource(String url, int sequence, String mime, boolean attachment) {
\r
2425 logger.log(logger.EXTREME, "Inside create resource");
\r
2426 QFile resourceFile;
\r
2427 //These two lines are added to handle odd characters in the name like #. Without it
\r
2428 // toLocalFile() chokes and returns the wrong name.
\r
2429 logger.log(logger.EXTREME, "File URL:" +url);
\r
2430 String whichOS = System.getProperty("os.name");
\r
2431 if (whichOS.contains("Windows"))
\r
2432 url = url.replace("file:///", "");
\r
2434 url = url.replace("file://", "");
\r
2435 String urlTest = new QUrl(url).toLocalFile();
\r
2436 logger.log(logger.EXTREME, "File URL toLocalFile():" +urlTest);
\r
2438 if (!urlTest.equals(""))
\r
2440 // url = url.replace("/", File.separator);
\r
2441 logger.log(logger.EXTREME, "Reading from file to create resource:" +url);
\r
2442 resourceFile = new QFile(url);
\r
2443 resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));
\r
2444 logger.log(logger.EXTREME, "Error opening file "+url.toString() +": "+resourceFile.errorString());
\r
2445 byte[] fileData = resourceFile.readAll().toByteArray();
\r
2446 resourceFile.close();
\r
2447 logger.log(logger.EXTREME, "File Length: " +fileData.length);
\r
2448 if (fileData.length == 0)
\r
2452 logger.log(logger.EXTREME, "Generating MD5");
\r
2453 md = MessageDigest.getInstance("MD5");
\r
2454 md.update(fileData);
\r
2455 byte[] hash = md.digest();
\r
2457 Resource r = new Resource();
\r
2458 Calendar time = new GregorianCalendar();
\r
2459 long prevTime = time.getTimeInMillis();
\r
2460 while (prevTime == time.getTimeInMillis()) {
\r
2461 time = new GregorianCalendar();
\r
2463 r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());
\r
2464 r.setNoteGuid(currentNote.getGuid());
\r
2466 r.setActive(true);
\r
2467 r.setUpdateSequenceNum(0);
\r
2468 r.setWidth((short) 0);
\r
2469 r.setHeight((short) 0);
\r
2470 r.setDuration((short) 0);
\r
2472 Data d = new Data();
\r
2473 d.setBody(fileData);
\r
2474 d.setBodyIsSet(true);
\r
2475 d.setBodyHash(hash);
\r
2476 d.setBodyHashIsSet(true);
\r
2478 d.setSize(fileData.length);
\r
2480 int fileNamePos = url.lastIndexOf(File.separator);
\r
2481 if (fileNamePos == -1)
\r
2482 fileNamePos = url.lastIndexOf("/");
\r
2483 String fileName = url.substring(fileNamePos+1);
\r
2484 ResourceAttributes a = new ResourceAttributes();
\r
2486 a.setAltitudeIsSet(false);
\r
2487 a.setLongitude(0);
\r
2488 a.setLongitudeIsSet(false);
\r
2490 a.setLatitudeIsSet(false);
\r
2491 a.setCameraMake("");
\r
2492 a.setCameraMakeIsSet(false);
\r
2493 a.setCameraModel("");
\r
2494 a.setCameraModelIsSet(false);
\r
2495 a.setAttachment(attachment);
\r
2496 a.setAttachmentIsSet(true);
\r
2497 a.setClientWillIndex(false);
\r
2498 a.setClientWillIndexIsSet(true);
\r
2499 a.setRecoType("");
\r
2500 a.setRecoTypeIsSet(false);
\r
2501 a.setSourceURL(url);
\r
2502 a.setSourceURLIsSet(true);
\r
2503 a.setTimestamp(0);
\r
2504 a.setTimestampIsSet(false);
\r
2505 a.setFileName(fileName);
\r
2506 a.setFileNameIsSet(true);
\r
2507 r.setAttributes(a);
\r
2509 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
2510 logger.log(logger.EXTREME, "Resource created");
\r
2512 } catch (NoSuchAlgorithmException e1) {
\r
2513 e1.printStackTrace();
\r
2519 // find the appropriate icon for an attachment
\r
2520 private String findIcon(String appl) {
\r
2521 appl = appl.toLowerCase();
\r
2522 File f = Global.getFileManager().getImageDirFile(appl + ".png");
\r
2524 return appl+".png";
\r
2525 return "attachment.png";
\r
2530 // Check the file attachment to be sure it isn't over 25 mb
\r
2531 private boolean checkFileAttachmentSize(String url) {
\r
2532 String fileName = url.substring(8);
\r
2533 QFile resourceFile = new QFile(fileName);
\r
2534 resourceFile.open(new QIODevice.OpenMode(
\r
2535 QIODevice.OpenModeFlag.ReadOnly));
\r
2536 long size = resourceFile.size();
\r
2537 resourceFile.close();
\r
2538 size = size / 1024 / 1024;
\r
2539 if (size < 50 && Global.isPremium())
\r
2544 String error = tr("A file attachment may not exceed 25MB.");
\r
2545 QMessageBox.information(this, tr("Attachment Size"), error);
\r
2550 @SuppressWarnings("unused")
\r
2551 private void createdChanged() {
\r
2552 QDateTime dt = new QDateTime();
\r
2553 dt.setDate(createdDate.date());
\r
2554 dt.setTime(createdTime.time());
\r
2555 noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);
\r
2559 @SuppressWarnings("unused")
\r
2560 private void alteredChanged() {
\r
2561 QDateTime dt = new QDateTime();
\r
2562 dt.setDate(alteredDate.date());
\r
2563 dt.setTime(alteredTime.time());
\r
2564 noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);
\r
2567 @SuppressWarnings("unused")
\r
2568 private void subjectDateTimeChanged() {
\r
2569 QDateTime dt = new QDateTime();
\r
2570 dt.setDate(subjectDate.date());
\r
2571 dt.setTime(subjectTime.time());
\r
2572 noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);
\r
2576 @SuppressWarnings("unused")
\r
2577 private void sourceUrlChanged() {
\r
2578 noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());
\r
2581 @SuppressWarnings("unused")
\r
2582 private void authorChanged() {
\r
2583 noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());
\r
2586 @SuppressWarnings("unused")
\r
2587 private void geoBoxChanged() {
\r
2588 int index = geoBox.currentIndex();
\r
2589 geoBox.setCurrentIndex(0);
\r
2591 GeoDialog box = new GeoDialog();
\r
2592 box.setLongitude(currentNote.getAttributes().getLongitude());
\r
2593 box.setLatitude(currentNote.getAttributes().getLatitude());
\r
2594 box.setAltitude(currentNote.getAttributes().getAltitude());
\r
2596 if (!box.okPressed())
\r
2598 double alt = box.getAltitude();
\r
2599 double lat = box.getLatitude();
\r
2600 double lon = box.getLongitude();
\r
2601 if (alt != currentNote.getAttributes().getAltitude() ||
\r
2602 lon != currentNote.getAttributes().getLongitude() ||
\r
2603 lat != currentNote.getAttributes().getLatitude()) {
\r
2604 noteSignal.geoChanged.emit(currentNote.getGuid(), lon, lat, alt);
\r
2605 currentNote.getAttributes().setAltitude(alt);
\r
2606 currentNote.getAttributes().setLongitude(lon);
\r
2607 currentNote.getAttributes().setLatitude(lat);
\r
2612 noteSignal.geoChanged.emit(currentNote.getGuid(), 0.0, 0.0, 0.0);
\r
2613 currentNote.getAttributes().setAltitude(0.0);
\r
2614 currentNote.getAttributes().setLongitude(0.0);
\r
2615 currentNote.getAttributes().setLatitude(0.0);
\r
2618 if (index == 3 || index == 0) {
\r
2619 QDesktopServices.openUrl(new QUrl("http://maps.google.com/maps?z=6&q="+currentNote.getAttributes().getLatitude() +"," +currentNote.getAttributes().getLongitude()));
\r
2623 // ************************************************************
\r
2624 // * User chose to save an attachment. Pares out the request *
\r
2625 // * into a guid & file. Save the result. *
\r
2626 // ************************************************************
\r
2627 public void downloadAttachment(QNetworkRequest request) {
\r
2629 QFileDialog fd = new QFileDialog(this);
\r
2630 fd.setFileMode(FileMode.AnyFile);
\r
2631 fd.setConfirmOverwrite(true);
\r
2632 fd.setWindowTitle(tr("Save File"));
\r
2633 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2634 fd.setDirectory(System.getProperty("user.home"));
\r
2635 String name = request.url().toString();
\r
2637 int pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2639 guid = name.substring(0, pos).replace("nnres://", "");
\r
2640 name = name.substring(pos +Global.attachmentNameDelimeter.length());
\r
2641 fd.selectFile(name);
\r
2642 pos = name.lastIndexOf('.');
\r
2644 String mimeType = "(*." + name.substring(pos + 1)
\r
2645 + ");; All Files (*)";
\r
2646 fd.setFilter(tr(mimeType));
\r
2652 // Strip URL prefix and base dir
\r
2653 guid = guid.replace("nnres://", "")
\r
2654 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2655 guid = guid.replace("file://", "").replace("/", "")
\r
2656 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2658 pos = guid.lastIndexOf('.');
\r
2660 guid = guid.substring(0,pos);
\r
2661 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2662 name = name.replace('\\', '/');
\r
2663 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2664 QFile saveFile = new QFile(fd.selectedFiles().get(0));
\r
2665 QFile.OpenMode mode = new QFile.OpenMode();
\r
2666 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2667 saveFile.open(mode);
\r
2668 QDataStream saveOut = new QDataStream(saveFile);
\r
2669 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2670 saveOut.writeBytes(binData.toByteArray());
\r
2677 // ************************************************************
\r
2678 // * User chose to save an attachment. Pares out the request *
\r
2679 // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!
\r
2680 // ************************************************************
\r
2681 public void downloadImage(QNetworkRequest request) {
\r
2682 QFileDialog fd = new QFileDialog(this);
\r
2683 fd.setFileMode(FileMode.AnyFile);
\r
2684 fd.setConfirmOverwrite(true);
\r
2685 fd.setWindowTitle(tr("Save File"));
\r
2686 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2687 fd.setDirectory(System.getProperty("user.home"));
\r
2688 String name = request.url().toString();
\r
2689 name = name.replace("nnres://", "");
\r
2690 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
\r
2691 name = name.replace(dPath, "");
\r
2692 int pos = name.lastIndexOf('.');
\r
2693 String guid = name;
\r
2695 String mimeType = "(*." + name.substring(pos + 1)
\r
2696 + ");; All Files (*)";
\r
2697 fd.setFilter(tr(mimeType));
\r
2698 guid = guid.substring(0,pos);
\r
2700 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2702 guid = name.substring(0, pos);
\r
2703 fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));
\r
2705 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2706 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2707 String fileName = fd.selectedFiles().get(0);
\r
2708 QFile saveFile = new QFile(fileName);
\r
2709 QFile.OpenMode mode = new QFile.OpenMode();
\r
2710 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2711 saveFile.open(mode);
\r
2712 QDataStream saveOut = new QDataStream(saveFile);
\r
2713 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2714 saveOut.writeBytes(binData.toByteArray());
\r
2720 // *************************************************************
\r
2721 // * decrypt any hidden text. We could do an XML parse, but
\r
2722 // * it is quicker here just to scan for an <img tag & do the fix
\r
2723 // * the manual way
\r
2724 // *************************************************************
\r
2725 private void removeEncryption(String id, String plainText, boolean permanent, String slot) {
\r
2727 plainText = " <table class=\"en-crypt-temp\" slot=\""
\r
2730 +"border=1 width=100%><tbody><tr><td>"
\r
2731 +plainText+"</td></tr></tbody></table>";
\r
2734 String html = browser.page().mainFrame().toHtml();
\r
2735 String text = html;
\r
2736 int imagePos = html.indexOf("<img");
\r
2738 for ( ;imagePos>0; ) {
\r
2739 // Find the end tag
\r
2740 endPos = text.indexOf(">", imagePos);
\r
2741 String tag = text.substring(imagePos-1,endPos);
\r
2742 if (tag.indexOf("id=\""+id+"\"") > -1) {
\r
2743 text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);
\r
2744 QTextCodec codec = QTextCodec.codecForName("UTF-8");
\r
2745 QByteArray unicode = codec.fromUnicode(text);
\r
2746 setContent(unicode);
\r
2750 imagePos = text.indexOf("<img", imagePos+1);
\r
2755 //****************************************************************
\r
2756 //* Focus shortcuts
\r
2757 //****************************************************************
\r
2758 @SuppressWarnings("unused")
\r
2759 private void focusTitle() {
\r
2760 titleLabel.setFocus();
\r
2762 @SuppressWarnings("unused")
\r
2763 private void focusTag() {
\r
2764 tagEdit.setFocus();
\r
2766 @SuppressWarnings("unused")
\r
2767 private void focusNote() {
\r
2768 browser.setFocus();
\r
2770 @SuppressWarnings("unused")
\r
2771 private void focusAuthor() {
\r
2772 authorLabel.setFocus();
\r
2774 @SuppressWarnings("unused")
\r
2775 private void focusUrl() {
\r
2776 urlLabel.setFocus();
\r
2780 //*****************************************************************
\r
2781 //* Set the document background color
\r
2782 //*****************************************************************
\r
2783 public void setBackgroundColor(String color) {
\r
2784 String js = "function changeBackground(color) {"
\r
2785 +"document.body.style.background = color;"
\r
2787 +"changeBackground('" +color+"');";
\r
2788 browser.page().mainFrame().evaluateJavaScript(js);
\r
2793 //****************************************************************
\r
2794 //* MicroFocus changed
\r
2795 //****************************************************************
\r
2796 private void microFocusChanged() {
\r
2797 boldButton.setDown(false);
\r
2798 italicButton.setDown(false);
\r
2799 underlineButton.setDown(false);
\r
2800 browser.openAction.setEnabled(false);
\r
2801 browser.downloadAttachment.setEnabled(false);
\r
2802 browser.downloadImage.setEnabled(false);
\r
2803 browser.rotateImageLeft.setEnabled(false);
\r
2804 browser.rotateImageRight.setEnabled(false);
\r
2805 browser.insertTableAction.setEnabled(true);
\r
2806 browser.deleteTableColumnAction.setEnabled(false);
\r
2807 browser.insertTableRowAction.setEnabled(false);
\r
2808 browser.insertTableColumnAction.setEnabled(false);
\r
2809 browser.deleteTableRowAction.setEnabled(false);
\r
2810 browser.insertLinkAction.setText(tr("Insert Hyperlink"));
\r
2811 insertHyperlink = true;
\r
2812 browser.insertQuickLinkAction.setEnabled(true);
\r
2813 currentHyperlink ="";
\r
2814 insideList = false;
\r
2815 insideTable = false;
\r
2816 insideEncryption = false;
\r
2817 forceTextPaste = false;
\r
2819 String js = new String( "function getCursorPos() {"
\r
2821 +"if (window.getSelection) {"
\r
2822 +" var selObj = window.getSelection();"
\r
2823 +" var selRange = selObj.getRangeAt(0);"
\r
2824 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2825 +" while(workingNode != null) { "
\r
2826 // +" window.jambi.printNode(workingNode.nodeName);"
\r
2827 +" if (workingNode.nodeName=='TABLE') { if (workingNode.getAttribute('class').toLowerCase() == 'en-crypt-temp') window.jambi.insideEncryption(); }"
\r
2828 +" if (workingNode.nodeName=='B') window.jambi.boldActive();"
\r
2829 +" if (workingNode.nodeName=='I') window.jambi.italicActive();"
\r
2830 +" if (workingNode.nodeName=='U') window.jambi.underlineActive();"
\r
2831 +" if (workingNode.nodeName=='UL') window.jambi.setInsideList();"
\r
2832 +" if (workingNode.nodeName=='OL') window.jambi.setInsideList();"
\r
2833 +" if (workingNode.nodeName=='LI') window.jambi.setInsideList();"
\r
2834 +" if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"
\r
2835 +" 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
2836 +" if (workingNode.nodeName=='SPAN') {"
\r
2837 +" if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"
\r
2839 +" workingNode = workingNode.parentNode;"
\r
2842 +"} getCursorPos();");
\r
2843 browser.page().mainFrame().evaluateJavaScript(js);
\r
2846 public void printNode(String n) {
\r
2847 System.out.println("Node Vaule: " +n);
\r
2850 public void insideEncryption() {
\r
2851 insideEncryption = true;
\r
2855 //****************************************************************
\r
2856 //* Insert a table row
\r
2857 //****************************************************************
\r
2858 public void insertTableRow() {
\r
2860 String js = new String( "function insertTableRow() {"
\r
2861 +" var selObj = window.getSelection();"
\r
2862 +" var selRange = selObj.getRangeAt(0);"
\r
2863 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2864 +" var cellCount = 0;"
\r
2865 +" while(workingNode != null) { "
\r
2866 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2867 +" row = document.createElement('TR');"
\r
2868 +" var nodes = workingNode.getElementsByTagName('td');"
\r
2869 +" for (j=0; j<nodes.length; j=j+1) {"
\r
2870 +" cell = document.createElement('TD');"
\r
2871 +" cell.innerHTML=' ';"
\r
2872 +" row.appendChild(cell);"
\r
2874 +" workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"
\r
2877 +" workingNode = workingNode.parentNode;"
\r
2879 +"} insertTableRow();");
\r
2880 browser.page().mainFrame().evaluateJavaScript(js);
\r
2884 public void insertTableColumn() {
\r
2885 String js = new String( "function insertTableColumn() {"
\r
2886 +" var selObj = window.getSelection();"
\r
2887 +" var selRange = selObj.getRangeAt(0);"
\r
2888 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2889 +" var current = 0;"
\r
2890 +" while (workingNode.nodeName.toLowerCase() != 'table' && workingNode != null) {"
\r
2891 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
2892 +" var td = workingNode;"
\r
2893 +" while (td.previousSibling != null) { "
\r
2894 +" current = current+1; td = td.previousSibling;"
\r
2897 +" workingNode = workingNode.parentNode; "
\r
2899 +" if (workingNode == null) return;"
\r
2900 +" for (var i=0; i<workingNode.rows.length; i++) { "
\r
2901 +" var cell = workingNode.rows[i].insertCell(current+1); "
\r
2902 +" cell.innerHTML = ' '; "
\r
2904 +"} insertTableColumn();");
\r
2905 browser.page().mainFrame().evaluateJavaScript(js);
\r
2909 //****************************************************************
\r
2910 //* Delete a table row
\r
2911 //****************************************************************
\r
2912 public void deleteTableRow() {
\r
2914 String js = new String( "function deleteTableRow() {"
\r
2915 +" var selObj = window.getSelection();"
\r
2916 +" var selRange = selObj.getRangeAt(0);"
\r
2917 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2918 +" var cellCount = 0;"
\r
2919 +" while(workingNode != null) { "
\r
2920 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2921 +" workingNode.parentNode.removeChild(workingNode);"
\r
2924 +" workingNode = workingNode.parentNode;"
\r
2926 +"} deleteTableRow();");
\r
2927 browser.page().mainFrame().evaluateJavaScript(js);
\r
2931 public void deleteTableColumn() {
\r
2932 String js = new String( "function deleteTableColumn() {"
\r
2933 +" var selObj = window.getSelection();"
\r
2934 +" var selRange = selObj.getRangeAt(0);"
\r
2935 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2936 +" var current = 0;"
\r
2937 +" while (workingNode.nodeName.toLowerCase() != 'table' && workingNode != null) {"
\r
2938 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
2939 +" var td = workingNode;"
\r
2940 +" while (td.previousSibling != null) { "
\r
2941 +" current = current+1; td = td.previousSibling;"
\r
2944 +" workingNode = workingNode.parentNode; "
\r
2946 +" if (workingNode == null) return;"
\r
2947 +" for (var i=0; i<workingNode.rows.length; i++) { "
\r
2948 +" workingNode.rows[i].deleteCell(current); "
\r
2950 +"} deleteTableColumn();");
\r
2951 browser.page().mainFrame().evaluateJavaScript(js);
\r
2956 public void setInsideTable() {
\r
2957 browser.insertTableRowAction.setEnabled(true);
\r
2958 browser.insertTableColumnAction.setEnabled(true);
\r
2959 browser.deleteTableRowAction.setEnabled(true);
\r
2960 browser.deleteTableColumnAction.setEnabled(true);
\r
2961 browser.insertTableAction.setEnabled(false);
\r
2962 browser.encryptAction.setEnabled(false);
\r
2963 insideTable = true;
\r
2966 public void setInsideLink(String link) {
\r
2967 browser.insertLinkAction.setText(tr("Edit Hyperlink"));
\r
2968 currentHyperlink = link;
\r
2969 insertHyperlink = false;
\r
2972 public void italicActive() {
\r
2973 italicButton.setDown(true);
\r
2975 public void boldActive() {
\r
2976 boldButton.setDown(true);
\r
2978 public void underlineActive() {
\r
2979 underlineButton.setDown(true);
\r
2981 public void forceTextPaste() {
\r
2982 forceTextPaste = true;
\r
2984 public void imageContextMenu(String f) {
\r
2985 browser.downloadImage.setEnabled(true);
\r
2986 browser.rotateImageRight.setEnabled(true);
\r
2987 browser.rotateImageLeft.setEnabled(true);
\r
2988 browser.openAction.setEnabled(true);
\r
2991 public void rotateImageRight() {
\r
2992 QWebSettings.setMaximumPagesInCache(0);
\r
2993 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2994 QImage image = new QImage(selectedFile);
\r
2995 QMatrix matrix = new QMatrix();
\r
2996 matrix.rotate( 90.0 );
\r
2997 image = image.transformed(matrix);
\r
2998 image.save(selectedFile);
\r
2999 QWebSettings.setMaximumPagesInCache(0);
\r
3000 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
3001 browser.setHtml(browser.page().mainFrame().toHtml());
\r
3004 resourceSignal.contentChanged.emit(selectedFile);
\r
3007 public void rotateImageLeft() {
\r
3008 QImage image = new QImage(selectedFile);
\r
3009 QMatrix matrix = new QMatrix();
\r
3010 matrix.rotate( -90.0 );
\r
3011 image = image.transformed(matrix);
\r
3012 image.save(selectedFile);
\r
3013 browser.setHtml(browser.page().mainFrame().toHtml());
\r
3016 resourceSignal.contentChanged.emit(selectedFile);
\r
3018 public void resourceContextMenu(String f) {
\r
3019 browser.downloadAttachment.setEnabled(true);
\r
3020 browser.openAction.setEnabled(true);
\r
3023 public void latexContextMenu(String f) {
\r
3024 browser.downloadImage.setEnabled(true);
\r
3025 browser.rotateImageRight.setEnabled(true);
\r
3026 browser.rotateImageLeft.setEnabled(true);
\r
3027 browser.openAction.setEnabled(true);
\r
3031 //****************************************************************
\r
3032 //* Apply CSS style to specified word
\r
3033 //****************************************************************
\r
3034 /* public void applyStyleToWords(String word, String style) {
\r
3035 QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");
\r
3036 script.open(OpenModeFlag.ReadOnly);
\r
3037 String s = script.readAll().toString();
\r
3038 String js = new String(s +" findit('"+word+"', '"+style+"');");
\r
3039 browser.page().mainFrame().evaluateJavaScript(js);
\r
3040 System.out.println(getContent());
\r
3043 //****************************************************************
\r
3044 //* Someone tried to paste a resource between notes, so we need *
\r
3045 //* to do some special handling. *
\r
3046 //****************************************************************
\r
3047 private String fixInternotePaste(String text) {
\r
3048 logger.log(logger.EXTREME, "Fixing internote paste");
\r
3049 String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");
\r
3050 return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");
\r
3052 private String fixInternotePasteSearch(String text, String type, String locTag) {
\r
3054 // First, let's fix the images.
\r
3055 int startPos = text.indexOf(type);
\r
3057 for (; startPos>=0;) {
\r
3058 endPos = text.indexOf(">", startPos+1);
\r
3059 String segment = text.substring(startPos, endPos);
\r
3060 if (segment.indexOf("en-tag") > -1) {
\r
3061 String newSegment = segment;
\r
3063 int guidStartPos = segment.indexOf("guid=\"");
\r
3064 int guidEndPos = segment.indexOf("\"", guidStartPos+7);
\r
3065 String guid = segment.substring(guidStartPos+6,guidEndPos);
\r
3067 int mimeStartPos = segment.indexOf("type");
\r
3068 int mimeEndPos = segment.indexOf("\"", mimeStartPos+7);
\r
3069 String mime = segment.substring(mimeStartPos+6,mimeEndPos);
\r
3071 int srcStartPos = segment.indexOf("src");
\r
3072 int srcEndPos = segment.indexOf("\"", srcStartPos+6);
\r
3073 String src = segment.substring(srcStartPos+5,srcEndPos);
\r
3075 Calendar currentTime = new GregorianCalendar();
\r
3076 Long l = new Long(currentTime.getTimeInMillis());
\r
3077 long prevTime = l;
\r
3078 while (l==prevTime) {
\r
3079 currentTime = new GregorianCalendar();
\r
3080 l= new Long(currentTime.getTimeInMillis());
\r
3083 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
3084 // if r==null, then the image doesn't exist (it was probably cut out of another note, so
\r
3085 // we need to recereate it
\r
3087 r = createResource(src, 1, mime, false);
\r
3091 String randint = new String(Long.toString(l));
\r
3092 String extension = null;
\r
3093 if (r.getMime()!= null) {
\r
3094 extension = r.getMime().toLowerCase();
\r
3095 if (extension.indexOf("/")>-1)
\r
3096 extension = extension.substring(extension.indexOf("/")+1);
\r
3098 String newFile = randint;
\r
3099 if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")
\r
3100 if (!locTag.startsWith("src"))
\r
3101 newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();
\r
3102 r.setNoteGuid(currentNote.getGuid());
\r
3104 r.setGuid(randint);
\r
3105 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
3106 QFile f = new QFile(Global.getFileManager().getResDirPath(newFile));
\r
3107 QByteArray bin = new QByteArray(r.getData().getBody());
\r
3108 f.open(QFile.OpenModeFlag.WriteOnly);
\r
3111 newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);
\r
3112 currentNote.getResources().add(r);
\r
3114 int startSrcPos = newSegment.indexOf(locTag);
\r
3115 int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);
\r
3117 if (locTag.startsWith("src")) {
\r
3118 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
3119 newSegment = newSegment.replace(source,
\r
3120 FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath(newFile)));
\r
3122 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
3123 newSegment = newSegment.replace(source, newFile);
\r
3126 text = text.substring(0,startPos) + newSegment + text.substring(endPos);
\r
3128 startPos = text.indexOf(type, startPos+1);
\r
3134 public void nextPage(String file) {
\r
3135 logger.log(logger.EXTREME, "Starting nextPage()");
\r
3137 Integer pageNumber;
\r
3138 if (previewPageList.containsKey(file))
\r
3139 pageNumber = previewPageList.get(file)+1;
\r
3142 previewPageList.remove(file);
\r
3143 previewPageList.put(file, pageNumber);
\r
3144 PDFPreview pdfPreview = new PDFPreview();
\r
3145 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
3146 if (goodPreview) {
\r
3148 // String html = getContent();
\r
3149 QWebSettings.setMaximumPagesInCache(0);
\r
3150 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
3151 // browser.setContent(new QByteArray());
\r
3152 browser.setHtml(browser.page().mainFrame().toHtml());
\r
3154 // browser.setContent(new QByteArray(html));
\r
3155 // browser.triggerPageAction(WebAction.Reload);
\r
3156 // pdfMouseOver(selectedFile);
\r
3160 public void previousPage(String file) {
\r
3161 logger.log(logger.EXTREME, "Starting previousPage()");
\r
3163 Integer pageNumber;
\r
3164 if (previewPageList.containsKey(file))
\r
3165 pageNumber = previewPageList.get(file)-1;
\r
3168 previewPageList.remove(file);
\r
3169 previewPageList.put(file, pageNumber);
\r
3170 PDFPreview pdfPreview = new PDFPreview();
\r
3171 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
3172 if (goodPreview) {
\r
3174 // String html = getContent();
\r
3175 QWebSettings.setMaximumPagesInCache(0);
\r
3176 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
3177 browser.setHtml(browser.page().mainFrame().toHtml());
\r
3179 // browser.setContent(new QByteArray(html));
\r
3180 // browser.triggerPageAction(WebAction.Reload);
\r
3184 /* public void pdfMouseOver(String name) {
\r
3186 if (previewPageList.containsKey(selectedFile))
\r
3187 pageNumber = previewPageList.get(selectedFile)+1;
\r
3191 if (pageNumber <= 1)
\r
3192 browser.previousPageAction.setEnabled(false);
\r
3194 browser.previousPageAction.setEnabled(true);
\r
3196 PDFPreview pdf = new PDFPreview();
\r
3197 int totalPages = pdf.getPageCount(name);
\r
3198 if (previewPageList.containsKey(selectedFile))
\r
3199 pageNumber = previewPageList.get(selectedFile)+1;
\r
3202 if (totalPages > pageNumber)
\r
3203 browser.nextPageAction.setEnabled(true);
\r
3205 browser.nextPageAction.setEnabled(false);
\r
3209 public void pdfMouseOut() {
\r
3210 // browser.nextPageAction.setVisible(false);
\r
3211 // browser.previousPageAction.setVisible(false);
\r
3215 @SuppressWarnings("unused")
\r
3216 private void toggleUndoVisible(Boolean toggle) {
\r
3217 undoAction.setVisible(toggle);
\r
3218 Global.saveEditorButtonsVisible("undo", toggle);
\r
3220 @SuppressWarnings("unused")
\r
3221 private void toggleRedoVisible(Boolean toggle) {
\r
3222 redoAction.setVisible(toggle);
\r
3223 Global.saveEditorButtonsVisible("redo", toggle);
\r
3225 @SuppressWarnings("unused")
\r
3226 private void toggleCutVisible(Boolean toggle) {
\r
3227 cutAction.setVisible(toggle);
\r
3228 Global.saveEditorButtonsVisible("cut", toggle);
\r
3230 @SuppressWarnings("unused")
\r
3231 private void toggleCopyVisible(Boolean toggle) {
\r
3232 copyAction.setVisible(toggle);
\r
3233 Global.saveEditorButtonsVisible("copy", toggle);
\r
3235 @SuppressWarnings("unused")
\r
3236 private void togglePasteVisible(Boolean toggle) {
\r
3237 pasteAction.setVisible(toggle);
\r
3238 Global.saveEditorButtonsVisible("paste", toggle);
\r
3240 @SuppressWarnings("unused")
\r
3241 private void toggleBoldVisible(Boolean toggle) {
\r
3242 boldAction.setVisible(toggle);
\r
3243 Global.saveEditorButtonsVisible("bold", toggle);
\r
3245 @SuppressWarnings("unused")
\r
3246 private void toggleItalicVisible(Boolean toggle) {
\r
3247 italicAction.setVisible(toggle);
\r
3248 Global.saveEditorButtonsVisible("italic", toggle);
\r
3250 @SuppressWarnings("unused")
\r
3251 private void toggleUnderlineVisible(Boolean toggle) {
\r
3252 underlineAction.setVisible(toggle);
\r
3253 Global.saveEditorButtonsVisible("underline", toggle);
\r
3255 @SuppressWarnings("unused")
\r
3256 private void toggleStrikethroughVisible(Boolean toggle) {
\r
3257 strikethroughAction.setVisible(toggle);
\r
3258 Global.saveEditorButtonsVisible("strikethrough", toggle);
\r
3260 @SuppressWarnings("unused")
\r
3261 private void toggleLeftAlignVisible(Boolean toggle) {
\r
3262 leftAlignAction.setVisible(toggle);
\r
3263 Global.saveEditorButtonsVisible("alignLeft", toggle);
\r
3265 @SuppressWarnings("unused")
\r
3266 private void toggleRightAlignVisible(Boolean toggle) {
\r
3267 rightAlignAction.setVisible(toggle);
\r
3268 Global.saveEditorButtonsVisible("alignRight", toggle);
\r
3270 @SuppressWarnings("unused")
\r
3271 private void toggleCenterAlignVisible(Boolean toggle) {
\r
3272 centerAlignAction.setVisible(toggle);
\r
3273 Global.saveEditorButtonsVisible("alignCenter", toggle);
\r
3275 @SuppressWarnings("unused")
\r
3276 private void toggleHLineVisible(Boolean toggle) {
\r
3277 hlineAction.setVisible(toggle);
\r
3278 Global.saveEditorButtonsVisible("hline", toggle);
\r
3280 @SuppressWarnings("unused")
\r
3281 private void toggleIndentVisible(Boolean toggle) {
\r
3282 indentAction.setVisible(toggle);
\r
3283 Global.saveEditorButtonsVisible("indent", toggle);
\r
3285 @SuppressWarnings("unused")
\r
3286 private void toggleTodoVisible(Boolean toggle) {
\r
3287 todoAction.setVisible(toggle);
\r
3288 Global.saveEditorButtonsVisible("todo", toggle);
\r
3290 @SuppressWarnings("unused")
\r
3291 private void toggleOutdentVisible(Boolean toggle) {
\r
3292 outdentAction.setVisible(toggle);
\r
3293 Global.saveEditorButtonsVisible("outdent", toggle);
\r
3295 @SuppressWarnings("unused")
\r
3296 private void toggleBulletListVisible(Boolean toggle) {
\r
3297 bulletListAction.setVisible(toggle);
\r
3298 Global.saveEditorButtonsVisible("bulletList", toggle);
\r
3300 @SuppressWarnings("unused")
\r
3301 private void toggleNumberListVisible(Boolean toggle) {
\r
3302 numberListAction.setVisible(toggle);
\r
3303 Global.saveEditorButtonsVisible("numberList", toggle);
\r
3305 @SuppressWarnings("unused")
\r
3306 private void toggleFontListVisible(Boolean toggle) {
\r
3307 fontListAction.setVisible(toggle);
\r
3308 Global.saveEditorButtonsVisible("font", toggle);
\r
3310 @SuppressWarnings("unused")
\r
3311 private void toggleFontColorVisible(Boolean toggle) {
\r
3312 fontColorAction.setVisible(toggle);
\r
3313 Global.saveEditorButtonsVisible("fontColor", toggle);
\r
3315 @SuppressWarnings("unused")
\r
3316 private void toggleFontSizeVisible(Boolean toggle) {
\r
3317 fontSizeAction.setVisible(toggle);
\r
3318 Global.saveEditorButtonsVisible("fontSize", toggle);
\r
3320 @SuppressWarnings("unused")
\r
3321 private void toggleFontHilightVisible(Boolean toggle) {
\r
3322 fontHilightAction.setVisible(toggle);
\r
3323 Global.saveEditorButtonsVisible("fontHilight", toggle);
\r
3325 @SuppressWarnings("unused")
\r
3326 private void toggleSpellCheckVisible(Boolean toggle) {
\r
3327 spellCheckAction.setVisible(toggle);
\r
3328 Global.saveEditorButtonsVisible("spellCheck", toggle);
\r
3332 private void setupDictionary() {
\r
3333 File wordList = new File(Global.getFileManager().getSpellDirPath()+Locale.getDefault()+".dic");
\r
3335 dictionary = new SpellDictionaryHashMap(wordList);
\r
3336 spellChecker = new SpellChecker(dictionary);
\r
3338 File userWordList;
\r
3339 userWordList = new File(Global.getFileManager().getSpellDirPathUser()+"user.dic");
\r
3341 // Get the local user spell dictionary
\r
3343 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
3344 } catch (FileNotFoundException e) {
\r
3345 userWordList.createNewFile();
\r
3346 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
3347 } catch (IOException e) {
\r
3348 userWordList.createNewFile();
\r
3349 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
3352 spellListener = new SuggestionListener(this, spellChecker);
\r
3354 // Add the user dictionary
\r
3355 spellChecker.addSpellCheckListener(spellListener);
\r
3356 spellChecker.setUserDictionary(userDictionary);
\r
3358 } catch (FileNotFoundException e) {
\r
3359 QMessageBox.critical(this, tr("Spell Check Error"),
\r
3360 tr("Dictionary ")+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
3361 tr(".dic was not found."));
\r
3362 } catch (IOException e) {
\r
3363 QMessageBox.critical(this, tr("Spell Check Error"),
\r
3364 tr("Dictionary ")+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
3365 tr(".dic is invalid."));
\r
3370 // Invoke spell checker dialog
\r
3371 @SuppressWarnings("unused")
\r
3372 private void spellCheckClicked() {
\r
3374 if (spellChecker == null) {
\r
3375 setupDictionary();
\r
3378 // Read user settings
\r
3379 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREDIGITWORDS,
\r
3380 Global.getSpellSetting(Configuration.SPELL_IGNOREDIGITWORDS));
\r
3381 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREINTERNETADDRESSES,
\r
3382 Global.getSpellSetting(Configuration.SPELL_IGNOREINTERNETADDRESSES));
\r
3383 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREMIXEDCASE,
\r
3384 Global.getSpellSetting(Configuration.SPELL_IGNOREMIXEDCASE));
\r
3385 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREUPPERCASE,
\r
3386 Global.getSpellSetting(Configuration.SPELL_IGNOREUPPERCASE));
\r
3387 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNORESENTENCECAPITALIZATION,
\r
3388 Global.getSpellSetting(Configuration.SPELL_IGNORESENTENCECAPITALIZATION));
\r
3390 spellListener.abortSpellCheck = false;
\r
3391 spellListener.errorsFound = false;
\r
3392 String content = getBrowser().page().mainFrame().toPlainText();
\r
3393 StringWordTokenizer tokenizer = new StringWordTokenizer(content);
\r
3394 if (!tokenizer.hasMoreWords())
\r
3396 getBrowser().page().action(WebAction.MoveToStartOfDocument);
\r
3398 getBrowser().setFocus();
\r
3401 // Move to the start of page
\r
3402 KeyboardModifiers ctrl = new KeyboardModifiers(KeyboardModifier.ControlModifier.value());
\r
3403 QKeyEvent home = new QKeyEvent(Type.KeyPress, Key.Key_Home.value(), ctrl);
\r
3404 browser.keyPressEvent(home);
\r
3405 getBrowser().setFocus();
\r
3407 tokenizer = new StringWordTokenizer(content);
\r
3410 while(tokenizer.hasMoreWords()) {
\r
3411 word = tokenizer.nextWord();
\r
3412 found = getBrowser().page().findText(word);
\r
3413 if (found && !spellListener.abortSpellCheck) {
\r
3414 spellChecker.checkSpelling(new StringWordTokenizer(word));
\r
3415 getBrowser().setFocus();
\r
3419 // Go to the end of the document & finish up.
\r
3420 home = new QKeyEvent(Type.KeyPress, Key.Key_End.value(), ctrl);
\r
3421 browser.keyPressEvent(home);
\r
3422 if (!spellListener.errorsFound)
\r
3423 QMessageBox.information(this, tr("Spell Check Complete"),
\r
3424 tr("No Errors Found"));
\r
3429 @SuppressWarnings("unused")
\r
3430 private void sourceEdited() {
\r
3431 QTextCodec codec = QTextCodec.codecForLocale();
\r
3432 codec = QTextCodec.codecForName("UTF-8");
\r
3433 String content = codec.fromUnicode(sourceEdit.toHtml()).toString();
\r
3434 content = StringEscapeUtils.unescapeHtml4(removeTags(content));
\r
3435 QByteArray data = new QByteArray(sourceEditHeader+content+"</body></html>");
\r
3436 getBrowser().setContent(data);
\r
3438 if (currentNote != null && sourceEdit != null)
\r
3439 noteSignal.noteChanged.emit(currentNote.getGuid(), sourceEdit.toPlainText());
\r
3442 private void setSource() {
\r
3443 String text = getContent();
\r
3444 sourceEdit.blockSignals(true);
\r
3445 int body = text.indexOf("<body");
\r
3447 body = text.indexOf(">",body);
\r
3449 sourceEditHeader =text.substring(0, body+1);
\r
3450 text = text.substring(body+1);
\r
3453 text = text.replace("</body></html>", "");
\r
3454 sourceEdit.setPlainText(text);
\r
3455 sourceEdit.setReadOnly(!getBrowser().page().isContentEditable());
\r
3456 //syntaxHighlighter.rehighlight();
\r
3457 sourceEdit.blockSignals(false);
\r
3460 // show/hide view source window
\r
3461 public void showSource(boolean value) {
\r
3463 sourceEdit.setVisible(value);
\r
3466 // Remove HTML tags
\r
3467 private String removeTags(String text) {
\r
3468 StringBuffer buffer = new StringBuffer(text);
\r
3469 boolean inTag = false;
\r
3470 int bodyPosition = text.indexOf("<body");
\r
3471 for (int i=buffer.length()-1; i>=0; i--) {
\r
3472 if (buffer.charAt(i) == '>')
\r
3474 if (buffer.charAt(i) == '<')
\r
3476 if (inTag || buffer.charAt(i) == '<' || i<bodyPosition)
\r
3477 buffer.deleteCharAt(i);
\r
3480 return buffer.toString();
\r