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 // String x = mime.html();
\r
1105 if (mime.hasImage()) {
\r
1106 logger.log(logger.EXTREME, "Image paste found");
\r
1107 browser.setFocus();
\r
1108 insertImage(mime);
\r
1109 browser.setFocus();
\r
1113 if (mime.hasUrls()) {
\r
1114 logger.log(logger.EXTREME, "URL paste found");
\r
1115 if (!mime.text().startsWith("evernote:")) {
\r
1116 handleNoteLink(mime);
\r
1119 browser.setFocus();
\r
1124 String text = mime.html();
\r
1125 if (text.contains("en-tag") && mime.hasHtml()) {
\r
1126 logger.log(logger.EXTREME, "Intra-note paste found");
\r
1127 text = fixInternotePaste(text);
\r
1128 mime.setHtml(text);
\r
1129 clipboard.setMimeData(mime);
\r
1132 logger.log(logger.EXTREME, "Final paste choice encountered");
\r
1133 browser.page().triggerAction(WebAction.Paste);
\r
1134 browser.setFocus();
\r
1138 // Paste text without formatting
\r
1139 private void pasteWithoutFormattingClicked() {
\r
1140 logger.log(logger.EXTREME, "Paste without format clipped");
\r
1141 QClipboard clipboard = QApplication.clipboard();
\r
1142 QMimeData mime = clipboard.mimeData();
\r
1143 if (!mime.hasText())
\r
1145 String text = mime.text();
\r
1146 clipboard.clear();
\r
1147 clipboard.setText(text, Mode.Clipboard);
\r
1148 browser.page().triggerAction(WebAction.Paste);
\r
1150 // This is done because pasting into an encryption block
\r
1151 // can cause multiple cells (which can't happen). It
\r
1152 // just goes through the table, extracts the data, &
\r
1153 // puts it back as one table cell.
\r
1154 if (insideEncryption) {
\r
1155 String js = new String( "function fixEncryption() { "
\r
1156 +" var selObj = window.getSelection();"
\r
1157 +" var selRange = selObj.getRangeAt(0);"
\r
1158 +" var workingNode = window.getSelection().anchorNode;"
\r
1159 +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
\r
1160 +" workingNode = workingNode.parentNode;"
\r
1162 +" workingNode.innerHTML = window.jambi.fixEncryptionPaste(workingNode.innerHTML);"
\r
1163 +"} fixEncryption();");
\r
1164 browser.page().mainFrame().evaluateJavaScript(js);
\r
1168 // This basically removes all the table tags and returns just the contents.
\r
1169 // This is called by JavaScript to fix encryption pastes.
\r
1170 public String fixEncryptionPaste(String data) {
\r
1171 data = data.replace("<tbody>", "");
\r
1172 data = data.replace("</tbody>", "");
\r
1173 data = data.replace("<tr>", "");
\r
1174 data = data.replace("</tr>", "");
\r
1175 data = data.replace("<td>", "");
\r
1176 data = data.replace("</td>", "<br>");
\r
1177 data = data.replace("<br><br>", "<br>");
\r
1179 return "<tbody><tr><td>"+data+"</td></tr></tbody>";
\r
1182 // insert date/time
\r
1183 @SuppressWarnings("unused")
\r
1184 private void insertDateTime() {
\r
1185 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
\r
1186 String dateTimeFormat = new String(fmt);
\r
1187 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
\r
1188 Calendar cal = Calendar.getInstance();
\r
1190 browser.page().mainFrame().evaluateJavaScript(
\r
1191 "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");
\r
1193 browser.setFocus();
\r
1197 // Listener when Left is clicked
\r
1198 @SuppressWarnings("unused")
\r
1199 private void justifyLeftClicked() {
\r
1200 browser.page().mainFrame().evaluateJavaScript(
\r
1201 "document.execCommand('JustifyLeft', false, '');");
\r
1202 browser.setFocus();
\r
1205 // Listener when Center is clicked
\r
1206 @SuppressWarnings("unused")
\r
1207 private void justifyCenterClicked() {
\r
1208 browser.page().mainFrame().evaluateJavaScript(
\r
1209 "document.execCommand('JustifyCenter', false, '');");
\r
1210 browser.setFocus();
\r
1213 // Listener when Left is clicked
\r
1214 @SuppressWarnings("unused")
\r
1215 private void justifyRightClicked() {
\r
1216 browser.page().mainFrame().evaluateJavaScript(
\r
1217 "document.execCommand('JustifyRight', false, '');");
\r
1218 browser.setFocus();
\r
1221 // Listener when HLINE is clicked
\r
1222 @SuppressWarnings("unused")
\r
1223 private void hlineClicked() {
\r
1224 browser.page().mainFrame().evaluateJavaScript(
\r
1225 "document.execCommand('insertHorizontalRule', false, '');");
\r
1226 browser.setFocus();
\r
1229 // Listener when outdent is clicked
\r
1230 private void outdentClicked() {
\r
1231 browser.page().mainFrame().evaluateJavaScript(
\r
1232 "document.execCommand('outdent', false, '');");
\r
1233 browser.setFocus();
\r
1236 // Listener when a bullet list is clicked
\r
1237 @SuppressWarnings("unused")
\r
1238 private void bulletListClicked() {
\r
1239 browser.page().mainFrame().evaluateJavaScript(
\r
1240 "document.execCommand('InsertUnorderedList', false, '');");
\r
1241 browser.setFocus();
\r
1244 // Listener when a bullet list is clicked
\r
1245 @SuppressWarnings("unused")
\r
1246 private void numberListClicked() {
\r
1247 browser.page().mainFrame().evaluateJavaScript(
\r
1248 "document.execCommand('InsertOrderedList', false, '');");
\r
1249 browser.setFocus();
\r
1252 // Listener when indent is clicked
\r
1253 private void indentClicked() {
\r
1254 browser.page().mainFrame().evaluateJavaScript(
\r
1255 "document.execCommand('indent', false, '');");
\r
1256 browser.setFocus();
\r
1259 // Listener when the font name is changed
\r
1260 @SuppressWarnings("unused")
\r
1261 private void fontChanged(String font) {
\r
1262 browser.page().mainFrame().evaluateJavaScript(
\r
1263 "document.execCommand('fontName',false,'" + font + "');");
\r
1264 browser.setFocus();
\r
1267 // Listener when a font size is changed
\r
1268 @SuppressWarnings("unused")
\r
1269 private void fontSizeChanged(String font) {
\r
1270 String text = browser.selectedText();
\r
1271 if (text.trim().equalsIgnoreCase(""))
\r
1274 String selectedText = browser.selectedText();
\r
1275 String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";
\r
1276 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1277 browser.page().mainFrame().evaluateJavaScript(script);
\r
1278 /* browser.page().mainFrame().evaluateJavaScript(
\r
1279 "document.execCommand('fontSize',false,'"
\r
1282 browser.setFocus();
\r
1285 // Load the font combo box based upon the font selected
\r
1286 private void loadFontSize(String name) {
\r
1287 QFontDatabase db = new QFontDatabase();
\r
1289 List<Integer> points = db.pointSizes(name);
\r
1290 for (int i=0; i<points.size(); i++) {
\r
1291 fontSize.addItem(points.get(i).toString());
\r
1294 fontSize.addItem("x-small");
\r
1295 fontSize.addItem("small");
\r
1296 fontSize.addItem("medium");
\r
1297 fontSize.addItem("large");
\r
1298 fontSize.addItem("x-large");
\r
1299 fontSize.addItem("xx-large");
\r
1300 fontSize.addItem("xxx-large");
\r
1304 // Listener when a font size is changed
\r
1305 @SuppressWarnings("unused")
\r
1306 private void fontColorClicked() {
\r
1307 // QColorDialog dialog = new QColorDialog();
\r
1308 // QColor color = QColorDialog.getColor();
\r
1309 QColor color = fontColorMenu.getColor();
\r
1310 if (color.isValid())
\r
1311 browser.page().mainFrame().evaluateJavaScript(
\r
1312 "document.execCommand('foreColor',false,'" + color.name()
\r
1314 browser.setFocus();
\r
1317 // Listener for when a background color change is requested
\r
1318 @SuppressWarnings("unused")
\r
1319 private void fontHilightClicked() {
\r
1320 // QColorDialog dialog = new QColorDialog();
\r
1321 // QColor color = QColorDialog.getColor();
\r
1322 QColor color = fontHilightColorMenu.getColor();
\r
1323 if (color.isValid())
\r
1324 browser.page().mainFrame().evaluateJavaScript(
\r
1325 "document.execCommand('backColor',false,'" + color.name()
\r
1327 browser.setFocus();
\r
1330 // Listener for when a background color change is requested
\r
1331 @SuppressWarnings("unused")
\r
1332 private void superscriptClicked() {
\r
1333 browser.page().mainFrame().evaluateJavaScript(
\r
1334 "document.execCommand('superscript');");
\r
1335 browser.setFocus();
\r
1338 // Listener for when a background color change is requested
\r
1339 @SuppressWarnings("unused")
\r
1340 private void subscriptClicked() {
\r
1341 browser.page().mainFrame().evaluateJavaScript(
\r
1342 "document.execCommand('subscript');");
\r
1343 browser.setFocus();
\r
1345 // Insert a to-do checkbox
\r
1346 @SuppressWarnings("unused")
\r
1347 private void todoClicked() {
\r
1348 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1349 String script_start = new String(
\r
1350 "document.execCommand('insertHtml', false, '");
\r
1351 String script_end = new String("');");
\r
1352 String todo = new String(
\r
1353 "<input TYPE=\"CHECKBOX\" value=\"false\" " +
\r
1354 "onMouseOver=\"style.cursor=\\'hand\\'\" " +
\r
1355 "onClick=\"value=checked; window.jambi.contentChanged(); \" />");
\r
1356 browser.page().mainFrame().evaluateJavaScript(
\r
1357 script_start + todo + script_end);
\r
1358 browser.setFocus();
\r
1361 // Encrypt the selected text
\r
1362 @SuppressWarnings("unused")
\r
1363 private void encryptText() {
\r
1364 String text = browser.selectedText();
\r
1365 if (text.trim().equalsIgnoreCase(""))
\r
1367 text = new String(text.replaceAll("\n", "<br/>"));
\r
1369 EnCryptDialog dialog = new EnCryptDialog();
\r
1371 if (!dialog.okPressed()) {
\r
1375 EnCrypt crypt = new EnCrypt();
\r
1376 String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);
\r
1377 String decrypted = crypt.decrypt(encrypted, dialog.getPassword().trim(), 64);
\r
1379 if (encrypted.trim().equals("")) {
\r
1380 QMessageBox.information(this, tr("Error"), tr("Error Encrypting String"));
\r
1383 StringBuffer buffer = new StringBuffer(encrypted.length() + 100);
\r
1384 buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""
\r
1385 + dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");
\r
1386 buffer.append("contentEditable=\"false\" alt=\"");
\r
1387 buffer.append(encrypted);
\r
1388 buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png") +"\""));
\r
1389 Global.cryptCounter++;
\r
1390 buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");
\r
1391 buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");
\r
1392 buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString()
\r
1393 +"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&apos;")+"\\');\"");
\r
1394 buffer.append("style=\"display:block\" />");
\r
1396 String script_start = new String(
\r
1397 "document.execCommand('insertHtml', false, '");
\r
1398 String script_end = new String("');");
\r
1399 browser.page().mainFrame().evaluateJavaScript(
\r
1400 script_start + buffer.toString() + script_end);
\r
1404 // Insert a Quick hyperlink
\r
1405 public void insertQuickLink() {
\r
1406 logger.log(logger.EXTREME, "Inserting link");
\r
1407 String text = browser.selectedText();
\r
1408 if (text.trim().equalsIgnoreCase(""))
\r
1411 NoteQuickLinkDialog dialog = new NoteQuickLinkDialog(logger, conn, text);
\r
1412 if (dialog.getResults().size() == 0) {
\r
1413 QMessageBox.critical(null, tr("No Matches Found") ,tr("No matching notes found."));
\r
1416 if (dialog.getResults().size() > 1) {
\r
1418 if (!dialog.okPressed) {
\r
1419 logger.log(logger.EXTREME, "Insert link canceled");
\r
1424 User user = Global.getUserInformation();
\r
1425 String dUrl = new String("evernote:///view/") + new String(user.getId() + "/" +user.getShardId() +"/"
\r
1426 +dialog.getSelectedNote()+"/"+dialog.getSelectedNote() +"/ " +"style=\"color:#69aa35\"");
\r
1428 String url = "<a title=\"" +dUrl
\r
1429 +"\" href=" +dUrl
\r
1430 +" >"+text +"</a>";
\r
1431 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1432 browser.page().mainFrame().evaluateJavaScript(script);
\r
1436 // Insert a hyperlink
\r
1437 public void insertLink() {
\r
1438 logger.log(logger.EXTREME, "Inserting link");
\r
1439 String text = browser.selectedText();
\r
1440 if (text.trim().equalsIgnoreCase(""))
\r
1443 InsertLinkDialog dialog = new InsertLinkDialog(insertHyperlink);
\r
1444 if (currentHyperlink != null && currentHyperlink != "") {
\r
1445 dialog.setUrl(currentHyperlink);
\r
1448 if (!dialog.okPressed()) {
\r
1449 logger.log(logger.EXTREME, "Insert link canceled");
\r
1453 // Take care of inserting new links
\r
1454 if (insertHyperlink) {
\r
1455 String selectedText = browser.selectedText();
\r
1456 if (dialog.getUrl().trim().equals(""))
\r
1458 logger.log(logger.EXTREME, "Inserting link on text "+selectedText);
\r
1459 logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim());
\r
1460 String dUrl = StringUtils.replace(dialog.getUrl().trim(), "'", "\\'");
\r
1461 String url = "<a href=\"" +dUrl
\r
1462 +"\" title=" +dUrl
\r
1463 +" >"+selectedText +"</a>";
\r
1464 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1465 browser.page().mainFrame().evaluateJavaScript(script);
\r
1469 // Edit existing links
\r
1470 String js = new String( "function getCursorPos() {"
\r
1472 +"if (window.getSelection) {"
\r
1473 +" var selObj = window.getSelection();"
\r
1474 +" var selRange = selObj.getRangeAt(0);"
\r
1475 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1476 +" while(workingNode != null) { "
\r
1477 +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');"
\r
1478 +" workingNode = workingNode.parentNode;"
\r
1481 +"} getCursorPos();");
\r
1482 browser.page().mainFrame().evaluateJavaScript(js);
\r
1484 if (!dialog.getUrl().trim().equals("")) {
\r
1490 js = new String( "function getCursorPos() {"
\r
1492 +"if (window.getSelection) {"
\r
1493 +" var selObj = window.getSelection();"
\r
1494 +" var selRange = selObj.getRangeAt(0);"
\r
1495 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1496 +" while(workingNode != null) { "
\r
1497 +" if (workingNode.nodeName.toLowerCase()=='a') { "
\r
1498 +" workingNode.removeAttribute('href');"
\r
1499 +" workingNode.removeAttribute('title');"
\r
1500 +" var text = document.createTextNode(workingNode.innerText);"
\r
1501 +" workingNode.parentNode.insertBefore(text, workingNode);"
\r
1502 +" workingNode.parentNode.removeChild(workingNode);"
\r
1504 +" workingNode = workingNode.parentNode;"
\r
1507 +"} getCursorPos();");
\r
1508 browser.page().mainFrame().evaluateJavaScript(js);
\r
1516 // Insert a hyperlink
\r
1517 public void insertLatex() {
\r
1520 public void editLatex(String guid) {
\r
1521 logger.log(logger.EXTREME, "Inserting latex");
\r
1522 String text = browser.selectedText();
\r
1523 if (text.trim().equalsIgnoreCase(" ") || text.trim().equalsIgnoreCase("")) {
\r
1524 InsertLatexImage dialog = new InsertLatexImage();
\r
1525 if (guid != null) {
\r
1526 String formula = conn.getNoteTable().noteResourceTable.getNoteSourceUrl(guid).replace("http://latex.codecogs.com/gif.latex?", "");
\r
1527 dialog.setFormula(formula);
\r
1530 if (!dialog.okPressed()) {
\r
1531 logger.log(logger.EXTREME, "Edit LaTex canceled");
\r
1534 text = dialog.getFormula().trim();
\r
1536 blockApplication.emit(this);
\r
1537 logger.log(logger.EXTREME, "Inserting LaTeX formula:" +text);
\r
1539 text = StringUtils.replace(text, "'", "\\'");
\r
1540 String url = "http://latex.codecogs.com/gif.latex?" +text;
\r
1541 logger.log(logger.EXTREME, "Sending request to codecogs --> " + url);
\r
1542 QNetworkAccessManager manager = new QNetworkAccessManager(this);
\r
1543 manager.finished.connect(this, "insertLatexImageReady(QNetworkReply)");
\r
1544 unblockTime = new GregorianCalendar().getTimeInMillis()+5000;
\r
1545 awaitingHttpResponse = true;
\r
1546 manager.get(new QNetworkRequest(new QUrl(url)));
\r
1549 public void insertLatexImageReady(QNetworkReply reply) {
\r
1550 logger.log(logger.EXTREME, "Response received from CodeCogs");
\r
1551 if (reply.error() != NetworkError.NoError)
\r
1555 if (!awaitingHttpResponse)
\r
1558 awaitingHttpResponse = false;
\r
1559 QUrl replyUrl = reply.url();
\r
1560 QByteArray image = reply.readAll();
\r
1562 logger.log(logger.EXTREME, "New image size: " +image.size());
\r
1564 Resource newRes = null;
\r
1567 if (latexGuid == null) {
\r
1568 logger.log(logger.EXTREME, "Creating temporary gif");
\r
1569 path = Global.getFileManager().getResDirPath("latex-temp.gif");
\r
1570 tfile = new QFile(path);
\r
1571 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1572 logger.log(logger.EXTREME, "File Open: " +tfile.errorString());
\r
1573 tfile.write(image);
\r
1574 logger.log(logger.EXTREME, "Bytes writtes: "+tfile.size());
\r
1576 logger.log(logger.EXTREME, "Creating resource");
\r
1578 if (currentNote.getResources() != null || currentNote.getResources().size() > 0)
\r
1579 sequence = currentNote.getResources().size();
\r
1580 newRes = createResource(path,sequence ,"image/gif", false);
\r
1581 QImage pix = new QImage();
\r
1582 pix.loadFromData(image);
\r
1583 newRes.setHeight(new Integer(pix.height()).shortValue());
\r
1584 newRes.setWidth(new Integer(pix.width()).shortValue());
\r
1585 logger.log(logger.EXTREME, "Renaming temporary file to " +newRes.getGuid()+".gif");
\r
1586 path = Global.getFileManager().getResDirPath(newRes.getGuid()+".gif");
\r
1587 tfile.rename(path);
\r
1589 newRes = conn.getNoteTable().noteResourceTable.getNoteResource(latexGuid, false);
\r
1590 path = Global.getFileManager().getResDirPath(newRes.getGuid()+".gif");
\r
1591 tfile = new QFile(path);
\r
1592 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1593 tfile.write(image);
\r
1595 newRes.getData().setBody(image.toByteArray());
\r
1596 // Calculate the new hash value
\r
1599 logger.log(logger.EXTREME, "Generating MD5");
\r
1601 md = MessageDigest.getInstance("MD5");
\r
1602 md.update(image.toByteArray());
\r
1603 byte[] hash = md.digest();
\r
1604 newRes.getData().setBodyHash(hash);
\r
1605 } catch (NoSuchAlgorithmException e) {
\r
1606 e.printStackTrace();
\r
1608 QImage pix = new QImage();
\r
1609 pix.loadFromData(image);
\r
1610 newRes.setHeight(new Integer(pix.height()).shortValue());
\r
1611 newRes.setWidth(new Integer(pix.width()).shortValue());
\r
1612 conn.getNoteTable().noteResourceTable.updateNoteResource(newRes, true);
\r
1615 logger.log(logger.EXTREME, "Setting source: " +replyUrl.toString());
\r
1616 newRes.getAttributes().setSourceURL(replyUrl.toString());
\r
1617 conn.getNoteTable().noteResourceTable.updateNoteSourceUrl(newRes.getGuid(), replyUrl.toString(), true);
\r
1619 for(int i=0; i<currentNote.getResourcesSize(); i++) {
\r
1620 if (currentNote.getResources().get(i).getGuid().equals(newRes.getGuid())) {
\r
1621 currentNote.getResources().remove(i);
\r
1622 i=currentNote.getResourcesSize();
\r
1625 currentNote.getResources().add(newRes);
\r
1628 // do the actual insert into the note. We only do this on new formulas.
\r
1629 if (latexGuid == null) {
\r
1630 StringBuffer buffer = new StringBuffer(100);
\r
1631 String formula = replyUrl.toString().toLowerCase().replace("http://latex.codecogs.com/gif.latex?", "");
\r
1632 buffer.append("<a href=\"latex://"+path.replace("\\", "/")+"\" title=\""+formula+"\""
\r
1634 buffer.append(path.replace("\\", "/"));
\r
1635 buffer.append("\" en-tag=\"en-latex\" type=\"image/gif\""
\r
1636 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1637 +" guid=\"" +newRes.getGuid() +"\""
\r
1640 String script_start = new String("document.execCommand('insertHTML', false, '");
\r
1641 String script_end = new String("');");
\r
1642 browser.page().mainFrame().evaluateJavaScript(
\r
1643 script_start + buffer + script_end);
\r
1645 HtmlTagModifier modifier = new HtmlTagModifier(getContent());
\r
1646 modifier.modifyLatexTagHash(newRes);
\r
1647 String newContent = modifier.getHtml();
\r
1648 setContent(new QByteArray(newContent));
\r
1651 logger.log(logger.EXTREME, "New HTML set\n" +browser.page().currentFrame().toHtml());
\r
1652 QWebSettings.setMaximumPagesInCache(0);
\r
1653 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
1655 browser.page().mainFrame().setHtml(browser.page().mainFrame().toHtml());
\r
1658 // resourceSignal.contentChanged.emit(path);
\r
1660 unblockApplication.emit();
\r
1668 public void insertTable() {
\r
1669 TableDialog dialog = new TableDialog();
\r
1671 if (!dialog.okPressed()) {
\r
1675 int cols = dialog.getCols();
\r
1676 int rows = dialog.getRows();
\r
1677 int width = dialog.getWidth();
\r
1678 boolean percent = dialog.isPercent();
\r
1680 String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();
\r
1682 newHTML = newHTML +"%";
\r
1683 newHTML = newHTML + "\"><tbody>";
\r
1685 for (int i=0; i<rows; i++) {
\r
1686 newHTML = newHTML +"<tr>";
\r
1687 for (int j=0; j<cols; j++) {
\r
1688 newHTML = newHTML +"<td> </td>";
\r
1690 newHTML = newHTML +"</tr>";
\r
1692 newHTML = newHTML+"</tbody></table>";
\r
1694 String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";
\r
1695 browser.page().mainFrame().evaluateJavaScript(script);
\r
1699 // Text content changed
\r
1700 @SuppressWarnings("unused")
\r
1701 private void selectionChanged() {
\r
1702 browser.encryptAction.setEnabled(true);
\r
1703 browser.insertLinkAction.setEnabled(true);
\r
1704 browser.insertQuickLinkAction.setEnabled(true);
\r
1705 String scriptStart = "var selection_text = (window.getSelection()).toString();"
\r
1706 + "var range = (window.getSelection()).getRangeAt(0);"
\r
1707 + "var parent_html = range.commonAncestorContainer.innerHTML;"
\r
1708 + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"
\r
1709 + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"
\r
1710 + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"
\r
1711 + "var start = parent_html.indexOf(first_text);"
\r
1712 + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"
\r
1713 + "var value = parent_html.substring(start,end);"
\r
1714 + "window.jambi.saveSelectedText(value);" ;
\r
1715 browser.page().mainFrame().evaluateJavaScript(scriptStart);
\r
1719 public void saveSelectedText(String text) {
\r
1720 boolean enabled = true;
\r
1721 if (text.trim().length() == 0)
\r
1723 if (text.indexOf("en-tag=\"en-crypt\"") >= 0)
\r
1725 if (text.indexOf("<img en-tag=\"en-media\"") >= 0)
\r
1727 if (text.indexOf("<a en-tag=\"en-media\"") >= 0)
\r
1729 if (text.indexOf("<input ") >= 0)
\r
1732 browser.encryptAction.setEnabled(enabled);
\r
1733 browser.insertLinkAction.setEnabled(enabled);
\r
1734 browser.insertQuickLinkAction.setEnabled(enabled);
\r
1735 // selectedText = text;
\r
1738 // Decrypt clicked text
\r
1739 public void decryptText(String id, String text, String hint) {
\r
1740 EnCrypt crypt = new EnCrypt();
\r
1741 String plainText = null;
\r
1742 Calendar currentTime = new GregorianCalendar();
\r
1743 Long l = new Long(currentTime.getTimeInMillis());
\r
1744 String slot = new String(Long.toString(l));
\r
1746 // First, try to decrypt with any keys we already have
\r
1747 for (int i=0; i<Global.passwordRemember.size(); i++) {
\r
1748 plainText = crypt.decrypt(text, Global.passwordRemember.get(i).getFirst(), 64);
\r
1749 if (plainText != null) {
\r
1750 slot = new String(Long.toString(l));
\r
1751 Global.passwordSafe.put(slot, Global.passwordRemember.get(i));
\r
1752 removeEncryption(id, plainText, false, slot);
\r
1758 EnDecryptDialog dialog = new EnDecryptDialog();
\r
1759 dialog.setHint(hint);
\r
1760 while (plainText == null || !dialog.okPressed()) {
\r
1762 if (!dialog.okPressed()) {
\r
1765 plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);
\r
1766 if (plainText == null) {
\r
1767 QMessageBox.warning(this, tr("Incorrect Password"), tr("The password entered is not correct"));
\r
1770 Pair<String,String> passwordPair = new Pair<String,String>();
\r
1771 passwordPair.setFirst(dialog.getPassword());
\r
1772 passwordPair.setSecond(dialog.getHint());
\r
1773 Global.passwordSafe.put(slot, passwordPair);
\r
1774 // removeEncryption(id, plainText.replaceAll("\n", "<br/>"), dialog.permanentlyDecrypt(), slot);
\r
1775 removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);
\r
1776 if (dialog.rememberPassword()) {
\r
1777 Pair<String, String> pair = new Pair<String,String>();
\r
1778 pair.setFirst(dialog.getPassword());
\r
1779 pair.setSecond(dialog.getHint());
\r
1780 Global.passwordRemember.add(pair);
\r
1785 // Get the editor tag line
\r
1786 public TagLineEdit getTagLine() {
\r
1790 // Modify a note's tags
\r
1791 @SuppressWarnings("unused")
\r
1792 private void modifyTags() {
\r
1793 TagAssign tagWindow = new TagAssign(allTags, currentTags, !conn.getNotebookTable().isLinked(currentNote.getNotebookGuid()));
\r
1795 if (tagWindow.okClicked()) {
\r
1796 currentTags.clear();
\r
1797 StringBuffer tagDisplay = new StringBuffer();
\r
1799 List<QListWidgetItem> newTags = tagWindow.getTagList()
\r
1801 for (int i = 0; i < newTags.size(); i++) {
\r
1802 currentTags.add(newTags.get(i).text());
\r
1803 tagDisplay.append(newTags.get(i).text());
\r
1804 if (i < newTags.size() - 1) {
\r
1805 tagDisplay.append(Global.tagDelimeter + " ");
\r
1808 tagEdit.setText(tagDisplay.toString());
\r
1809 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1813 // Tag line has been modified by typing text
\r
1814 @SuppressWarnings("unused")
\r
1815 private void modifyTagsTyping() {
\r
1816 String completionText = "";
\r
1817 if (tagEdit.currentCompleterSelection != null && !tagEdit.currentCompleterSelection.equals("")) {
\r
1818 completionText = tagEdit.currentCompleterSelection;
\r
1819 tagEdit.currentCompleterSelection = "";
\r
1822 if (tagEdit.text().equalsIgnoreCase(saveTagList))
\r
1825 // We know something has changed...
\r
1826 String oldTagArray[] = saveTagList.split(Global.tagDelimeter);
\r
1827 String newTagArray[];
\r
1828 if (!completionText.equals("")) {
\r
1829 String before = tagEdit.text().substring(0,tagEdit.cursorPosition());
\r
1830 int lastDelimiter = before.lastIndexOf(Global.tagDelimeter);
\r
1831 if (lastDelimiter > 0)
\r
1832 before = before.substring(0,before.lastIndexOf(Global.tagDelimeter));
\r
1835 String after = tagEdit.text().substring(tagEdit.cursorPosition());
\r
1836 newTagArray = (before+Global.tagDelimeter+completionText+Global.tagDelimeter+after).split(Global.tagDelimeter);
\r
1839 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1842 // Remove any traling or leading blanks
\r
1843 for (int i=0; i<newTagArray.length; i++)
\r
1844 newTagArray[i] = newTagArray[i].trim().replaceAll("^\\s+", "");;
\r
1846 // Remove any potential duplicates from the new list
\r
1847 for (int i=0; i<newTagArray.length; i++) {
\r
1848 boolean foundOnce = false;
\r
1849 for (int j=0; j<newTagArray.length; j++) {
\r
1850 if (newTagArray[j].equalsIgnoreCase(newTagArray[i])) {
\r
1854 newTagArray[j] = "";
\r
1859 List<String> newTagList = new ArrayList<String>();
\r
1860 List<String> oldTagList = new ArrayList<String>();
\r
1862 for (int i = 0; i < oldTagArray.length; i++)
\r
1863 if (!oldTagArray[i].trim().equals(""))
\r
1864 oldTagList.add(oldTagArray[i]);
\r
1865 for (int i = 0; i < newTagArray.length; i++)
\r
1866 if (!newTagArray[i].trim().equals(""))
\r
1867 newTagList.add(newTagArray[i]);
\r
1869 if (conn.getNotebookTable().isLinked(currentNote.getNotebookGuid())) {
\r
1870 for (int i=newTagList.size()-1; i>=0; i--) {
\r
1871 boolean found = false;
\r
1872 for (int j=0; j<allTags.size(); j++) {
\r
1873 if (allTags.get(j).getName().equalsIgnoreCase(newTagList.get(i))) {
\r
1879 newTagList.remove(i);
\r
1883 // Let's cleanup the appearance of the tag list
\r
1884 Collections.sort(newTagList);
\r
1885 String newDisplay = "";
\r
1886 for (int i=0; i<newTagList.size(); i++) {
\r
1887 newDisplay = newDisplay+newTagList.get(i);
\r
1888 if (i<newTagList.size()-1)
\r
1889 newDisplay = newDisplay+Global.tagDelimeter +" ";
\r
1891 tagEdit.blockSignals(true);
\r
1892 tagEdit.setText(newDisplay);
\r
1893 tagEdit.blockSignals(false);
\r
1895 // We now have lists of the new & old. Remove duplicates. If all
\r
1896 // are removed from both then nothing has really changed
\r
1897 for (int i = newTagList.size() - 1; i >= 0; i--) {
\r
1898 String nTag = newTagList.get(i);
\r
1899 for (int j = oldTagList.size() - 1; j >= 0; j--) {
\r
1900 String oTag = oldTagList.get(j);
\r
1901 if (oTag.equalsIgnoreCase(nTag)) {
\r
1902 oldTagList.remove(j);
\r
1903 newTagList.remove(i);
\r
1909 if (oldTagList.size() != 0 || newTagList.size() != 0) {
\r
1910 currentTags.clear();
\r
1911 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1912 for (int i = 0; i < newTagArray.length; i++)
\r
1913 if (!newTagArray[i].trim().equals(""))
\r
1914 currentTags.add(newTagArray[i].trim());
\r
1916 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1921 // Tab button was pressed
\r
1922 public void tabPressed() {
\r
1923 if (insideEncryption)
\r
1925 if (!insideList && !insideTable) {
\r
1926 String script_start = new String(
\r
1927 "document.execCommand('insertHtml', false, ' ');");
\r
1928 browser.page().mainFrame().evaluateJavaScript(script_start);
\r
1934 if (insideTable) {
\r
1935 String js = new String( "function getCursorPosition() { "
\r
1936 +" var selObj = window.getSelection();"
\r
1937 +" var selRange = selObj.getRangeAt(0);"
\r
1938 +" var workingNode = window.getSelection().anchorNode;"
\r
1939 +" var rowCount = 0;"
\r
1940 +" var colCount = 0;"
\r
1941 +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
\r
1942 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
1943 +" rowCount = rowCount+1;"
\r
1945 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
1946 +" colCount = colCount+1;"
\r
1948 +" if (workingNode.previousSibling != null)"
\r
1949 +" workingNode = workingNode.previousSibling;"
\r
1951 +" workingNode = workingNode.parentNode;"
\r
1953 +" var nodes = workingNode.getElementsByTagName('tr');"
\r
1954 +" var tableRows = nodes.length;"
\r
1955 +" nodes = nodes[0].getElementsByTagName('td');"
\r
1956 +" var tableColumns = nodes.length;"
\r
1957 +" window.jambi.setTableCursorPositionTab(rowCount, colCount, tableRows, tableColumns);"
\r
1958 +"} getCursorPosition();");
\r
1959 browser.page().mainFrame().evaluateJavaScript(js);
\r
1963 // If a user presses tab from within a table
\r
1964 public void setTableCursorPositionTab(int currentRow, int currentCol, int tableRows, int tableColumns) {
\r
1965 if (tableRows == currentRow && currentCol == tableColumns) {
\r
1968 KeyboardModifiers modifiers = new KeyboardModifiers(KeyboardModifier.NoModifier);
\r
1969 QKeyEvent right = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Right.value(), modifiers);
\r
1970 QKeyEvent end = new QKeyEvent(Type.KeyPress, Qt.Key.Key_End.value(), modifiers);
\r
1971 QKeyEvent end2 = new QKeyEvent(Type.KeyPress, Qt.Key.Key_End.value(), modifiers);
\r
1972 getBrowser().focusWidget();
\r
1973 QCoreApplication.postEvent(getBrowser(), end);
\r
1974 QCoreApplication.postEvent(getBrowser(), right);
\r
1975 QCoreApplication.postEvent(getBrowser(), end2);
\r
1978 public void backtabPressed() {
\r
1979 if (insideEncryption)
\r
1983 if (insideTable) {
\r
1984 String js = new String( "function getCursorPosition() { "
\r
1985 +" var selObj = window.getSelection();"
\r
1986 +" var selRange = selObj.getRangeAt(0);"
\r
1987 +" var workingNode = window.getSelection().anchorNode;"
\r
1988 +" var rowCount = 0;"
\r
1989 +" var colCount = 0;"
\r
1990 +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
\r
1991 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
1992 +" rowCount = rowCount+1;"
\r
1994 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
1995 +" colCount = colCount+1;"
\r
1997 +" if (workingNode.previousSibling != null)"
\r
1998 +" workingNode = workingNode.previousSibling;"
\r
2000 +" workingNode = workingNode.parentNode;"
\r
2002 +" var nodes = workingNode.getElementsByTagName('tr');"
\r
2003 +" var tableRows = nodes.length;"
\r
2004 +" nodes = nodes[0].getElementsByTagName('td');"
\r
2005 +" var tableColumns = nodes.length;"
\r
2006 +" window.jambi.setTableCursorPositionBackTab(rowCount, colCount, tableRows, tableColumns);"
\r
2007 +"} getCursorPosition();");
\r
2008 browser.page().mainFrame().evaluateJavaScript(js);
\r
2013 // If a user presses backtab from within a table
\r
2014 public void setTableCursorPositionBackTab(int currentRow, int currentCol, int tableRows, int tableColumns) {
\r
2015 if (currentRow == 1 && currentCol == 1) {
\r
2018 KeyboardModifiers modifiers = new KeyboardModifiers(KeyboardModifier.NoModifier);
\r
2019 QKeyEvent left = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Left.value(), modifiers);
\r
2020 QKeyEvent home = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Home.value(), modifiers);
\r
2021 getBrowser().focusWidget();
\r
2022 QCoreApplication.postEvent(getBrowser(), home);
\r
2023 QCoreApplication.postEvent(getBrowser(), left);
\r
2027 public void setInsideList() {
\r
2028 insideList = true;
\r
2031 // The title has been edited
\r
2032 @SuppressWarnings("unused")
\r
2033 private void titleEdited() {
\r
2034 // If we don't have a good note, or if the current title
\r
2035 // matches the old title then we don't need to do anything
\r
2036 if (currentNote == null)
\r
2038 if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))
\r
2041 // If we have a real change, we need to save it.
\r
2042 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text().trim());
\r
2043 currentNote.setTitle(titleLabel.text().trim());
\r
2044 saveNoteTitle = titleLabel.text().trim();
\r
2048 // Set the list of note tags
\r
2049 public void setAllTags(List<Tag> l) {
\r
2051 tagEdit.setTagList(l);
\r
2054 // Setter for the current tags
\r
2055 public void setCurrentTags(List<String> s) {
\r
2059 // Save the list of notebooks
\r
2060 public void setNotebookList(List<Notebook> n) {
\r
2062 loadNotebookList();
\r
2065 // Load the notebook list and select the current notebook
\r
2066 private void loadNotebookList() {
\r
2067 if (notebookBox.count() != 0)
\r
2068 notebookBox.clear();
\r
2069 if (notebookList == null)
\r
2072 for (int i = 0; i < notebookList.size(); i++) {
\r
2073 notebookBox.addItem(notebookList.get(i).getName());
\r
2074 if (currentNote != null) {
\r
2075 if (currentNote.getNotebookGuid().equals(
\r
2076 notebookList.get(i).getGuid())) {
\r
2077 notebookBox.setCurrentIndex(i);
\r
2084 // Set the notebook for a note
\r
2085 public void setNotebook(String notebook) {
\r
2086 currentNote.setNotebookGuid(notebook);
\r
2087 loadNotebookList();
\r
2090 // Get the contents of the editor
\r
2091 public String getContent() {
\r
2092 return browser.page().currentFrame().toHtml();
\r
2095 // The note contents have changed
\r
2096 public void contentChanged() {
\r
2097 String content = getContent();
\r
2099 // This puts in a 1/2 second delay
\r
2100 // before updating the source editor.
\r
2101 // It improves response when someone is doing
\r
2102 // frequent updates on a large note.
\r
2103 // If the source editor isn't visible, then there
\r
2104 // is no point to doing any of this.
\r
2105 if (sourceEdit.isVisible()) {
\r
2106 setSourceTimer.stop();
\r
2107 setSourceTimer.setInterval(500);
\r
2108 setSourceTimer.setSingleShot(true);
\r
2109 setSourceTimer.start();
\r
2113 noteSignal.noteChanged.emit(currentNote.getGuid(), content);
\r
2116 // The notebook selection has changed
\r
2117 @SuppressWarnings("unused")
\r
2118 private void notebookChanged() {
\r
2119 boolean changed = false;
\r
2120 String n = notebookBox.currentText();
\r
2121 for (int i = 0; i < notebookList.size(); i++) {
\r
2122 if (n.equals(notebookList.get(i).getName())) {
\r
2123 if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {
\r
2124 String guid = conn.getNotebookTable().findNotebookByName(n);
\r
2125 if (conn.getNotebookTable().isLinked(guid)) {
\r
2126 tagEdit.setText("");
\r
2127 noteSignal.tagsChanged.emit(currentNote.getGuid(), new ArrayList<String>());
\r
2128 FilterEditorTags t = new FilterEditorTags(conn, logger);
\r
2129 setAllTags(t.getValidTags(currentNote));
\r
2131 currentNote.setNotebookGuid(notebookList.get(i).getGuid());
\r
2134 i = notebookList.size();
\r
2138 // If the notebook changed, signal the update
\r
2140 noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote
\r
2141 .getNotebookGuid());
\r
2144 // Check the note title
\r
2145 private void checkNoteTitle() {
\r
2146 String text = browser.page().currentFrame().toPlainText();
\r
2147 if (saveNoteTitle == null)
\r
2148 saveNoteTitle = new String();
\r
2149 if (saveNoteTitle.trim().equals("") || saveNoteTitle.trim().equals("Untitled Note")) {
\r
2150 int newLine = text.indexOf("\n");
\r
2151 if (newLine > 0) {
\r
2152 text = text.substring(0, newLine);
\r
2153 if (text.trim().equals(""))
\r
2154 text = tr("Untitled Note");
\r
2155 titleLabel.setText(text);
\r
2157 if (text.length() > Constants.EDAM_NOTE_TITLE_LEN_MAX)
\r
2158 titleLabel.setText(text.substring(0, Constants.EDAM_NOTE_TITLE_LEN_MAX));
\r
2160 titleLabel.blockSignals(true);
\r
2161 if (text.trim().equals(""))
\r
2162 titleLabel.setText(tr("Untitled Note"));
\r
2164 titleLabel.setText(text);
\r
2165 titleLabel.blockSignals(false);
\r
2168 if (currentNote != null && titleLabel != null)
\r
2169 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text());
\r
2173 // Return the note contents so we can email them
\r
2174 public String getContentsToEmail() {
\r
2175 return browser.page().currentFrame().toPlainText().trim();
\r
2177 * int body = browser.page().currentFrame().toHtml().indexOf("<body>");
\r
2178 * String temp = browser.page().currentFrame().toHtml(); if (body == -1)
\r
2179 * temp = "<html><body><b>Test</b></body></html>"; else temp =
\r
2180 * "<html>"+temp.substring(body); return temp; // return
\r
2181 * urlEncode(browser.page().currentFrame().toHtml());
\r
2185 // Insert an image into the editor
\r
2186 private void insertImage(QMimeData mime) {
\r
2187 logger.log(logger.EXTREME, "Entering insertImage");
\r
2188 QImage img = (QImage) mime.imageData();
\r
2189 String script_start = new String(
\r
2190 "document.execCommand('insertHTML', false, '");
\r
2191 String script_end = new String("');");
\r
2193 long now = new Date().getTime();
\r
2194 String path = Global.getFileManager().getResDirPath(
\r
2195 (new Long(now).toString()) + ".jpg");
\r
2197 // This block is just a hack to make sure we wait at least 1ms so we
\r
2199 // have collisions on image names
\r
2200 long i = new Date().getTime();
\r
2202 i = new Date().getTime();
\r
2204 // Open the file & write the data
\r
2205 QFile tfile = new QFile(path);
\r
2206 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
2207 if (!img.save(tfile)) {
\r
2213 Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);
\r
2214 if (newRes == null)
\r
2216 currentNote.getResources().add(newRes);
\r
2218 // do the actual insert into the note
\r
2219 StringBuffer buffer = new StringBuffer(100);
\r
2220 buffer.append("<img src=\"");
\r
2221 buffer.append(tfile.fileName());
\r
2222 buffer.append("\" en-tag=en-media type=\"image/jpeg\""
\r
2223 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
2224 +" guid=\"" +newRes.getGuid() +"\""
\r
2225 +" onContextMenu=\"window.jambi.imageContextMenu(&." +tfile.fileName() +"&.);\""
\r
2228 browser.page().mainFrame().evaluateJavaScript(
\r
2229 script_start + buffer + script_end);
\r
2234 // Handle pasting of a note-to-note link
\r
2235 private void handleNoteLink(QMimeData mime) {
\r
2236 for (int i=0; i<mime.urls().size(); i++) {
\r
2237 StringTokenizer tokens = new StringTokenizer(mime.urls().get(i).toString().replace("evernote:///view/", ""), "/");
\r
2238 tokens.nextToken();
\r
2239 tokens.nextToken();
\r
2240 String sid = tokens.nextToken();
\r
2241 String lid = tokens.nextToken();
\r
2243 if (!sid.equals(currentNote.getGuid()) && !lid.equals(currentNote.getGuid())) {
\r
2245 Note note = conn.getNoteTable().getNote(sid, false, false, false, false, false);
\r
2247 note = conn.getNoteTable().getNote(lid, false, false, false, false, false);
\r
2252 // If we've gotten this far, we have a bunch of values. We need to build the link.
\r
2253 StringBuffer url = new StringBuffer(100);
\r
2254 String script_start = new String(
\r
2255 "document.execCommand('insertHtml', false, '");
\r
2256 String script_end = new String("');");
\r
2258 url.append("<a href=\""+mime.urls().get(i).toString() +"\" style=\"color:#69aa35\">");
\r
2259 url.append(note.getTitle());
\r
2260 url.append("</a>");
\r
2261 if (mime.urls().size() > 1)
\r
2262 url.append(" ");
\r
2263 browser.page().mainFrame().evaluateJavaScript(
\r
2264 script_start + url + script_end);
\r
2269 // Handle URLs that are trying to be pasted
\r
2270 public void handleUrls(QMimeData mime) {
\r
2271 logger.log(logger.EXTREME, "Starting handleUrls");
\r
2272 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
2274 List<QUrl> urlList = mime.urls();
\r
2275 String url = new String();
\r
2276 String script_start = new String(
\r
2277 "document.execCommand('createLink', false, '");
\r
2278 String script_end = new String("');");
\r
2280 for (int i = 0; i < urlList.size(); i++) {
\r
2281 url = urlList.get(i).toString();
\r
2282 // Find out what type of file we have
\r
2283 String mimeType = fileNameMap.getContentTypeFor(url);
\r
2285 // If null returned, we need to guess at the file type
\r
2286 if (mimeType == null)
\r
2287 mimeType = "application/"
\r
2288 + url.substring(url.lastIndexOf(".") + 1);
\r
2290 // Check if we have an image or some other type of file
\r
2291 if (url.substring(0, 5).equalsIgnoreCase("file:")
\r
2292 && mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
2293 handleLocalImageURLPaste(mime, mimeType);
\r
2297 boolean smallEnough = checkFileAttachmentSize(url);
\r
2299 && url.substring(0, 5).equalsIgnoreCase("file:")
\r
2300 && !mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
2301 handleLocalAttachment(mime, mimeType);
\r
2304 browser.page().mainFrame().evaluateJavaScript(
\r
2305 script_start + url + script_end);
\r
2310 // If a URL being pasted is an image URL, then attach the image
\r
2311 private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {
\r
2312 List<QUrl> urlList = mime.urls();
\r
2313 String url = new String();
\r
2314 String script_start_image = new String(
\r
2315 "document.execCommand('insertHtml', false, '");
\r
2316 String script_end = new String("');");
\r
2317 StringBuffer buffer;
\r
2319 // Copy the image over into the resource directory and create a new resource
\r
2320 // record for each url pasted
\r
2321 for (int i = 0; i < urlList.size(); i++) {
\r
2322 url = urlList.get(i).toString();
\r
2324 Resource newRes = createResource(url, i, mimeType, false);
\r
2325 if (newRes == null)
\r
2327 currentNote.getResources().add(newRes);
\r
2328 buffer = new StringBuffer(100);
\r
2330 // Open the file & write the data
\r
2331 String fileName = Global.getFileManager().getResDirPath(newRes.getGuid());
\r
2332 QFile tfile = new QFile(fileName);
\r
2333 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
2334 tfile.write(newRes.getData().getBody());
\r
2336 buffer.append(script_start_image);
\r
2337 buffer.append("<img src=\"" + FileUtils.toForwardSlashedPath(fileName));
\r
2338 // if (mimeType.equalsIgnoreCase("image/jpg"))
\r
2339 // mimeType = "image/jpeg";
\r
2340 buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""
\r
2341 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
2342 +" guid=\"" +newRes.getGuid() +"\""
\r
2343 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
2345 buffer.append(script_end);
\r
2346 browser.page().mainFrame().evaluateJavaScript(buffer.toString());
\r
2352 // If a URL being pasted is a local file URL, then attach the file
\r
2353 private void handleLocalAttachment(QMimeData mime, String mimeType) {
\r
2354 logger.log(logger.EXTREME, "Attaching local file");
\r
2355 List<QUrl> urlList = mime.urls();
\r
2356 String script_start = new String(
\r
2357 "document.execCommand('insertHtml', false, '");
\r
2358 String script_end = new String("');");
\r
2359 StringBuffer buffer;
\r
2361 String[] type = mimeType.split("/");
\r
2362 String icon = findIcon(type[1]);
\r
2363 if (icon.equals("attachment.png"))
\r
2364 icon = findIcon(type[0]);
\r
2365 buffer = new StringBuffer(100);
\r
2367 for (int i = 0; i < urlList.size(); i++) {
\r
2368 String url = urlList.get(i).toString();
\r
2370 // Start building the HTML
\r
2371 if (icon.equals("attachment.png"))
\r
2372 icon = findIcon(url.substring(url.lastIndexOf(".")+1));
\r
2373 String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));
\r
2375 logger.log(logger.EXTREME, "Creating resource ");
\r
2376 Resource newRes = createResource(url, i, mimeType, true);
\r
2377 if (newRes == null)
\r
2379 logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());
\r
2380 currentNote.getResources().add(newRes);
\r
2382 String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();
\r
2383 // If we have a PDF, we need to setup the preview.
\r
2384 if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {
\r
2385 logger.log(logger.EXTREME, "Setting up PDF preview");
\r
2386 if (newRes.getAttributes() != null &&
\r
2387 newRes.getAttributes().getFileName() != null &&
\r
2388 !newRes.getAttributes().getFileName().trim().equals(""))
\r
2389 fileName = newRes.getGuid()+Global.attachmentNameDelimeter+
\r
2390 newRes.getAttributes().getFileName();
\r
2392 fileName = newRes.getGuid()+".pdf";
\r
2393 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
2394 QFile.OpenMode mode = new QFile.OpenMode();
\r
2395 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2397 QDataStream out = new QDataStream(file);
\r
2398 // Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);
\r
2399 QByteArray binData = new QByteArray(newRes.getData().getBody());
\r
2400 // resBinary = null;
\r
2401 out.writeBytes(binData.toByteArray());
\r
2404 PDFPreview pdfPreview = new PDFPreview();
\r
2405 if (pdfPreview.setupPreview(Global.getFileManager().getResDirPath(fileName), "pdf",0)) {
\r
2406 imageURL = file.fileName() + ".png";
\r
2410 logger.log(logger.EXTREME, "Generating link tags");
\r
2411 buffer.delete(0, buffer.length());
\r
2412 buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");
\r
2413 buffer.append(" onContextMenu=\"window.jambi.imageContextMenu('")
\r
2414 .append(Global.getFileManager().getResDirPath(fileName))
\r
2415 .append("');\" "); buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");
\r
2416 buffer.append("<img src=\"" + imageURL + "\" title=\"" +newRes.getAttributes().getFileName());
\r
2417 buffer.append("\"></img>");
\r
2418 buffer.append("</a>");
\r
2419 browser.page().mainFrame().evaluateJavaScript(
\r
2420 script_start + buffer.toString() + script_end);
\r
2425 private Resource createResource(String url, int sequence, String mime, boolean attachment) {
\r
2426 logger.log(logger.EXTREME, "Inside create resource");
\r
2427 QFile resourceFile;
\r
2428 String urlTest = new QUrl(url).toLocalFile();
\r
2429 if (!urlTest.equals(""))
\r
2431 url = url.replace("/", File.separator);
\r
2432 logger.log(logger.EXTREME, "Reading from file to create resource");
\r
2433 resourceFile = new QFile(url);
\r
2434 resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));
\r
2435 // logger.log(logger.EXTREME, "Error opening file "+url.toString() +": "+resourceFile.errorString());
\r
2436 byte[] fileData = resourceFile.readAll().toByteArray();
\r
2437 resourceFile.close();
\r
2438 if (fileData.length == 0)
\r
2442 logger.log(logger.EXTREME, "Generating MD5");
\r
2443 md = MessageDigest.getInstance("MD5");
\r
2444 md.update(fileData);
\r
2445 byte[] hash = md.digest();
\r
2447 Resource r = new Resource();
\r
2448 Calendar time = new GregorianCalendar();
\r
2449 long prevTime = time.getTimeInMillis();
\r
2450 while (prevTime == time.getTimeInMillis()) {
\r
2451 time = new GregorianCalendar();
\r
2453 r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());
\r
2454 r.setNoteGuid(currentNote.getGuid());
\r
2456 r.setActive(true);
\r
2457 r.setUpdateSequenceNum(0);
\r
2458 r.setWidth((short) 0);
\r
2459 r.setHeight((short) 0);
\r
2460 r.setDuration((short) 0);
\r
2462 Data d = new Data();
\r
2463 d.setBody(fileData);
\r
2464 d.setBodyIsSet(true);
\r
2465 d.setBodyHash(hash);
\r
2466 d.setBodyHashIsSet(true);
\r
2468 d.setSize(fileData.length);
\r
2470 int fileNamePos = url.lastIndexOf(File.separator);
\r
2471 if (fileNamePos == -1)
\r
2472 fileNamePos = url.lastIndexOf("/");
\r
2473 String fileName = url.substring(fileNamePos+1);
\r
2474 ResourceAttributes a = new ResourceAttributes();
\r
2476 a.setAltitudeIsSet(false);
\r
2477 a.setLongitude(0);
\r
2478 a.setLongitudeIsSet(false);
\r
2480 a.setLatitudeIsSet(false);
\r
2481 a.setCameraMake("");
\r
2482 a.setCameraMakeIsSet(false);
\r
2483 a.setCameraModel("");
\r
2484 a.setCameraModelIsSet(false);
\r
2485 a.setAttachment(attachment);
\r
2486 a.setAttachmentIsSet(true);
\r
2487 a.setClientWillIndex(false);
\r
2488 a.setClientWillIndexIsSet(true);
\r
2489 a.setRecoType("");
\r
2490 a.setRecoTypeIsSet(false);
\r
2491 a.setSourceURL(url);
\r
2492 a.setSourceURLIsSet(true);
\r
2493 a.setTimestamp(0);
\r
2494 a.setTimestampIsSet(false);
\r
2495 a.setFileName(fileName);
\r
2496 a.setFileNameIsSet(true);
\r
2497 r.setAttributes(a);
\r
2499 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
2500 logger.log(logger.EXTREME, "Resource created");
\r
2502 } catch (NoSuchAlgorithmException e1) {
\r
2503 e1.printStackTrace();
\r
2509 // find the appropriate icon for an attachment
\r
2510 private String findIcon(String appl) {
\r
2511 appl = appl.toLowerCase();
\r
2512 File f = Global.getFileManager().getImageDirFile(appl + ".png");
\r
2514 return appl+".png";
\r
2515 return "attachment.png";
\r
2520 // Check the file attachment to be sure it isn't over 25 mb
\r
2521 private boolean checkFileAttachmentSize(String url) {
\r
2522 String fileName = url.substring(8);
\r
2523 QFile resourceFile = new QFile(fileName);
\r
2524 resourceFile.open(new QIODevice.OpenMode(
\r
2525 QIODevice.OpenModeFlag.ReadOnly));
\r
2526 long size = resourceFile.size();
\r
2527 resourceFile.close();
\r
2528 size = size / 1024 / 1024;
\r
2529 if (size < 50 && Global.isPremium())
\r
2534 String error = tr("A file attachment may not exceed 25MB.");
\r
2535 QMessageBox.information(this, tr("Attachment Size"), error);
\r
2540 @SuppressWarnings("unused")
\r
2541 private void createdChanged() {
\r
2542 QDateTime dt = new QDateTime();
\r
2543 dt.setDate(createdDate.date());
\r
2544 dt.setTime(createdTime.time());
\r
2545 noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);
\r
2549 @SuppressWarnings("unused")
\r
2550 private void alteredChanged() {
\r
2551 QDateTime dt = new QDateTime();
\r
2552 dt.setDate(alteredDate.date());
\r
2553 dt.setTime(alteredTime.time());
\r
2554 noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);
\r
2557 @SuppressWarnings("unused")
\r
2558 private void subjectDateTimeChanged() {
\r
2559 QDateTime dt = new QDateTime();
\r
2560 dt.setDate(subjectDate.date());
\r
2561 dt.setTime(subjectTime.time());
\r
2562 noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);
\r
2566 @SuppressWarnings("unused")
\r
2567 private void sourceUrlChanged() {
\r
2568 noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());
\r
2571 @SuppressWarnings("unused")
\r
2572 private void authorChanged() {
\r
2573 noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());
\r
2576 @SuppressWarnings("unused")
\r
2577 private void geoBoxChanged() {
\r
2578 int index = geoBox.currentIndex();
\r
2579 geoBox.setCurrentIndex(0);
\r
2581 GeoDialog box = new GeoDialog();
\r
2582 box.setLongitude(currentNote.getAttributes().getLongitude());
\r
2583 box.setLatitude(currentNote.getAttributes().getLatitude());
\r
2584 box.setAltitude(currentNote.getAttributes().getAltitude());
\r
2586 if (!box.okPressed())
\r
2588 double alt = box.getAltitude();
\r
2589 double lat = box.getLatitude();
\r
2590 double lon = box.getLongitude();
\r
2591 if (alt != currentNote.getAttributes().getAltitude() ||
\r
2592 lon != currentNote.getAttributes().getLongitude() ||
\r
2593 lat != currentNote.getAttributes().getLatitude()) {
\r
2594 noteSignal.geoChanged.emit(currentNote.getGuid(), lon, lat, alt);
\r
2595 currentNote.getAttributes().setAltitude(alt);
\r
2596 currentNote.getAttributes().setLongitude(lon);
\r
2597 currentNote.getAttributes().setLatitude(lat);
\r
2602 noteSignal.geoChanged.emit(currentNote.getGuid(), 0.0, 0.0, 0.0);
\r
2603 currentNote.getAttributes().setAltitude(0.0);
\r
2604 currentNote.getAttributes().setLongitude(0.0);
\r
2605 currentNote.getAttributes().setLatitude(0.0);
\r
2608 if (index == 3 || index == 0) {
\r
2609 QDesktopServices.openUrl(new QUrl("http://maps.google.com/maps?z=6&q="+currentNote.getAttributes().getLatitude() +"," +currentNote.getAttributes().getLongitude()));
\r
2613 // ************************************************************
\r
2614 // * User chose to save an attachment. Pares out the request *
\r
2615 // * into a guid & file. Save the result. *
\r
2616 // ************************************************************
\r
2617 public void downloadAttachment(QNetworkRequest request) {
\r
2619 QFileDialog fd = new QFileDialog(this);
\r
2620 fd.setFileMode(FileMode.AnyFile);
\r
2621 fd.setConfirmOverwrite(true);
\r
2622 fd.setWindowTitle(tr("Save File"));
\r
2623 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2624 fd.setDirectory(System.getProperty("user.home"));
\r
2625 String name = request.url().toString();
\r
2627 int pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2629 guid = name.substring(0, pos).replace("nnres://", "");
\r
2630 name = name.substring(pos +Global.attachmentNameDelimeter.length());
\r
2631 fd.selectFile(name);
\r
2632 pos = name.lastIndexOf('.');
\r
2634 String mimeType = "(*." + name.substring(pos + 1)
\r
2635 + ");; All Files (*)";
\r
2636 fd.setFilter(tr(mimeType));
\r
2642 // Strip URL prefix and base dir
\r
2643 guid = guid.replace("nnres://", "")
\r
2644 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2645 guid = guid.replace("file://", "").replace("/", "")
\r
2646 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2648 pos = guid.lastIndexOf('.');
\r
2650 guid = guid.substring(0,pos);
\r
2651 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2652 name = name.replace('\\', '/');
\r
2653 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2654 QFile saveFile = new QFile(fd.selectedFiles().get(0));
\r
2655 QFile.OpenMode mode = new QFile.OpenMode();
\r
2656 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2657 saveFile.open(mode);
\r
2658 QDataStream saveOut = new QDataStream(saveFile);
\r
2659 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2660 saveOut.writeBytes(binData.toByteArray());
\r
2667 // ************************************************************
\r
2668 // * User chose to save an attachment. Pares out the request *
\r
2669 // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!
\r
2670 // ************************************************************
\r
2671 public void downloadImage(QNetworkRequest request) {
\r
2672 QFileDialog fd = new QFileDialog(this);
\r
2673 fd.setFileMode(FileMode.AnyFile);
\r
2674 fd.setConfirmOverwrite(true);
\r
2675 fd.setWindowTitle(tr("Save File"));
\r
2676 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2677 fd.setDirectory(System.getProperty("user.home"));
\r
2678 String name = request.url().toString();
\r
2679 name = name.replace("nnres://", "");
\r
2680 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
\r
2681 name = name.replace(dPath, "");
\r
2682 int pos = name.lastIndexOf('.');
\r
2683 String guid = name;
\r
2685 String mimeType = "(*." + name.substring(pos + 1)
\r
2686 + ");; All Files (*)";
\r
2687 fd.setFilter(tr(mimeType));
\r
2688 guid = guid.substring(0,pos);
\r
2690 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2692 guid = name.substring(0, pos);
\r
2693 fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));
\r
2695 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2696 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2697 String fileName = fd.selectedFiles().get(0);
\r
2698 QFile saveFile = new QFile(fileName);
\r
2699 QFile.OpenMode mode = new QFile.OpenMode();
\r
2700 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2701 saveFile.open(mode);
\r
2702 QDataStream saveOut = new QDataStream(saveFile);
\r
2703 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2704 saveOut.writeBytes(binData.toByteArray());
\r
2710 // *************************************************************
\r
2711 // * decrypt any hidden text. We could do an XML parse, but
\r
2712 // * it is quicker here just to scan for an <img tag & do the fix
\r
2713 // * the manual way
\r
2714 // *************************************************************
\r
2715 private void removeEncryption(String id, String plainText, boolean permanent, String slot) {
\r
2717 plainText = " <table class=\"en-crypt-temp\" slot=\""
\r
2720 +"border=1 width=100%><tbody><tr><td>"
\r
2721 +plainText+"</td></tr></tbody></table>";
\r
2724 String html = browser.page().mainFrame().toHtml();
\r
2725 String text = html;
\r
2726 int imagePos = html.indexOf("<img");
\r
2728 for ( ;imagePos>0; ) {
\r
2729 // Find the end tag
\r
2730 endPos = text.indexOf(">", imagePos);
\r
2731 String tag = text.substring(imagePos-1,endPos);
\r
2732 if (tag.indexOf("id=\""+id+"\"") > -1) {
\r
2733 text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);
\r
2734 QTextCodec codec = QTextCodec.codecForName("UTF-8");
\r
2735 QByteArray unicode = codec.fromUnicode(text);
\r
2736 setContent(unicode);
\r
2740 imagePos = text.indexOf("<img", imagePos+1);
\r
2745 //****************************************************************
\r
2746 //* Focus shortcuts
\r
2747 //****************************************************************
\r
2748 @SuppressWarnings("unused")
\r
2749 private void focusTitle() {
\r
2750 titleLabel.setFocus();
\r
2752 @SuppressWarnings("unused")
\r
2753 private void focusTag() {
\r
2754 tagEdit.setFocus();
\r
2756 @SuppressWarnings("unused")
\r
2757 private void focusNote() {
\r
2758 browser.setFocus();
\r
2760 @SuppressWarnings("unused")
\r
2761 private void focusAuthor() {
\r
2762 authorLabel.setFocus();
\r
2764 @SuppressWarnings("unused")
\r
2765 private void focusUrl() {
\r
2766 urlLabel.setFocus();
\r
2770 //*****************************************************************
\r
2771 //* Set the document background color
\r
2772 //*****************************************************************
\r
2773 public void setBackgroundColor(String color) {
\r
2774 String js = "function changeBackground(color) {"
\r
2775 +"document.body.style.background = color;"
\r
2777 +"changeBackground('" +color+"');";
\r
2778 browser.page().mainFrame().evaluateJavaScript(js);
\r
2783 //****************************************************************
\r
2784 //* MicroFocus changed
\r
2785 //****************************************************************
\r
2786 private void microFocusChanged() {
\r
2787 boldButton.setDown(false);
\r
2788 italicButton.setDown(false);
\r
2789 underlineButton.setDown(false);
\r
2790 browser.openAction.setEnabled(false);
\r
2791 browser.downloadAttachment.setEnabled(false);
\r
2792 browser.downloadImage.setEnabled(false);
\r
2793 browser.rotateImageLeft.setEnabled(false);
\r
2794 browser.rotateImageRight.setEnabled(false);
\r
2795 browser.insertTableAction.setEnabled(true);
\r
2796 browser.deleteTableColumnAction.setEnabled(false);
\r
2797 browser.insertTableRowAction.setEnabled(false);
\r
2798 browser.insertTableColumnAction.setEnabled(false);
\r
2799 browser.deleteTableRowAction.setEnabled(false);
\r
2800 browser.insertLinkAction.setText(tr("Insert Hyperlink"));
\r
2801 insertHyperlink = true;
\r
2802 browser.insertQuickLinkAction.setEnabled(true);
\r
2803 currentHyperlink ="";
\r
2804 insideList = false;
\r
2805 insideTable = false;
\r
2806 insideEncryption = false;
\r
2807 forceTextPaste = false;
\r
2809 String js = new String( "function getCursorPos() {"
\r
2811 +"if (window.getSelection) {"
\r
2812 +" var selObj = window.getSelection();"
\r
2813 +" var selRange = selObj.getRangeAt(0);"
\r
2814 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2815 +" while(workingNode != null) { "
\r
2816 // +" window.jambi.printNode(workingNode.nodeName);"
\r
2817 +" if (workingNode.nodeName=='TABLE') { if (workingNode.getAttribute('class').toLowerCase() == 'en-crypt-temp') window.jambi.insideEncryption(); }"
\r
2818 +" if (workingNode.nodeName=='B') window.jambi.boldActive();"
\r
2819 +" if (workingNode.nodeName=='I') window.jambi.italicActive();"
\r
2820 +" if (workingNode.nodeName=='U') window.jambi.underlineActive();"
\r
2821 +" if (workingNode.nodeName=='UL') window.jambi.setInsideList();"
\r
2822 +" if (workingNode.nodeName=='OL') window.jambi.setInsideList();"
\r
2823 +" if (workingNode.nodeName=='LI') window.jambi.setInsideList();"
\r
2824 +" if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"
\r
2825 +" 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
2826 +" if (workingNode.nodeName=='SPAN') {"
\r
2827 +" if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"
\r
2829 +" workingNode = workingNode.parentNode;"
\r
2832 +"} getCursorPos();");
\r
2833 browser.page().mainFrame().evaluateJavaScript(js);
\r
2836 public void printNode(String n) {
\r
2837 System.out.println("Node Vaule: " +n);
\r
2840 public void insideEncryption() {
\r
2841 insideEncryption = true;
\r
2845 //****************************************************************
\r
2846 //* Insert a table row
\r
2847 //****************************************************************
\r
2848 public void insertTableRow() {
\r
2850 String js = new String( "function insertTableRow() {"
\r
2851 +" var selObj = window.getSelection();"
\r
2852 +" var selRange = selObj.getRangeAt(0);"
\r
2853 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2854 +" var cellCount = 0;"
\r
2855 +" while(workingNode != null) { "
\r
2856 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2857 +" row = document.createElement('TR');"
\r
2858 +" var nodes = workingNode.getElementsByTagName('td');"
\r
2859 +" for (j=0; j<nodes.length; j=j+1) {"
\r
2860 +" cell = document.createElement('TD');"
\r
2861 +" cell.innerHTML=' ';"
\r
2862 +" row.appendChild(cell);"
\r
2864 +" workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"
\r
2867 +" workingNode = workingNode.parentNode;"
\r
2869 +"} insertTableRow();");
\r
2870 browser.page().mainFrame().evaluateJavaScript(js);
\r
2874 public void insertTableColumn() {
\r
2875 String js = new String( "function insertTableColumn() {"
\r
2876 +" var selObj = window.getSelection();"
\r
2877 +" var selRange = selObj.getRangeAt(0);"
\r
2878 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2879 +" var current = 0;"
\r
2880 +" while (workingNode.nodeName.toLowerCase() != 'table' && workingNode != null) {"
\r
2881 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
2882 +" var td = workingNode;"
\r
2883 +" while (td.previousSibling != null) { "
\r
2884 +" current = current+1; td = td.previousSibling;"
\r
2887 +" workingNode = workingNode.parentNode; "
\r
2889 +" if (workingNode == null) return;"
\r
2890 +" for (var i=0; i<workingNode.rows.length; i++) { "
\r
2891 +" var cell = workingNode.rows[i].insertCell(current+1); "
\r
2892 +" cell.innerHTML = ' '; "
\r
2894 +"} insertTableColumn();");
\r
2895 browser.page().mainFrame().evaluateJavaScript(js);
\r
2899 //****************************************************************
\r
2900 //* Delete a table row
\r
2901 //****************************************************************
\r
2902 public void deleteTableRow() {
\r
2904 String js = new String( "function deleteTableRow() {"
\r
2905 +" var selObj = window.getSelection();"
\r
2906 +" var selRange = selObj.getRangeAt(0);"
\r
2907 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2908 +" var cellCount = 0;"
\r
2909 +" while(workingNode != null) { "
\r
2910 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2911 +" workingNode.parentNode.removeChild(workingNode);"
\r
2914 +" workingNode = workingNode.parentNode;"
\r
2916 +"} deleteTableRow();");
\r
2917 browser.page().mainFrame().evaluateJavaScript(js);
\r
2921 public void deleteTableColumn() {
\r
2922 String js = new String( "function deleteTableColumn() {"
\r
2923 +" var selObj = window.getSelection();"
\r
2924 +" var selRange = selObj.getRangeAt(0);"
\r
2925 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2926 +" var current = 0;"
\r
2927 +" while (workingNode.nodeName.toLowerCase() != 'table' && workingNode != null) {"
\r
2928 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
2929 +" var td = workingNode;"
\r
2930 +" while (td.previousSibling != null) { "
\r
2931 +" current = current+1; td = td.previousSibling;"
\r
2934 +" workingNode = workingNode.parentNode; "
\r
2936 +" if (workingNode == null) return;"
\r
2937 +" for (var i=0; i<workingNode.rows.length; i++) { "
\r
2938 +" workingNode.rows[i].deleteCell(current); "
\r
2940 +"} deleteTableColumn();");
\r
2941 browser.page().mainFrame().evaluateJavaScript(js);
\r
2946 public void setInsideTable() {
\r
2947 browser.insertTableRowAction.setEnabled(true);
\r
2948 browser.insertTableColumnAction.setEnabled(true);
\r
2949 browser.deleteTableRowAction.setEnabled(true);
\r
2950 browser.deleteTableColumnAction.setEnabled(true);
\r
2951 browser.insertTableAction.setEnabled(false);
\r
2952 browser.encryptAction.setEnabled(false);
\r
2953 insideTable = true;
\r
2956 public void setInsideLink(String link) {
\r
2957 browser.insertLinkAction.setText(tr("Edit Hyperlink"));
\r
2958 currentHyperlink = link;
\r
2959 insertHyperlink = false;
\r
2962 public void italicActive() {
\r
2963 italicButton.setDown(true);
\r
2965 public void boldActive() {
\r
2966 boldButton.setDown(true);
\r
2968 public void underlineActive() {
\r
2969 underlineButton.setDown(true);
\r
2971 public void forceTextPaste() {
\r
2972 forceTextPaste = true;
\r
2974 public void imageContextMenu(String f) {
\r
2975 browser.downloadImage.setEnabled(true);
\r
2976 browser.rotateImageRight.setEnabled(true);
\r
2977 browser.rotateImageLeft.setEnabled(true);
\r
2978 browser.openAction.setEnabled(true);
\r
2981 public void rotateImageRight() {
\r
2982 QWebSettings.setMaximumPagesInCache(0);
\r
2983 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2984 QImage image = new QImage(selectedFile);
\r
2985 QMatrix matrix = new QMatrix();
\r
2986 matrix.rotate( 90.0 );
\r
2987 image = image.transformed(matrix);
\r
2988 image.save(selectedFile);
\r
2989 QWebSettings.setMaximumPagesInCache(0);
\r
2990 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2991 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2994 resourceSignal.contentChanged.emit(selectedFile);
\r
2997 public void rotateImageLeft() {
\r
2998 QImage image = new QImage(selectedFile);
\r
2999 QMatrix matrix = new QMatrix();
\r
3000 matrix.rotate( -90.0 );
\r
3001 image = image.transformed(matrix);
\r
3002 image.save(selectedFile);
\r
3003 browser.setHtml(browser.page().mainFrame().toHtml());
\r
3006 resourceSignal.contentChanged.emit(selectedFile);
\r
3008 public void resourceContextMenu(String f) {
\r
3009 browser.downloadAttachment.setEnabled(true);
\r
3010 browser.openAction.setEnabled(true);
\r
3013 public void latexContextMenu(String f) {
\r
3014 browser.downloadImage.setEnabled(true);
\r
3015 browser.rotateImageRight.setEnabled(true);
\r
3016 browser.rotateImageLeft.setEnabled(true);
\r
3017 browser.openAction.setEnabled(true);
\r
3021 //****************************************************************
\r
3022 //* Apply CSS style to specified word
\r
3023 //****************************************************************
\r
3024 /* public void applyStyleToWords(String word, String style) {
\r
3025 QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");
\r
3026 script.open(OpenModeFlag.ReadOnly);
\r
3027 String s = script.readAll().toString();
\r
3028 String js = new String(s +" findit('"+word+"', '"+style+"');");
\r
3029 browser.page().mainFrame().evaluateJavaScript(js);
\r
3030 System.out.println(getContent());
\r
3033 //****************************************************************
\r
3034 //* Someone tried to paste a resource between notes, so we need *
\r
3035 //* to do some special handling. *
\r
3036 //****************************************************************
\r
3037 private String fixInternotePaste(String text) {
\r
3038 logger.log(logger.EXTREME, "Fixing internote paste");
\r
3039 String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");
\r
3040 return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");
\r
3042 private String fixInternotePasteSearch(String text, String type, String locTag) {
\r
3044 // First, let's fix the images.
\r
3045 int startPos = text.indexOf(type);
\r
3047 for (; startPos>=0;) {
\r
3048 endPos = text.indexOf(">", startPos+1);
\r
3049 String segment = text.substring(startPos, endPos);
\r
3050 if (segment.indexOf("en-tag") > -1) {
\r
3051 String newSegment = segment;
\r
3053 int guidStartPos = segment.indexOf("guid=\"");
\r
3054 int guidEndPos = segment.indexOf("\"", guidStartPos+7);
\r
3055 String guid = segment.substring(guidStartPos+6,guidEndPos);
\r
3057 int mimeStartPos = segment.indexOf("type");
\r
3058 int mimeEndPos = segment.indexOf("\"", mimeStartPos+7);
\r
3059 String mime = segment.substring(mimeStartPos+6,mimeEndPos);
\r
3061 int srcStartPos = segment.indexOf("src");
\r
3062 int srcEndPos = segment.indexOf("\"", srcStartPos+6);
\r
3063 String src = segment.substring(srcStartPos+5,srcEndPos);
\r
3065 Calendar currentTime = new GregorianCalendar();
\r
3066 Long l = new Long(currentTime.getTimeInMillis());
\r
3067 long prevTime = l;
\r
3068 while (l==prevTime) {
\r
3069 currentTime = new GregorianCalendar();
\r
3070 l= new Long(currentTime.getTimeInMillis());
\r
3073 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
3074 // if r==null, then the image doesn't exist (it was probably cut out of another note, so
\r
3075 // we need to recereate it
\r
3077 r = createResource(src, 1, mime, false);
\r
3081 String randint = new String(Long.toString(l));
\r
3082 String extension = null;
\r
3083 if (r.getMime()!= null) {
\r
3084 extension = r.getMime().toLowerCase();
\r
3085 if (extension.indexOf("/")>-1)
\r
3086 extension = extension.substring(extension.indexOf("/")+1);
\r
3088 String newFile = randint;
\r
3089 if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")
\r
3090 if (!locTag.startsWith("src"))
\r
3091 newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();
\r
3092 r.setNoteGuid(currentNote.getGuid());
\r
3094 r.setGuid(randint);
\r
3095 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
3096 QFile f = new QFile(Global.getFileManager().getResDirPath(newFile));
\r
3097 QByteArray bin = new QByteArray(r.getData().getBody());
\r
3098 f.open(QFile.OpenModeFlag.WriteOnly);
\r
3101 newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);
\r
3102 currentNote.getResources().add(r);
\r
3104 int startSrcPos = newSegment.indexOf(locTag);
\r
3105 int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);
\r
3107 if (locTag.startsWith("src")) {
\r
3108 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
3109 newSegment = newSegment.replace(source,
\r
3110 FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath(newFile)));
\r
3112 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
3113 newSegment = newSegment.replace(source, newFile);
\r
3116 text = text.substring(0,startPos) + newSegment + text.substring(endPos);
\r
3118 startPos = text.indexOf(type, startPos+1);
\r
3124 public void nextPage(String file) {
\r
3125 logger.log(logger.EXTREME, "Starting nextPage()");
\r
3127 Integer pageNumber;
\r
3128 if (previewPageList.containsKey(file))
\r
3129 pageNumber = previewPageList.get(file)+1;
\r
3132 previewPageList.remove(file);
\r
3133 previewPageList.put(file, pageNumber);
\r
3134 PDFPreview pdfPreview = new PDFPreview();
\r
3135 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
3136 if (goodPreview) {
\r
3138 // String html = getContent();
\r
3139 QWebSettings.setMaximumPagesInCache(0);
\r
3140 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
3141 // browser.setContent(new QByteArray());
\r
3142 browser.setHtml(browser.page().mainFrame().toHtml());
\r
3144 // browser.setContent(new QByteArray(html));
\r
3145 // browser.triggerPageAction(WebAction.Reload);
\r
3146 // pdfMouseOver(selectedFile);
\r
3150 public void previousPage(String file) {
\r
3151 logger.log(logger.EXTREME, "Starting previousPage()");
\r
3153 Integer pageNumber;
\r
3154 if (previewPageList.containsKey(file))
\r
3155 pageNumber = previewPageList.get(file)-1;
\r
3158 previewPageList.remove(file);
\r
3159 previewPageList.put(file, pageNumber);
\r
3160 PDFPreview pdfPreview = new PDFPreview();
\r
3161 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
3162 if (goodPreview) {
\r
3164 // String html = getContent();
\r
3165 QWebSettings.setMaximumPagesInCache(0);
\r
3166 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
3167 browser.setHtml(browser.page().mainFrame().toHtml());
\r
3169 // browser.setContent(new QByteArray(html));
\r
3170 // browser.triggerPageAction(WebAction.Reload);
\r
3174 /* public void pdfMouseOver(String name) {
\r
3176 if (previewPageList.containsKey(selectedFile))
\r
3177 pageNumber = previewPageList.get(selectedFile)+1;
\r
3181 if (pageNumber <= 1)
\r
3182 browser.previousPageAction.setEnabled(false);
\r
3184 browser.previousPageAction.setEnabled(true);
\r
3186 PDFPreview pdf = new PDFPreview();
\r
3187 int totalPages = pdf.getPageCount(name);
\r
3188 if (previewPageList.containsKey(selectedFile))
\r
3189 pageNumber = previewPageList.get(selectedFile)+1;
\r
3192 if (totalPages > pageNumber)
\r
3193 browser.nextPageAction.setEnabled(true);
\r
3195 browser.nextPageAction.setEnabled(false);
\r
3199 public void pdfMouseOut() {
\r
3200 // browser.nextPageAction.setVisible(false);
\r
3201 // browser.previousPageAction.setVisible(false);
\r
3205 @SuppressWarnings("unused")
\r
3206 private void toggleUndoVisible(Boolean toggle) {
\r
3207 undoAction.setVisible(toggle);
\r
3208 Global.saveEditorButtonsVisible("undo", toggle);
\r
3210 @SuppressWarnings("unused")
\r
3211 private void toggleRedoVisible(Boolean toggle) {
\r
3212 redoAction.setVisible(toggle);
\r
3213 Global.saveEditorButtonsVisible("redo", toggle);
\r
3215 @SuppressWarnings("unused")
\r
3216 private void toggleCutVisible(Boolean toggle) {
\r
3217 cutAction.setVisible(toggle);
\r
3218 Global.saveEditorButtonsVisible("cut", toggle);
\r
3220 @SuppressWarnings("unused")
\r
3221 private void toggleCopyVisible(Boolean toggle) {
\r
3222 copyAction.setVisible(toggle);
\r
3223 Global.saveEditorButtonsVisible("copy", toggle);
\r
3225 @SuppressWarnings("unused")
\r
3226 private void togglePasteVisible(Boolean toggle) {
\r
3227 pasteAction.setVisible(toggle);
\r
3228 Global.saveEditorButtonsVisible("paste", toggle);
\r
3230 @SuppressWarnings("unused")
\r
3231 private void toggleBoldVisible(Boolean toggle) {
\r
3232 boldAction.setVisible(toggle);
\r
3233 Global.saveEditorButtonsVisible("bold", toggle);
\r
3235 @SuppressWarnings("unused")
\r
3236 private void toggleItalicVisible(Boolean toggle) {
\r
3237 italicAction.setVisible(toggle);
\r
3238 Global.saveEditorButtonsVisible("italic", toggle);
\r
3240 @SuppressWarnings("unused")
\r
3241 private void toggleUnderlineVisible(Boolean toggle) {
\r
3242 underlineAction.setVisible(toggle);
\r
3243 Global.saveEditorButtonsVisible("underline", toggle);
\r
3245 @SuppressWarnings("unused")
\r
3246 private void toggleStrikethroughVisible(Boolean toggle) {
\r
3247 strikethroughAction.setVisible(toggle);
\r
3248 Global.saveEditorButtonsVisible("strikethrough", toggle);
\r
3250 @SuppressWarnings("unused")
\r
3251 private void toggleLeftAlignVisible(Boolean toggle) {
\r
3252 leftAlignAction.setVisible(toggle);
\r
3253 Global.saveEditorButtonsVisible("alignLeft", toggle);
\r
3255 @SuppressWarnings("unused")
\r
3256 private void toggleRightAlignVisible(Boolean toggle) {
\r
3257 rightAlignAction.setVisible(toggle);
\r
3258 Global.saveEditorButtonsVisible("alignRight", toggle);
\r
3260 @SuppressWarnings("unused")
\r
3261 private void toggleCenterAlignVisible(Boolean toggle) {
\r
3262 centerAlignAction.setVisible(toggle);
\r
3263 Global.saveEditorButtonsVisible("alignCenter", toggle);
\r
3265 @SuppressWarnings("unused")
\r
3266 private void toggleHLineVisible(Boolean toggle) {
\r
3267 hlineAction.setVisible(toggle);
\r
3268 Global.saveEditorButtonsVisible("hline", toggle);
\r
3270 @SuppressWarnings("unused")
\r
3271 private void toggleIndentVisible(Boolean toggle) {
\r
3272 indentAction.setVisible(toggle);
\r
3273 Global.saveEditorButtonsVisible("indent", toggle);
\r
3275 @SuppressWarnings("unused")
\r
3276 private void toggleTodoVisible(Boolean toggle) {
\r
3277 todoAction.setVisible(toggle);
\r
3278 Global.saveEditorButtonsVisible("todo", toggle);
\r
3280 @SuppressWarnings("unused")
\r
3281 private void toggleOutdentVisible(Boolean toggle) {
\r
3282 outdentAction.setVisible(toggle);
\r
3283 Global.saveEditorButtonsVisible("outdent", toggle);
\r
3285 @SuppressWarnings("unused")
\r
3286 private void toggleBulletListVisible(Boolean toggle) {
\r
3287 bulletListAction.setVisible(toggle);
\r
3288 Global.saveEditorButtonsVisible("bulletList", toggle);
\r
3290 @SuppressWarnings("unused")
\r
3291 private void toggleNumberListVisible(Boolean toggle) {
\r
3292 numberListAction.setVisible(toggle);
\r
3293 Global.saveEditorButtonsVisible("numberList", toggle);
\r
3295 @SuppressWarnings("unused")
\r
3296 private void toggleFontListVisible(Boolean toggle) {
\r
3297 fontListAction.setVisible(toggle);
\r
3298 Global.saveEditorButtonsVisible("font", toggle);
\r
3300 @SuppressWarnings("unused")
\r
3301 private void toggleFontColorVisible(Boolean toggle) {
\r
3302 fontColorAction.setVisible(toggle);
\r
3303 Global.saveEditorButtonsVisible("fontColor", toggle);
\r
3305 @SuppressWarnings("unused")
\r
3306 private void toggleFontSizeVisible(Boolean toggle) {
\r
3307 fontSizeAction.setVisible(toggle);
\r
3308 Global.saveEditorButtonsVisible("fontSize", toggle);
\r
3310 @SuppressWarnings("unused")
\r
3311 private void toggleFontHilightVisible(Boolean toggle) {
\r
3312 fontHilightAction.setVisible(toggle);
\r
3313 Global.saveEditorButtonsVisible("fontHilight", toggle);
\r
3315 @SuppressWarnings("unused")
\r
3316 private void toggleSpellCheckVisible(Boolean toggle) {
\r
3317 spellCheckAction.setVisible(toggle);
\r
3318 Global.saveEditorButtonsVisible("spellCheck", toggle);
\r
3322 private void setupDictionary() {
\r
3323 File wordList = new File(Global.getFileManager().getSpellDirPath()+Locale.getDefault()+".dic");
\r
3325 dictionary = new SpellDictionaryHashMap(wordList);
\r
3326 spellChecker = new SpellChecker(dictionary);
\r
3328 File userWordList;
\r
3329 userWordList = new File(Global.getFileManager().getSpellDirPathUser()+"user.dic");
\r
3331 // Get the local user spell dictionary
\r
3333 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
3334 } catch (FileNotFoundException e) {
\r
3335 userWordList.createNewFile();
\r
3336 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
3337 } catch (IOException e) {
\r
3338 userWordList.createNewFile();
\r
3339 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
3342 spellListener = new SuggestionListener(this, spellChecker);
\r
3344 // Add the user dictionary
\r
3345 spellChecker.addSpellCheckListener(spellListener);
\r
3346 spellChecker.setUserDictionary(userDictionary);
\r
3348 } catch (FileNotFoundException e) {
\r
3349 QMessageBox.critical(this, tr("Spell Check Error"),
\r
3350 tr("Dictionary ")+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
3351 tr(".dic was not found."));
\r
3352 } catch (IOException e) {
\r
3353 QMessageBox.critical(this, tr("Spell Check Error"),
\r
3354 tr("Dictionary ")+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
3355 tr(".dic is invalid."));
\r
3360 // Invoke spell checker dialog
\r
3361 @SuppressWarnings("unused")
\r
3362 private void spellCheckClicked() {
\r
3364 if (spellChecker == null) {
\r
3365 setupDictionary();
\r
3368 // Read user settings
\r
3369 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREDIGITWORDS,
\r
3370 Global.getSpellSetting(Configuration.SPELL_IGNOREDIGITWORDS));
\r
3371 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREINTERNETADDRESSES,
\r
3372 Global.getSpellSetting(Configuration.SPELL_IGNOREINTERNETADDRESSES));
\r
3373 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREMIXEDCASE,
\r
3374 Global.getSpellSetting(Configuration.SPELL_IGNOREMIXEDCASE));
\r
3375 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREUPPERCASE,
\r
3376 Global.getSpellSetting(Configuration.SPELL_IGNOREUPPERCASE));
\r
3377 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNORESENTENCECAPITALIZATION,
\r
3378 Global.getSpellSetting(Configuration.SPELL_IGNORESENTENCECAPITALIZATION));
\r
3380 spellListener.abortSpellCheck = false;
\r
3381 spellListener.errorsFound = false;
\r
3382 String content = getBrowser().page().mainFrame().toPlainText();
\r
3383 StringWordTokenizer tokenizer = new StringWordTokenizer(content);
\r
3384 if (!tokenizer.hasMoreWords())
\r
3386 getBrowser().page().action(WebAction.MoveToStartOfDocument);
\r
3388 getBrowser().setFocus();
\r
3391 // Move to the start of page
\r
3392 KeyboardModifiers ctrl = new KeyboardModifiers(KeyboardModifier.ControlModifier.value());
\r
3393 QKeyEvent home = new QKeyEvent(Type.KeyPress, Key.Key_Home.value(), ctrl);
\r
3394 browser.keyPressEvent(home);
\r
3395 getBrowser().setFocus();
\r
3397 tokenizer = new StringWordTokenizer(content);
\r
3400 while(tokenizer.hasMoreWords()) {
\r
3401 word = tokenizer.nextWord();
\r
3402 found = getBrowser().page().findText(word);
\r
3403 if (found && !spellListener.abortSpellCheck) {
\r
3404 spellChecker.checkSpelling(new StringWordTokenizer(word));
\r
3405 getBrowser().setFocus();
\r
3409 // Go to the end of the document & finish up.
\r
3410 home = new QKeyEvent(Type.KeyPress, Key.Key_End.value(), ctrl);
\r
3411 browser.keyPressEvent(home);
\r
3412 if (!spellListener.errorsFound)
\r
3413 QMessageBox.information(this, tr("Spell Check Complete"),
\r
3414 tr("No Errors Found"));
\r
3419 @SuppressWarnings("unused")
\r
3420 private void sourceEdited() {
\r
3421 QTextCodec codec = QTextCodec.codecForLocale();
\r
3422 codec = QTextCodec.codecForName("UTF-8");
\r
3423 String content = codec.fromUnicode(sourceEdit.toHtml()).toString();
\r
3424 content = StringEscapeUtils.unescapeHtml4(removeTags(content));
\r
3425 QByteArray data = new QByteArray(sourceEditHeader+content+"</body></html>");
\r
3426 getBrowser().setContent(data);
\r
3428 if (currentNote != null && sourceEdit != null)
\r
3429 noteSignal.noteChanged.emit(currentNote.getGuid(), sourceEdit.toPlainText());
\r
3432 private void setSource() {
\r
3433 String text = getContent();
\r
3434 sourceEdit.blockSignals(true);
\r
3435 int body = text.indexOf("<body");
\r
3437 body = text.indexOf(">",body);
\r
3439 sourceEditHeader =text.substring(0, body+1);
\r
3440 text = text.substring(body+1);
\r
3443 text = text.replace("</body></html>", "");
\r
3444 sourceEdit.setPlainText(text);
\r
3445 sourceEdit.setReadOnly(!getBrowser().page().isContentEditable());
\r
3446 //syntaxHighlighter.rehighlight();
\r
3447 sourceEdit.blockSignals(false);
\r
3450 // show/hide view source window
\r
3451 public void showSource(boolean value) {
\r
3453 sourceEdit.setVisible(value);
\r
3456 // Remove HTML tags
\r
3457 private String removeTags(String text) {
\r
3458 StringBuffer buffer = new StringBuffer(text);
\r
3459 boolean inTag = false;
\r
3460 int bodyPosition = text.indexOf("<body");
\r
3461 for (int i=buffer.length()-1; i>=0; i--) {
\r
3462 if (buffer.charAt(i) == '>')
\r
3464 if (buffer.charAt(i) == '<')
\r
3466 if (inTag || buffer.charAt(i) == '<' || i<bodyPosition)
\r
3467 buffer.deleteCharAt(i);
\r
3470 return buffer.toString();
\r