2 * This file is part of NeverNote
\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
40 import org.apache.commons.lang.StringUtils;
\r
42 import com.evernote.edam.limits.Constants;
\r
43 import com.evernote.edam.type.Data;
\r
44 import com.evernote.edam.type.Note;
\r
45 import com.evernote.edam.type.Notebook;
\r
46 import com.evernote.edam.type.Resource;
\r
47 import com.evernote.edam.type.ResourceAttributes;
\r
48 import com.evernote.edam.type.Tag;
\r
49 import com.swabunga.spell.engine.Configuration;
\r
50 import com.swabunga.spell.engine.SpellDictionary;
\r
51 import com.swabunga.spell.engine.SpellDictionaryHashMap;
\r
52 import com.swabunga.spell.engine.Word;
\r
53 import com.swabunga.spell.event.SpellCheckEvent;
\r
54 import com.swabunga.spell.event.SpellCheckListener;
\r
55 import com.swabunga.spell.event.SpellChecker;
\r
56 import com.swabunga.spell.event.StringWordTokenizer;
\r
57 import com.trolltech.qt.core.QByteArray;
\r
58 import com.trolltech.qt.core.QDataStream;
\r
59 import com.trolltech.qt.core.QDateTime;
\r
60 import com.trolltech.qt.core.QEvent;
\r
61 import com.trolltech.qt.core.QEvent.Type;
\r
62 import com.trolltech.qt.core.QFile;
\r
63 import com.trolltech.qt.core.QFileSystemWatcher;
\r
64 import com.trolltech.qt.core.QIODevice;
\r
65 import com.trolltech.qt.core.QMimeData;
\r
66 import com.trolltech.qt.core.QTextCodec;
\r
67 import com.trolltech.qt.core.QUrl;
\r
68 import com.trolltech.qt.core.Qt.Key;
\r
69 import com.trolltech.qt.core.Qt.KeyboardModifier;
\r
70 import com.trolltech.qt.core.Qt.KeyboardModifiers;
\r
71 import com.trolltech.qt.gui.QAction;
\r
72 import com.trolltech.qt.gui.QApplication;
\r
73 import com.trolltech.qt.gui.QCalendarWidget;
\r
74 import com.trolltech.qt.gui.QClipboard;
\r
75 import com.trolltech.qt.gui.QColor;
\r
76 import com.trolltech.qt.gui.QComboBox;
\r
77 import com.trolltech.qt.gui.QDateEdit;
\r
78 import com.trolltech.qt.gui.QDesktopServices;
\r
79 import com.trolltech.qt.gui.QFileDialog;
\r
80 import com.trolltech.qt.gui.QFileDialog.AcceptMode;
\r
81 import com.trolltech.qt.gui.QFileDialog.FileMode;
\r
82 import com.trolltech.qt.gui.QFontDatabase;
\r
83 import com.trolltech.qt.gui.QFormLayout;
\r
84 import com.trolltech.qt.gui.QGridLayout;
\r
85 import com.trolltech.qt.gui.QHBoxLayout;
\r
86 import com.trolltech.qt.gui.QIcon;
\r
87 import com.trolltech.qt.gui.QImage;
\r
88 import com.trolltech.qt.gui.QKeyEvent;
\r
89 import com.trolltech.qt.gui.QKeySequence;
\r
90 import com.trolltech.qt.gui.QLabel;
\r
91 import com.trolltech.qt.gui.QLineEdit;
\r
92 import com.trolltech.qt.gui.QListWidgetItem;
\r
93 import com.trolltech.qt.gui.QMatrix;
\r
94 import com.trolltech.qt.gui.QMessageBox;
\r
95 import com.trolltech.qt.gui.QPalette;
\r
96 import com.trolltech.qt.gui.QPalette.ColorRole;
\r
97 import com.trolltech.qt.gui.QPushButton;
\r
98 import com.trolltech.qt.gui.QShortcut;
\r
99 import com.trolltech.qt.gui.QTimeEdit;
\r
100 import com.trolltech.qt.gui.QToolButton;
\r
101 import com.trolltech.qt.gui.QToolButton.ToolButtonPopupMode;
\r
102 import com.trolltech.qt.gui.QVBoxLayout;
\r
103 import com.trolltech.qt.gui.QWidget;
\r
104 import com.trolltech.qt.network.QNetworkRequest;
\r
105 import com.trolltech.qt.webkit.QWebPage;
\r
106 import com.trolltech.qt.webkit.QWebPage.WebAction;
\r
107 import com.trolltech.qt.webkit.QWebSettings;
\r
108 import com.trolltech.qt.webkit.QWebView;
\r
110 import cx.fbn.nevernote.Global;
\r
111 import cx.fbn.nevernote.dialog.EnCryptDialog;
\r
112 import cx.fbn.nevernote.dialog.EnDecryptDialog;
\r
113 import cx.fbn.nevernote.dialog.GeoDialog;
\r
114 import cx.fbn.nevernote.dialog.InsertLinkDialog;
\r
115 import cx.fbn.nevernote.dialog.SpellCheck;
\r
116 import cx.fbn.nevernote.dialog.TableDialog;
\r
117 import cx.fbn.nevernote.dialog.TagAssign;
\r
118 import cx.fbn.nevernote.evernote.EnCrypt;
\r
119 import cx.fbn.nevernote.filters.FilterEditorTags;
\r
120 import cx.fbn.nevernote.signals.NoteResourceSignal;
\r
121 import cx.fbn.nevernote.signals.NoteSignal;
\r
122 import cx.fbn.nevernote.sql.DatabaseConnection;
\r
123 import cx.fbn.nevernote.utilities.ApplicationLogger;
\r
124 import cx.fbn.nevernote.utilities.FileUtils;
\r
125 import cx.fbn.nevernote.utilities.Pair;
\r
127 public class BrowserWindow extends QWidget {
\r
129 public final QLineEdit titleLabel;
\r
130 private final QLineEdit urlText;
\r
131 private final QLabel authorLabel;
\r
132 private final QLineEdit authorText;
\r
133 private final QComboBox geoBox;
\r
134 public final TagLineEdit tagEdit;
\r
135 public final QLabel tagLabel;
\r
136 private final QPushButton urlLabel;
\r
137 private final QLabel alteredLabel;
\r
138 private final QDateEdit alteredDate;
\r
139 private final QTimeEdit alteredTime;
\r
140 private final QDateEdit createdDate;
\r
141 private final QTimeEdit createdTime;
\r
142 private final QLabel subjectLabel;
\r
143 private final QDateEdit subjectDate;
\r
144 private final QTimeEdit subjectTime;
\r
145 public final QComboBox notebookBox;
\r
146 private final QLabel notebookLabel;
\r
147 private final QLabel createdLabel;
\r
148 public final QComboBox fontSize;
\r
149 public final QAction fontSizeAction;
\r
150 private boolean extendedOn;
\r
151 public boolean buttonsVisible;
\r
152 private final String iconPath = new String("classpath:cx/fbn/nevernote/icons/");
\r
153 private final ContentView browser;
\r
154 private List<Tag> allTags;
\r
155 private List<String> currentTags;
\r
156 public NoteSignal noteSignal;
\r
157 private List<Notebook> notebookList;
\r
158 private Note currentNote;
\r
159 private String saveNoteTitle;
\r
160 private String saveTagList;
\r
161 private boolean insideList;
\r
162 // private String selectedText;
\r
163 private final DatabaseConnection conn;
\r
164 private final QCalendarWidget createdCalendarWidget;
\r
165 private final QCalendarWidget alteredCalendarWidget;
\r
166 private final QCalendarWidget subjectCalendarWidget;
\r
168 public final QPushButton undoButton;
\r
169 public final QAction undoAction;
\r
170 public final QPushButton redoButton;
\r
171 public final QAction redoAction;
\r
172 public final QPushButton cutButton;
\r
173 public final QAction cutAction;
\r
174 public final QPushButton copyButton;
\r
175 public final QAction copyAction;
\r
176 public final QPushButton pasteButton;
\r
177 public final QAction pasteAction;
\r
178 public final QPushButton boldButton;
\r
179 public final QAction boldAction;
\r
180 public final QPushButton underlineButton;
\r
181 public final QAction underlineAction;
\r
182 public final QPushButton italicButton;
\r
183 public final QAction italicAction;
\r
184 public final Signal0 focusLost;
\r
185 public final NoteResourceSignal resourceSignal;
\r
187 public QPushButton rightAlignButton;
\r
188 public final QAction rightAlignAction;
\r
189 public QPushButton leftAlignButton;
\r
190 public final QAction leftAlignAction;
\r
191 public QPushButton centerAlignButton;
\r
192 public final QAction centerAlignAction;
\r
194 public final QPushButton strikethroughButton;
\r
195 public final QAction strikethroughAction;
\r
196 public final QPushButton hlineButton;
\r
197 public final QAction hlineAction;
\r
198 public final QPushButton indentButton;
\r
199 public final QAction indentAction;
\r
200 public final QPushButton outdentButton;
\r
201 public final QAction outdentAction;
\r
202 public final QPushButton bulletListButton;
\r
203 public final QAction bulletListAction;
\r
204 public final QPushButton numberListButton;
\r
205 public final QAction numberListAction;
\r
206 public final QPushButton spellCheckButton;
\r
207 public final QAction spellCheckAction;
\r
208 public final QPushButton todoButton;
\r
209 public final QAction todoAction;
\r
211 public final QShortcut focusTitleShortcut;
\r
212 public final QShortcut focusTagShortcut;
\r
213 public final QShortcut focusNoteShortcut;
\r
214 public final QShortcut focusUrlShortcut;
\r
215 public final QShortcut focusAuthorShortcut;
\r
217 public EditorButtonBar buttonLayout;
\r
218 public final QComboBox fontList;
\r
219 public final QAction fontListAction;
\r
220 public final QToolButton fontColor;
\r
221 public final QAction fontColorAction;
\r
222 private final ColorMenu fontColorMenu;
\r
223 public final QToolButton fontHilight;
\r
224 public final QAction fontHilightAction;
\r
225 private final ColorMenu fontHilightColorMenu;
\r
226 public final QFileSystemWatcher fileWatcher;
\r
227 public int cursorPosition;
\r
228 private boolean forceTextPaste = false;
\r
229 private String selectedFile;
\r
230 private String currentHyperlink;
\r
231 public boolean keepPDFNavigationHidden;
\r
232 private final ApplicationLogger logger;
\r
233 SpellDictionary dictionary;
\r
234 SpellDictionary userDictionary;
\r
235 SpellChecker spellChecker;
\r
236 SuggestionListener spellListener;
\r
237 private final HashMap<String,Integer> previewPageList;
\r
238 boolean insertHyperlink = true;
\r
241 public static class SuggestionListener implements SpellCheckListener {
\r
242 public boolean abortSpellCheck = false;
\r
243 public boolean errorsFound = false;
\r
244 private final SpellCheck spellCheckDialog;
\r
247 private final BrowserWindow parent;
\r
248 public SuggestionListener(BrowserWindow parent, SpellChecker checker) {
\r
249 this.parent = parent;
\r
250 spellCheckDialog = new SpellCheck(checker);
\r
252 public void spellingError(SpellCheckEvent event) {
\r
253 errorsFound = true;
\r
254 spellCheckDialog.setWord(event.getInvalidWord());
\r
256 @SuppressWarnings("unchecked")
\r
257 List<Word> suggestions = event.getSuggestions();
\r
258 spellCheckDialog.clearSuggestions();
\r
259 if (!suggestions.isEmpty()) {
\r
260 // spellCheckDialog.setCurrentSuggestion(suggestions.get(0).getWord());
\r
261 for (int i=0; i<suggestions.size(); i++) {
\r
262 spellCheckDialog.addSuggestion(suggestions.get(i).getWord());
\r
264 spellCheckDialog.setSelectedSuggestion(0);
\r
266 spellCheckDialog.exec();
\r
267 if (spellCheckDialog.cancelPressed()) {
\r
268 abortSpellCheck = true;
\r
272 if (spellCheckDialog.replacePressed()) {
\r
273 QClipboard clipboard = QApplication.clipboard();
\r
274 clipboard.setText(spellCheckDialog.getReplacementWord());
\r
275 parent.pasteClicked();
\r
283 public BrowserWindow(DatabaseConnection c) {
\r
284 logger = new ApplicationLogger("browser.log");
\r
285 logger.log(logger.HIGH, "Setting up browser");
\r
287 fileWatcher = new QFileSystemWatcher();
\r
288 // fileWatcher.fileChanged.connect(this, "fileChanged(String)");
\r
289 noteSignal = new NoteSignal();
\r
290 titleLabel = new QLineEdit();
\r
291 titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX);
\r
292 urlText = new QLineEdit();
\r
293 authorText = new QLineEdit();
\r
294 geoBox = new QComboBox();
\r
295 urlLabel = new QPushButton();
\r
296 urlLabel.clicked.connect(this, "sourceUrlClicked()");
\r
297 authorLabel = new QLabel();
\r
300 focusLost = new Signal0();
\r
302 tagEdit = new TagLineEdit(allTags);
\r
303 tagLabel = new QLabel("Tags:");
\r
304 tagEdit.focusLost.connect(this, "modifyTagsTyping()");
\r
306 createdCalendarWidget = new QCalendarWidget();
\r
307 createdDate = new QDateEdit();
\r
308 createdDate.setDisplayFormat(Global.getDateFormat());
\r
309 createdDate.setCalendarPopup(true);
\r
310 createdDate.setCalendarWidget(createdCalendarWidget);
\r
311 createdTime = new QTimeEdit();
\r
312 createdDate.dateChanged.connect(this, "createdChanged()");
\r
313 createdTime.timeChanged.connect(this, "createdChanged()");
\r
315 alteredCalendarWidget = new QCalendarWidget();
\r
316 alteredDate = new QDateEdit();
\r
317 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
318 alteredDate.setCalendarPopup(true);
\r
319 alteredDate.setCalendarWidget(alteredCalendarWidget);
\r
320 alteredTime = new QTimeEdit();
\r
321 alteredLabel = new QLabel("Altered:");
\r
322 alteredDate.dateChanged.connect(this, "alteredChanged()");
\r
323 alteredTime.timeChanged.connect(this, "alteredChanged()");
\r
325 subjectCalendarWidget = new QCalendarWidget();
\r
326 subjectDate = new QDateEdit();
\r
327 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
328 subjectDate.setCalendarPopup(true);
\r
329 subjectDate.setCalendarWidget(subjectCalendarWidget);
\r
330 subjectTime = new QTimeEdit();
\r
331 subjectLabel = new QLabel(tr("Subject Date:"));
\r
332 subjectDate.dateChanged.connect(this, "subjectDateTimeChanged()");
\r
333 subjectTime.timeChanged.connect(this, "subjectDateTimeChanged()");
\r
334 authorText.textChanged.connect(this, "authorChanged()");
\r
335 urlText.textChanged.connect(this, "sourceUrlChanged()");
\r
337 notebookBox = new QComboBox();
\r
338 notebookLabel = new QLabel(tr("Notebook"));
\r
339 createdLabel = new QLabel(tr("Created:"));
\r
340 // selectedText = new String();
\r
342 urlLabel.setVisible(false);
\r
343 urlText.setVisible(false);
\r
344 authorLabel.setVisible(false);
\r
346 geoBox.setVisible(false);
\r
347 geoBox.addItem(new QIcon(iconPath+"globe.png"), "");
\r
348 geoBox.addItem(new String(tr("Set")));
\r
349 geoBox.addItem(new String(tr("Clear")));
\r
350 geoBox.addItem(new String(tr("View On Map")));
\r
351 geoBox.activated.connect(this, "geoBoxChanged()");
\r
353 authorText.setVisible(false);
\r
354 createdDate.setVisible(false);
\r
355 alteredLabel.setVisible(false);
\r
356 //notebookBox.setVisible(false);
\r
357 notebookLabel.setVisible(false);
\r
358 createdLabel.setVisible(false);
\r
359 createdTime.setVisible(false);
\r
360 alteredDate.setVisible(false);
\r
361 alteredTime.setVisible(false);
\r
362 subjectLabel.setVisible(false);
\r
363 subjectDate.setVisible(false);
\r
364 subjectTime.setVisible(false);
\r
365 extendedOn = false;
\r
366 buttonsVisible = true;
\r
367 setAcceptDrops(true);
\r
369 browser = new ContentView(this);
\r
370 browser.page().setLinkDelegationPolicy(
\r
371 QWebPage.LinkDelegationPolicy.DelegateAllLinks);
\r
372 browser.linkClicked.connect(this, "linkClicked(QUrl)");
\r
373 currentHyperlink = "";
\r
375 QVBoxLayout v = new QVBoxLayout();
\r
376 QFormLayout notebookLayout = new QFormLayout();
\r
377 QGridLayout dateLayout = new QGridLayout();
\r
378 titleLabel.setReadOnly(false);
\r
379 titleLabel.editingFinished.connect(this, "titleEdited()");
\r
380 browser.page().contentsChanged.connect(this, "contentChanged()");
\r
381 browser.page().selectionChanged.connect(this, "selectionChanged()");
\r
382 browser.page().mainFrame().javaScriptWindowObjectCleared.connect(this,
\r
383 "exposeToJavascript()");
\r
385 notebookBox.activated.connect(this, "notebookChanged()");
\r
386 resourceSignal = new NoteResourceSignal();
\r
388 QHBoxLayout tagLayout = new QHBoxLayout();
\r
389 v.addWidget(titleLabel, 0);
\r
390 notebookLayout.addRow(notebookLabel, notebookBox);
\r
391 tagLayout.addLayout(notebookLayout, 0);
\r
392 tagLayout.stretch(4);
\r
393 tagLayout.addWidget(tagLabel, 0);
\r
394 tagLayout.addWidget(tagEdit, 1);
\r
395 v.addLayout(tagLayout);
\r
397 QHBoxLayout urlLayout = new QHBoxLayout();
\r
398 urlLayout.addWidget(urlLabel, 0);
\r
399 urlLayout.addWidget(urlText, 0);
\r
400 v.addLayout(urlLayout);
\r
402 QHBoxLayout authorLayout = new QHBoxLayout();
\r
403 authorLayout.addWidget(authorLabel, 0);
\r
404 authorLayout.addWidget(authorText, 0);
\r
405 authorLayout.addWidget(geoBox);
\r
406 v.addLayout(authorLayout);
\r
408 dateLayout.addWidget(createdLabel, 0, 0);
\r
409 dateLayout.addWidget(createdDate, 0, 1);
\r
410 dateLayout.addWidget(createdTime, 0, 2);
\r
411 dateLayout.setColumnStretch(9, 100);
\r
412 dateLayout.addWidget(alteredLabel, 0, 3);
\r
413 dateLayout.addWidget(alteredDate, 0, 4);
\r
414 dateLayout.addWidget(alteredTime, 0, 5);
\r
415 dateLayout.addWidget(subjectLabel, 0, 6);
\r
416 dateLayout.addWidget(subjectDate, 0, 7);
\r
417 dateLayout.addWidget(subjectTime, 0, 8);
\r
418 v.addLayout(dateLayout, 0);
\r
420 undoButton = newEditorButton("undo", tr("Undo Change"));
\r
421 redoButton = newEditorButton("redo", tr("Redo Change"));
\r
422 cutButton = newEditorButton("cut", tr("Cut"));
\r
423 copyButton = newEditorButton("copy", tr("Copy"));
\r
424 pasteButton = newEditorButton("paste", tr("Paste"));
\r
425 boldButton = newEditorButton("bold", tr("Bold"));
\r
426 underlineButton = newEditorButton("underline", tr("Underline"));
\r
427 italicButton = newEditorButton("italic", tr("Italic"));
\r
429 rightAlignButton = newEditorButton("justifyRight", tr("Right Align"));
\r
430 leftAlignButton = newEditorButton("justifyLeft", tr("Left Align"));
\r
431 centerAlignButton = newEditorButton("justifyCenter", tr("Center Align"));
\r
433 strikethroughButton = newEditorButton("strikethrough", tr("Strikethrough"));
\r
434 hlineButton = newEditorButton("hline", tr("Insert Horizontal Line"));
\r
435 indentButton = newEditorButton("indent", tr("Shift Right"));
\r
436 outdentButton = newEditorButton("outdent", tr("Shift Left"));
\r
437 bulletListButton = newEditorButton("bulletList", tr("Bullet List"));
\r
438 numberListButton = newEditorButton("numberList", tr("Number List"));
\r
439 spellCheckButton = newEditorButton("spellCheck", tr("Spell Check"));
\r
440 todoButton = newEditorButton("todo", tr("To-do"));
\r
443 buttonLayout = new EditorButtonBar();
\r
444 v.addWidget(buttonLayout);
\r
446 undoAction = buttonLayout.addWidget(undoButton);
\r
447 buttonLayout.toggleUndoVisible.triggered.connect(this, "toggleUndoVisible(Boolean)");
\r
448 redoAction = buttonLayout.addWidget(redoButton);
\r
449 buttonLayout.toggleRedoVisible.triggered.connect(this, "toggleRedoVisible(Boolean)");
\r
451 buttonLayout.addWidget(newSeparator());
\r
452 cutAction = buttonLayout.addWidget(cutButton);
\r
453 buttonLayout.toggleCutVisible.triggered.connect(this, "toggleCutVisible(Boolean)");
\r
454 copyAction = buttonLayout.addWidget(copyButton);
\r
455 buttonLayout.toggleCopyVisible.triggered.connect(this, "toggleCopyVisible(Boolean)");
\r
456 pasteAction = buttonLayout.addWidget(pasteButton);
\r
457 buttonLayout.togglePasteVisible.triggered.connect(this, "togglePasteVisible(Boolean)");
\r
459 buttonLayout.addWidget(newSeparator());
\r
460 boldAction = buttonLayout.addWidget(boldButton);
\r
461 buttonLayout.toggleBoldVisible.triggered.connect(this, "toggleBoldVisible(Boolean)");
\r
462 italicAction = buttonLayout.addWidget(italicButton);
\r
463 buttonLayout.toggleItalicVisible.triggered.connect(this, "toggleItalicVisible(Boolean)");
\r
464 underlineAction = buttonLayout.addWidget(underlineButton);
\r
465 buttonLayout.toggleUnderlineVisible.triggered.connect(this, "toggleUnderlineVisible(Boolean)");
\r
466 strikethroughAction = buttonLayout.addWidget(strikethroughButton);
\r
467 buttonLayout.toggleStrikethroughVisible.triggered.connect(this, "toggleStrikethroughVisible(Boolean)");
\r
470 buttonLayout.addWidget(newSeparator());
\r
471 leftAlignAction = buttonLayout.addWidget(leftAlignButton);
\r
472 buttonLayout.toggleLeftAlignVisible.triggered.connect(this, "toggleLeftAlignVisible(Boolean)");
\r
473 centerAlignAction = buttonLayout.addWidget(centerAlignButton);
\r
474 buttonLayout.toggleCenterAlignVisible.triggered.connect(this, "toggleCenterAlignVisible(Boolean)");
\r
475 rightAlignAction = buttonLayout.addWidget(rightAlignButton);
\r
476 buttonLayout.toggleRightAlignVisible.triggered.connect(this, "toggleRightAlignVisible(Boolean)");
\r
478 buttonLayout.addWidget(newSeparator());
\r
479 hlineAction = buttonLayout.addWidget(hlineButton);
\r
480 buttonLayout.toggleHLineVisible.triggered.connect(this, "toggleHLineVisible(Boolean)");
\r
482 indentAction = buttonLayout.addWidget(indentButton);
\r
483 buttonLayout.toggleIndentVisible.triggered.connect(this, "toggleIndentVisible(Boolean)");
\r
484 outdentAction = buttonLayout.addWidget(outdentButton);
\r
485 buttonLayout.toggleOutdentVisible.triggered.connect(this, "toggleOutdentVisible(Boolean)");
\r
486 bulletListAction = buttonLayout.addWidget(bulletListButton);
\r
487 buttonLayout.toggleBulletListVisible.triggered.connect(this, "toggleBulletListVisible(Boolean)");
\r
488 numberListAction = buttonLayout.addWidget(numberListButton);
\r
489 buttonLayout.toggleNumberListVisible.triggered.connect(this, "toggleNumberListVisible(Boolean)");
\r
491 // Setup the font & font size combo boxes
\r
492 buttonLayout.addWidget(newSeparator());
\r
493 fontList = new QComboBox();
\r
494 fontSize = new QComboBox();
\r
495 fontList.setToolTip("Font");
\r
496 fontSize.setToolTip("Font Size");
\r
497 fontList.activated.connect(this, "fontChanged(String)");
\r
498 fontSize.activated.connect(this, "fontSizeChanged(String)");
\r
499 fontListAction = buttonLayout.addWidget(fontList);
\r
500 buttonLayout.toggleFontVisible.triggered.connect(this, "toggleFontListVisible(Boolean)");
\r
501 fontSizeAction = buttonLayout.addWidget(fontSize);
\r
502 buttonLayout.toggleFontSizeVisible.triggered.connect(this, "toggleFontSizeVisible(Boolean)");
\r
503 QFontDatabase fonts = new QFontDatabase();
\r
504 List<String> fontFamilies = fonts.families();
\r
505 for (int i = 0; i < fontFamilies.size(); i++) {
\r
506 fontList.addItem(fontFamilies.get(i));
\r
508 loadFontSize(fontFamilies.get(i));
\r
512 // buttonLayout.addWidget(newSeparator(), 0);
\r
513 fontColor = newToolButton("fontColor", tr("Font Color"));
\r
514 fontColorMenu = new ColorMenu(this);
\r
515 fontColor.setMenu(fontColorMenu.getMenu());
\r
516 fontColor.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
517 fontColor.setAutoRaise(false);
\r
518 fontColorMenu.getMenu().triggered.connect(this, "fontColorClicked()");
\r
519 fontColorAction = buttonLayout.addWidget(fontColor);
\r
520 buttonLayout.toggleFontColorVisible.triggered.connect(this, "toggleFontColorVisible(Boolean)");
\r
521 fontHilight = newToolButton("fontHilight", tr("Font Hilight Color"));
\r
522 fontHilight.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
523 fontHilight.setAutoRaise(false);
\r
524 fontHilightColorMenu = new ColorMenu(this);
\r
525 fontHilightColorMenu.setDefault(QColor.yellow);
\r
526 fontHilight.setMenu(fontHilightColorMenu.getMenu());
\r
527 fontHilightColorMenu.getMenu().triggered.connect(this, "fontHilightClicked()");
\r
528 fontHilightAction = buttonLayout.addWidget(fontHilight);
\r
529 fontHilightColorMenu.setDefault(QColor.yellow);
\r
530 buttonLayout.toggleFontHilight.triggered.connect(this, "toggleFontHilightVisible(Boolean)");
\r
532 spellCheckAction = buttonLayout.addWidget(spellCheckButton);
\r
533 buttonLayout.toggleNumberListVisible.triggered.connect(this, "spellCheckClicked()");
\r
534 buttonLayout.toggleSpellCheck.triggered.connect(this, "toggleSpellCheckVisible(Boolean)");
\r
536 todoAction = buttonLayout.addWidget(todoButton);
\r
537 buttonLayout.toggleNumberListVisible.triggered.connect(this, "todoClicked()");
\r
538 buttonLayout.toggleTodo.triggered.connect(this, "toggleTodoVisible(Boolean)");
\r
541 // buttonLayout.addWidget(new QLabel(), 1);
\r
542 v.addWidget(browser, 1);
\r
545 browser.downloadAttachmentRequested.connect(this,
\r
546 "downloadAttachment(QNetworkRequest)");
\r
547 browser.downloadImageRequested.connect(this,
\r
548 "downloadImage(QNetworkRequest)");
\r
549 setTabOrder(notebookBox, tagEdit);
\r
550 setTabOrder(tagEdit, browser);
\r
552 focusNoteShortcut = new QShortcut(this);
\r
553 setupShortcut(focusNoteShortcut, "Focus_Note");
\r
554 focusNoteShortcut.activated.connect(this, "focusNote()");
\r
555 focusTitleShortcut = new QShortcut(this);
\r
556 setupShortcut(focusTitleShortcut, "Focus_Title");
\r
557 focusTitleShortcut.activated.connect(this, "focusTitle()");
\r
558 focusTagShortcut = new QShortcut(this);
\r
559 setupShortcut(focusTagShortcut, "Focus_Tag");
\r
560 focusTagShortcut.activated.connect(this, "focusTag()");
\r
561 focusAuthorShortcut = new QShortcut(this);
\r
562 setupShortcut(focusAuthorShortcut, "Focus_Author");
\r
563 focusAuthorShortcut.activated.connect(this, "focusAuthor()");
\r
564 focusUrlShortcut = new QShortcut(this);
\r
565 setupShortcut(focusUrlShortcut, "Focus_Url");
\r
566 focusUrlShortcut.activated.connect(this, "focusUrl()");
\r
568 browser.page().mainFrame().setTextSizeMultiplier(Global.getTextSizeMultiplier());
\r
569 browser.page().mainFrame().setZoomFactor(Global.getZoomFactor());
\r
571 previewPageList = new HashMap<String,Integer>();
\r
573 browser.page().microFocusChanged.connect(this, "microFocusChanged()");
\r
577 QPalette pal = new QPalette();
\r
578 pal.setColor(ColorRole.Text, QColor.black);
\r
579 titleLabel.setPalette(pal);
\r
580 authorText.setPalette(pal);
\r
581 authorLabel.setPalette(pal);
\r
582 urlLabel.setPalette(pal);
\r
583 urlText.setPalette(pal);
\r
584 createdDate.setPalette(pal);
\r
585 createdTime.setPalette(pal);
\r
586 alteredDate.setPalette(pal);
\r
587 alteredTime.setPalette(pal);
\r
588 subjectDate.setPalette(pal);
\r
589 subjectTime.setPalette(pal);
\r
590 tagEdit.setPalette(pal);
\r
591 notebookBox.setPalette(pal);
\r
593 logger.log(logger.HIGH, "Browser setup complete");
\r
598 private void setupShortcut(QShortcut action, String text) {
\r
599 if (!Global.shortcutKeys.containsAction(text))
\r
601 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
\r
607 // Getter for the QWebView
\r
608 public QWebView getBrowser() {
\r
612 // Block signals while loading data or things are flagged as dirty by
\r
614 public void loadingData(boolean val) {
\r
615 logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val);
\r
616 notebookBox.blockSignals(val);
\r
617 browser.page().blockSignals(val);
\r
618 browser.page().mainFrame().blockSignals(val);
\r
619 titleLabel.blockSignals(val);
\r
620 alteredDate.blockSignals(val);
\r
621 alteredTime.blockSignals(val);
\r
622 createdTime.blockSignals(val);
\r
623 createdDate.blockSignals(val);
\r
624 subjectDate.blockSignals(val);
\r
625 subjectTime.blockSignals(val);
\r
626 urlText.blockSignals(val);
\r
627 authorText.blockSignals(val);
\r
629 exposeToJavascript();
\r
630 logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val);
\r
634 public void setReadOnly(boolean v) {
\r
636 titleLabel.setEnabled(!v);
\r
637 notebookBox.setEnabled(!v);
\r
638 tagEdit.setEnabled(!v);
\r
639 authorLabel.setEnabled(!v);
\r
640 geoBox.setEnabled(!v);
\r
641 urlText.setEnabled(!v);
\r
642 createdDate.setEnabled(!v);
\r
643 subjectDate.setEnabled(!v);
\r
644 alteredDate.setEnabled(!v);
\r
645 authorText.setEnabled(!v);
\r
646 createdTime.setEnabled(!v);
\r
647 alteredTime.setEnabled(!v);
\r
648 subjectTime.setEnabled(!v);
\r
649 getBrowser().setEnabled(true);
\r
652 // expose this class to Javascript on the web page
\r
653 private void exposeToJavascript() {
\r
654 browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this);
\r
657 // Custom event queue
\r
659 public boolean event(QEvent e) {
\r
660 if (e.type().equals(QEvent.Type.FocusOut)) {
\r
661 logger.log(logger.EXTREME, "Focus lost");
\r
664 return super.event(e);
\r
667 // clear out browser
\r
668 public void clear() {
\r
669 logger.log(logger.EXTREME, "Entering BrowserWindow.clear()");
\r
671 browser.setContent(new QByteArray());
\r
672 tagEdit.setText("");
\r
673 tagEdit.tagCompleter.reset();
\r
674 urlLabel.setText(tr("Source URL:"));
\r
675 titleLabel.setText("");
\r
676 logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()");
\r
679 // get/set current note
\r
680 public void setNote(Note n) {
\r
684 saveNoteTitle = n.getTitle();
\r
688 public Note getNote() {
\r
689 return currentNote;
\r
692 // New Editor Button
\r
693 private QPushButton newEditorButton(String name, String toolTip) {
\r
694 QPushButton button = new QPushButton();
\r
695 // QIcon icon = new QIcon(iconPath + name + ".gif");
\r
696 QIcon icon = new QIcon(iconPath + name + ".png");
\r
697 button.setIcon(icon);
\r
698 button.setToolTip(toolTip);
\r
699 button.clicked.connect(this, name + "Clicked()");
\r
702 // New Editor Button
\r
703 private QToolButton newToolButton(String name, String toolTip) {
\r
704 QToolButton button = new QToolButton();
\r
705 // QIcon icon = new QIcon(iconPath + name + ".gif");
\r
706 QIcon icon = new QIcon(iconPath + name + ".png");
\r
707 button.setIcon(icon);
\r
708 button.setToolTip(toolTip);
\r
709 button.clicked.connect(this, name + "Clicked()");
\r
714 private QLabel newSeparator() {
\r
715 return new QLabel(" ");
\r
718 // Set the title in the window
\r
719 public void setTitle(String t) {
\r
720 titleLabel.setText(t);
\r
725 // Return the current text title
\r
726 public String getTitle() {
\r
727 return titleLabel.text();
\r
730 // Set the tag name string
\r
731 public void setTag(String t) {
\r
733 tagEdit.setText(t);
\r
734 tagEdit.tagCompleter.reset();
\r
737 // Set the source URL
\r
738 public void setUrl(String t) {
\r
739 urlLabel.setText(tr("Source URL:\t"));
\r
740 urlText.setText(t);
\r
743 // The user want's to launch a web browser on the source of the URL
\r
744 public void sourceUrlClicked() {
\r
745 // Make sure we have a valid URL
\r
746 if (urlText.text().trim().equals(""))
\r
749 String url = urlText.text();
\r
750 if (!url.toLowerCase().startsWith(tr("http://")))
\r
751 url = tr("http://") +url;
\r
753 if (!QDesktopServices.openUrl(new QUrl(url))) {
\r
754 logger.log(logger.LOW, "Error opening file :" +url);
\r
758 public void setAuthor(String t) {
\r
759 authorLabel.setText(tr("Author:\t"));
\r
760 authorText.setText(t);
\r
763 // Set the creation date
\r
764 public void setCreation(long date) {
\r
765 QDateTime dt = new QDateTime();
\r
766 dt.setTime_t((int) (date / 1000));
\r
767 createdDate.setDateTime(dt);
\r
768 createdTime.setDateTime(dt);
\r
769 createdDate.setDisplayFormat(Global.getDateFormat());
\r
770 createdTime.setDisplayFormat(Global.getTimeFormat());
\r
773 // Set the creation date
\r
774 public void setAltered(long date) {
\r
775 QDateTime dt = new QDateTime();
\r
776 dt.setTime_t((int) (date / 1000));
\r
777 alteredDate.setDateTime(dt);
\r
778 alteredTime.setDateTime(dt);
\r
779 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
780 alteredTime.setDisplayFormat(Global.getTimeFormat());
\r
783 // Set the subject date
\r
784 public void setSubjectDate(long date) {
\r
785 QDateTime dt = new QDateTime();
\r
786 dt.setTime_t((int) (date / 1000));
\r
787 subjectDate.setDateTime(dt);
\r
788 subjectTime.setDateTime(dt);
\r
789 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
790 subjectTime.setDisplayFormat(Global.getTimeFormat());
\r
793 // Toggle the extended attribute information
\r
794 public void toggleInformation() {
\r
796 extendedOn = false;
\r
800 urlLabel.setVisible(extendedOn);
\r
801 urlText.setVisible(extendedOn);
\r
802 authorText.setVisible(extendedOn);
\r
803 geoBox.setVisible(extendedOn);
\r
804 authorLabel.setVisible(extendedOn);
\r
805 createdDate.setVisible(extendedOn);
\r
806 createdTime.setVisible(extendedOn);
\r
807 createdLabel.setVisible(extendedOn);
\r
808 alteredLabel.setVisible(extendedOn);
\r
809 alteredDate.setVisible(extendedOn);
\r
810 alteredTime.setVisible(extendedOn);
\r
811 //notebookBox.setVisible(extendedOn);
\r
812 notebookLabel.setVisible(extendedOn);
\r
813 subjectLabel.setVisible(extendedOn);
\r
814 subjectDate.setVisible(extendedOn);
\r
815 subjectTime.setVisible(extendedOn);
\r
818 public void hideButtons() {
\r
820 undoButton.parentWidget().setVisible(false);
\r
821 buttonsVisible = false;
\r
825 // Is the extended view on?
\r
826 public boolean isExtended() {
\r
830 // Listener for when a link is clicked
\r
831 @SuppressWarnings("unused")
\r
832 private void openFile() {
\r
833 logger.log(logger.EXTREME, "Starting openFile()");
\r
834 File fileHandle = new File(selectedFile);
\r
835 URI fileURL = fileHandle.toURI();
\r
836 String localURL = fileURL.toString();
\r
837 QUrl url = new QUrl(localURL);
\r
838 QFile file = new QFile(selectedFile);
\r
840 logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName());
\r
841 fileWatcher.addPath(file.fileName());
\r
843 if (!QDesktopServices.openUrl(url)) {
\r
844 logger.log(logger.LOW, "Error opening file :" +url);
\r
849 // Listener for when a link is clicked
\r
850 @SuppressWarnings("unused")
\r
851 private void linkClicked(QUrl url) {
\r
852 logger.log(logger.EXTREME, "URL Clicked: " +url.toString());
\r
853 if (url.toString().substring(0,8).equals("nnres://")) {
\r
854 logger.log(logger.EXTREME, "URL is NN resource");
\r
855 if (url.toString().endsWith("/vnd.evernote.ink")) {
\r
856 logger.log(logger.EXTREME, "Unable to open ink note");
\r
857 QMessageBox.information(this, tr("Unable Open"), tr("This is an ink note.\n"+
\r
858 "Ink notes are not supported since Evernote has not\n published any specifications on them\n" +
\r
859 "and I'm too lazy to figure them out by myself."));
\r
862 String fullName = url.toString().substring(8);
\r
863 int index = fullName.indexOf(".");
\r
867 type = fullName.substring(index+1);
\r
868 guid = fullName.substring(0,index);
\r
870 index = guid.indexOf(Global.attachmentNameDelimeter);
\r
872 guid = guid.substring(0,index);
\r
874 List<Resource> resList = currentNote.getResources();
\r
875 Resource res = null;
\r
876 for (int i=0; i<resList.size(); i++) {
\r
877 if (resList.get(i).getGuid().equals(guid)) {
\r
878 res = resList.get(i);
\r
883 String resGuid = Global.resourceMap.get(guid);
\r
884 if (resGuid != null)
\r
885 res = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, true);
\r
889 if (res.getAttributes() != null &&
\r
890 res.getAttributes().getFileName() != null &&
\r
891 !res.getAttributes().getFileName().trim().equals(""))
\r
892 fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();
\r
894 fileName = res.getGuid()+"."+type;
\r
895 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
896 QFile.OpenMode mode = new QFile.OpenMode();
\r
897 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
898 boolean openResult = file.open(mode);
\r
899 logger.log(logger.EXTREME, "File opened:" +openResult);
\r
900 QDataStream out = new QDataStream(file);
\r
901 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);
\r
902 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
904 logger.log(logger.EXTREME, "Writing resource");
\r
905 out.writeBytes(binData.toByteArray());
\r
908 String whichOS = System.getProperty("os.name");
\r
909 if (whichOS.contains("Windows"))
\r
910 url.setUrl("file:///"+file.fileName());
\r
912 url.setUrl("file://"+file.fileName());
\r
913 // fileWatcher.removePath(file.fileName());
\r
914 logger.log(logger.EXTREME, "Adding file watcher " +file.fileName());
\r
915 fileWatcher.addPath(file.fileName());
\r
917 // If we can't open it, then prompt the user to save it.
\r
918 if (!QDesktopServices.openUrl(url)) {
\r
919 logger.log(logger.EXTREME, "We can't handle this. Where do we put it?");
\r
920 QFileDialog dialog = new QFileDialog();
\r
922 if (dialog.exec()!=0) {
\r
923 List<String> fileNames = dialog.selectedFiles(); //gets all selected filenames
\r
924 if (fileNames.size() == 0)
\r
926 String sf = fileNames.get(0);
\r
927 QFile saveFile = new QFile(sf);
\r
928 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
929 saveFile.open(mode);
\r
930 QDataStream saveOut = new QDataStream(saveFile);
\r
931 saveOut.writeBytes(binData.toByteArray());
\r
939 logger.log(logger.EXTREME, "Launching URL");
\r
940 QDesktopServices.openUrl(url);
\r
943 // Listener for when BOLD is clicked
\r
944 @SuppressWarnings("unused")
\r
945 private void undoClicked() {
\r
946 browser.page().triggerAction(WebAction.Undo);
\r
947 browser.setFocus();
\r
950 // Listener for when BOLD is clicked
\r
951 @SuppressWarnings("unused")
\r
952 private void redoClicked() {
\r
953 browser.page().triggerAction(WebAction.Redo);
\r
954 browser.setFocus();
\r
957 // Listener for when BOLD is clicked
\r
958 @SuppressWarnings("unused")
\r
959 private void boldClicked() {
\r
960 browser.page().triggerAction(WebAction.ToggleBold);
\r
961 microFocusChanged();
\r
962 browser.setFocus();
\r
965 // Listener for when Italics is clicked
\r
966 @SuppressWarnings("unused")
\r
967 private void italicClicked() {
\r
968 browser.page().triggerAction(WebAction.ToggleItalic);
\r
969 microFocusChanged();
\r
970 browser.setFocus();
\r
973 // Listener for when UNDERLINE is clicked
\r
974 @SuppressWarnings("unused")
\r
975 private void underlineClicked() {
\r
976 browser.page().triggerAction(WebAction.ToggleUnderline);
\r
977 microFocusChanged();
\r
978 browser.setFocus();
\r
981 // Listener for when Strikethrough is clicked
\r
982 @SuppressWarnings("unused")
\r
983 private void strikethroughClicked() {
\r
984 browser.page().mainFrame().evaluateJavaScript(
\r
985 "document.execCommand('strikeThrough', false, '');");
\r
986 browser.setFocus();
\r
989 // Listener for when cut is clicked
\r
990 @SuppressWarnings("unused")
\r
991 private void cutClicked() {
\r
992 browser.page().triggerAction(WebAction.Cut);
\r
993 browser.setFocus();
\r
996 // Listener when COPY is clicked
\r
997 @SuppressWarnings("unused")
\r
998 private void copyClicked() {
\r
999 browser.page().triggerAction(WebAction.Copy);
\r
1000 browser.setFocus();
\r
1003 // Listener when PASTE is clicked
\r
1004 public void pasteClicked() {
\r
1005 logger.log(logger.EXTREME, "Paste Clicked");
\r
1006 if (forceTextPaste) {
\r
1007 pasteWithoutFormattingClicked();
\r
1010 QClipboard clipboard = QApplication.clipboard();
\r
1011 QMimeData mime = clipboard.mimeData();
\r
1013 // String x = mime.html();
\r
1015 if (mime.hasImage()) {
\r
1016 logger.log(logger.EXTREME, "Image paste found");
\r
1017 browser.setFocus();
\r
1018 insertImage(mime);
\r
1019 browser.setFocus();
\r
1023 if (mime.hasUrls()) {
\r
1024 logger.log(logger.EXTREME, "URL paste found");
\r
1026 browser.setFocus();
\r
1030 String text = mime.html();
\r
1031 if (text.contains("en-tag") && mime.hasHtml()) {
\r
1032 logger.log(logger.EXTREME, "Intra-note paste found");
\r
1033 text = fixInternotePaste(text);
\r
1034 mime.setHtml(text);
\r
1035 clipboard.setMimeData(mime);
\r
1038 logger.log(logger.EXTREME, "Final paste choice encountered");
\r
1039 browser.page().triggerAction(WebAction.Paste);
\r
1040 browser.setFocus();
\r
1044 // Paste text without formatting
\r
1045 private void pasteWithoutFormattingClicked() {
\r
1046 logger.log(logger.EXTREME, "Paste without format clipped");
\r
1047 QClipboard clipboard = QApplication.clipboard();
\r
1048 QMimeData mime = clipboard.mimeData();
\r
1049 if (!mime.hasText())
\r
1051 String text = mime.text();
\r
1052 clipboard.setText(text);
\r
1053 browser.page().triggerAction(WebAction.Paste);
\r
1054 QApplication.clipboard().setMimeData(mime);
\r
1055 browser.setFocus();
\r
1059 // insert date/time
\r
1060 @SuppressWarnings("unused")
\r
1061 private void insertDateTime() {
\r
1062 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
\r
1063 String dateTimeFormat = new String(fmt);
\r
1064 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
\r
1065 Calendar cal = Calendar.getInstance();
\r
1067 browser.page().mainFrame().evaluateJavaScript(
\r
1068 "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");
\r
1070 browser.setFocus();
\r
1074 // Listener when Left is clicked
\r
1075 @SuppressWarnings("unused")
\r
1076 private void justifyLeftClicked() {
\r
1077 browser.page().mainFrame().evaluateJavaScript(
\r
1078 "document.execCommand('JustifyLeft', false, '');");
\r
1079 browser.setFocus();
\r
1082 // Listener when Center is clicked
\r
1083 @SuppressWarnings("unused")
\r
1084 private void justifyCenterClicked() {
\r
1085 browser.page().mainFrame().evaluateJavaScript(
\r
1086 "document.execCommand('JustifyCenter', false, '');");
\r
1087 browser.setFocus();
\r
1090 // Listener when Left is clicked
\r
1091 @SuppressWarnings("unused")
\r
1092 private void justifyRightClicked() {
\r
1093 browser.page().mainFrame().evaluateJavaScript(
\r
1094 "document.execCommand('JustifyRight', false, '');");
\r
1095 browser.setFocus();
\r
1098 // Listener when HLINE is clicked
\r
1099 @SuppressWarnings("unused")
\r
1100 private void hlineClicked() {
\r
1101 browser.page().mainFrame().evaluateJavaScript(
\r
1102 "document.execCommand('insertHorizontalRule', false, '');");
\r
1103 browser.setFocus();
\r
1106 // Listener when outdent is clicked
\r
1107 private void outdentClicked() {
\r
1108 browser.page().mainFrame().evaluateJavaScript(
\r
1109 "document.execCommand('outdent', false, '');");
\r
1110 browser.setFocus();
\r
1113 // Listener when a bullet list is clicked
\r
1114 @SuppressWarnings("unused")
\r
1115 private void bulletListClicked() {
\r
1116 browser.page().mainFrame().evaluateJavaScript(
\r
1117 "document.execCommand('InsertUnorderedList', false, '');");
\r
1118 browser.setFocus();
\r
1121 // Listener when a bullet list is clicked
\r
1122 @SuppressWarnings("unused")
\r
1123 private void numberListClicked() {
\r
1124 browser.page().mainFrame().evaluateJavaScript(
\r
1125 "document.execCommand('InsertOrderedList', false, '');");
\r
1126 browser.setFocus();
\r
1129 // Listener when indent is clicked
\r
1130 private void indentClicked() {
\r
1131 browser.page().mainFrame().evaluateJavaScript(
\r
1132 "document.execCommand('indent', false, '');");
\r
1133 browser.setFocus();
\r
1136 // Listener when the font name is changed
\r
1137 @SuppressWarnings("unused")
\r
1138 private void fontChanged(String font) {
\r
1139 browser.page().mainFrame().evaluateJavaScript(
\r
1140 "document.execCommand('fontName',false,'" + font + "');");
\r
1141 browser.setFocus();
\r
1144 // Listener when a font size is changed
\r
1145 @SuppressWarnings("unused")
\r
1146 private void fontSizeChanged(String font) {
\r
1147 String text = browser.selectedText();
\r
1148 if (text.trim().equalsIgnoreCase(""))
\r
1151 String selectedText = browser.selectedText();
\r
1152 String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";
\r
1153 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1154 browser.page().mainFrame().evaluateJavaScript(script);
\r
1155 /* browser.page().mainFrame().evaluateJavaScript(
\r
1156 "document.execCommand('fontSize',false,'"
\r
1159 browser.setFocus();
\r
1162 // Load the font combo box based upon the font selected
\r
1163 private void loadFontSize(String name) {
\r
1164 QFontDatabase db = new QFontDatabase();
\r
1166 List<Integer> points = db.pointSizes(name);
\r
1167 for (int i=0; i<points.size(); i++) {
\r
1168 fontSize.addItem(points.get(i).toString());
\r
1171 fontSize.addItem("x-small");
\r
1172 fontSize.addItem("small");
\r
1173 fontSize.addItem("medium");
\r
1174 fontSize.addItem("large");
\r
1175 fontSize.addItem("x-large");
\r
1176 fontSize.addItem("xx-large");
\r
1177 fontSize.addItem("xxx-large");
\r
1181 // Listener when a font size is changed
\r
1182 @SuppressWarnings("unused")
\r
1183 private void fontColorClicked() {
\r
1184 // QColorDialog dialog = new QColorDialog();
\r
1185 // QColor color = QColorDialog.getColor();
\r
1186 QColor color = fontColorMenu.getColor();
\r
1187 if (color.isValid())
\r
1188 browser.page().mainFrame().evaluateJavaScript(
\r
1189 "document.execCommand('foreColor',false,'" + color.name()
\r
1191 browser.setFocus();
\r
1194 // Listener for when a background color change is requested
\r
1195 @SuppressWarnings("unused")
\r
1196 private void fontHilightClicked() {
\r
1197 // QColorDialog dialog = new QColorDialog();
\r
1198 // QColor color = QColorDialog.getColor();
\r
1199 QColor color = fontHilightColorMenu.getColor();
\r
1200 if (color.isValid())
\r
1201 browser.page().mainFrame().evaluateJavaScript(
\r
1202 "document.execCommand('backColor',false,'" + color.name()
\r
1204 browser.setFocus();
\r
1207 // Listener for when a background color change is requested
\r
1208 @SuppressWarnings("unused")
\r
1209 private void superscriptClicked() {
\r
1210 browser.page().mainFrame().evaluateJavaScript(
\r
1211 "document.execCommand('superscript');");
\r
1212 browser.setFocus();
\r
1215 // Listener for when a background color change is requested
\r
1216 @SuppressWarnings("unused")
\r
1217 private void subscriptClicked() {
\r
1218 browser.page().mainFrame().evaluateJavaScript(
\r
1219 "document.execCommand('subscript');");
\r
1220 browser.setFocus();
\r
1222 // Insert a to-do checkbox
\r
1223 @SuppressWarnings("unused")
\r
1224 private void todoClicked() {
\r
1225 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1226 String script_start = new String(
\r
1227 "document.execCommand('insertHtml', false, '");
\r
1228 String script_end = new String("');");
\r
1229 String todo = new String(
\r
1230 "<input TYPE=\"CHECKBOX\" value=\"false\" " +
\r
1231 "onMouseOver=\"style.cursor=\\'hand\\'\" " +
\r
1232 "onClick=\"value=checked; window.jambi.contentChanged(); \" />");
\r
1233 browser.page().mainFrame().evaluateJavaScript(
\r
1234 script_start + todo + script_end);
\r
1235 browser.setFocus();
\r
1238 // Encrypt the selected text
\r
1239 @SuppressWarnings("unused")
\r
1240 private void encryptText() {
\r
1241 String text = browser.selectedText();
\r
1242 if (text.trim().equalsIgnoreCase(""))
\r
1244 text = new String(text.replaceAll("\n", "<br/>"));
\r
1246 EnCryptDialog dialog = new EnCryptDialog();
\r
1248 if (!dialog.okPressed()) {
\r
1252 EnCrypt crypt = new EnCrypt();
\r
1253 String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);
\r
1254 String decrypted = crypt.decrypt(encrypted, dialog.getPassword().trim(), 64);
\r
1256 if (encrypted.trim().equals("")) {
\r
1257 QMessageBox.information(this, tr("Error"), tr("Error Encrypting String"));
\r
1260 StringBuffer buffer = new StringBuffer(encrypted.length() + 100);
\r
1261 buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""
\r
1262 + dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");
\r
1263 buffer.append("contentEditable=\"false\" alt=\"");
\r
1264 buffer.append(encrypted);
\r
1265 buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png") +"\""));
\r
1266 Global.cryptCounter++;
\r
1267 buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");
\r
1268 buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");
\r
1269 buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString()
\r
1270 +"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&apos;")+"\\');\"");
\r
1271 buffer.append("style=\"display:block\" />");
\r
1273 String script_start = new String(
\r
1274 "document.execCommand('insertHtml', false, '");
\r
1275 String script_end = new String("');");
\r
1276 browser.page().mainFrame().evaluateJavaScript(
\r
1277 script_start + buffer.toString() + script_end);
\r
1281 // Insert a hyperlink
\r
1282 public void insertLink() {
\r
1283 logger.log(logger.EXTREME, "Inserting link");
\r
1284 String text = browser.selectedText();
\r
1285 if (text.trim().equalsIgnoreCase(""))
\r
1288 InsertLinkDialog dialog = new InsertLinkDialog(insertHyperlink);
\r
1289 if (currentHyperlink != null && currentHyperlink != "") {
\r
1290 dialog.setUrl(currentHyperlink);
\r
1293 if (!dialog.okPressed()) {
\r
1294 logger.log(logger.EXTREME, "Insert link canceled");
\r
1298 // Take care of inserting new links
\r
1299 if (insertHyperlink) {
\r
1300 String selectedText = browser.selectedText();
\r
1301 if (dialog.getUrl().trim().equals(""))
\r
1303 logger.log(logger.EXTREME, "Inserting link on text "+selectedText);
\r
1304 logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim());
\r
1305 String dUrl = StringUtils.replace(dialog.getUrl().trim(), "'", "\\'");
\r
1306 String url = "<a href=\"" +dUrl
\r
1307 +"\" title=" +dUrl
\r
1308 +" >"+selectedText +"</a>";
\r
1309 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1310 browser.page().mainFrame().evaluateJavaScript(script);
\r
1314 // Edit existing links
\r
1315 String js = new String( "function getCursorPos() {"
\r
1317 +"if (window.getSelection) {"
\r
1318 +" var selObj = window.getSelection();"
\r
1319 +" var selRange = selObj.getRangeAt(0);"
\r
1320 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1321 +" while(workingNode != null) { "
\r
1322 +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');"
\r
1323 +" workingNode = workingNode.parentNode;"
\r
1326 +"} getCursorPos();");
\r
1327 browser.page().mainFrame().evaluateJavaScript(js);
\r
1329 if (!dialog.getUrl().trim().equals("")) {
\r
1335 js = new String( "function getCursorPos() {"
\r
1337 +"if (window.getSelection) {"
\r
1338 +" var selObj = window.getSelection();"
\r
1339 +" var selRange = selObj.getRangeAt(0);"
\r
1340 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1341 +" while(workingNode != null) { "
\r
1342 +" if (workingNode.nodeName.toLowerCase()=='a') { "
\r
1343 +" workingNode.removeAttribute('href');"
\r
1344 +" workingNode.removeAttribute('title');"
\r
1345 +" var text = document.createTextNode(workingNode.innerText);"
\r
1346 +" workingNode.parentNode.insertBefore(text, workingNode);"
\r
1347 +" workingNode.parentNode.removeChild(workingNode);"
\r
1349 +" workingNode = workingNode.parentNode;"
\r
1352 +"} getCursorPos();");
\r
1353 browser.page().mainFrame().evaluateJavaScript(js);
\r
1362 public void insertTable() {
\r
1363 TableDialog dialog = new TableDialog();
\r
1365 if (!dialog.okPressed()) {
\r
1369 int cols = dialog.getCols();
\r
1370 int rows = dialog.getRows();
\r
1371 int width = dialog.getWidth();
\r
1372 boolean percent = dialog.isPercent();
\r
1374 String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();
\r
1376 newHTML = newHTML +"%";
\r
1377 newHTML = newHTML + "\"><tbody>";
\r
1379 for (int i=0; i<rows; i++) {
\r
1380 newHTML = newHTML +"<tr>";
\r
1381 for (int j=0; j<cols; j++) {
\r
1382 newHTML = newHTML +"<td> </td>";
\r
1384 newHTML = newHTML +"</tr>";
\r
1386 newHTML = newHTML+"</tbody></table>";
\r
1388 String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";
\r
1389 browser.page().mainFrame().evaluateJavaScript(script);
\r
1393 // Text content changed
\r
1394 @SuppressWarnings("unused")
\r
1395 private void selectionChanged() {
\r
1396 browser.encryptAction.setEnabled(true);
\r
1397 browser.insertLinkAction.setEnabled(true);
\r
1398 String scriptStart = "var selection_text = (window.getSelection()).toString();"
\r
1399 + "var range = (window.getSelection()).getRangeAt(0);"
\r
1400 + "var parent_html = range.commonAncestorContainer.innerHTML;"
\r
1401 + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"
\r
1402 + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"
\r
1403 + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"
\r
1404 + "var start = parent_html.indexOf(first_text);"
\r
1405 + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"
\r
1406 + "var value = parent_html.substring(start,end);"
\r
1407 + "window.jambi.saveSelectedText(value);" ;
\r
1408 browser.page().mainFrame().evaluateJavaScript(scriptStart);
\r
1412 public void saveSelectedText(String text) {
\r
1413 boolean enabled = true;
\r
1414 if (text.trim().length() == 0)
\r
1416 if (text.indexOf("en-tag=\"en-crypt\"") >= 0)
\r
1418 if (text.indexOf("<img en-tag=\"en-media\"") >= 0)
\r
1420 if (text.indexOf("<a en-tag=\"en-media\"") >= 0)
\r
1422 if (text.indexOf("<input ") >= 0)
\r
1425 browser.encryptAction.setEnabled(enabled);
\r
1426 browser.insertLinkAction.setEnabled(enabled);
\r
1427 // selectedText = text;
\r
1430 // Decrypt clicked text
\r
1431 public void decryptText(String id, String text, String hint) {
\r
1432 EnCrypt crypt = new EnCrypt();
\r
1433 String plainText = null;
\r
1434 Calendar currentTime = new GregorianCalendar();
\r
1435 Long l = new Long(currentTime.getTimeInMillis());
\r
1436 String slot = new String(Long.toString(l));
\r
1438 // First, try to decrypt with any keys we already have
\r
1439 for (int i=0; i<Global.passwordRemember.size(); i++) {
\r
1440 plainText = crypt.decrypt(text, Global.passwordRemember.get(i).getFirst(), 64);
\r
1441 if (plainText != null) {
\r
1442 slot = new String(Long.toString(l));
\r
1443 Global.passwordSafe.put(slot, Global.passwordRemember.get(i));
\r
1444 removeEncryption(id, plainText, false, slot);
\r
1450 EnDecryptDialog dialog = new EnDecryptDialog();
\r
1451 dialog.setHint(hint);
\r
1452 while (plainText == null || !dialog.okPressed()) {
\r
1454 if (!dialog.okPressed()) {
\r
1457 plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);
\r
1458 if (plainText == null) {
\r
1459 QMessageBox.warning(this, "Incorrect Password", "The password entered is not correct");
\r
1462 Pair<String,String> passwordPair = new Pair<String,String>();
\r
1463 passwordPair.setFirst(dialog.getPassword());
\r
1464 passwordPair.setSecond(dialog.getHint());
\r
1465 Global.passwordSafe.put(slot, passwordPair);
\r
1466 // removeEncryption(id, plainText.replaceAll("\n", "<br/>"), dialog.permanentlyDecrypt(), slot);
\r
1467 removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);
\r
1468 if (dialog.rememberPassword()) {
\r
1469 Pair<String, String> pair = new Pair<String,String>();
\r
1470 pair.setFirst(dialog.getPassword());
\r
1471 pair.setSecond(dialog.getHint());
\r
1472 Global.passwordRemember.add(pair);
\r
1477 // Get the editor tag line
\r
1478 public TagLineEdit getTagLine() {
\r
1482 // Modify a note's tags
\r
1483 @SuppressWarnings("unused")
\r
1484 private void modifyTags() {
\r
1485 TagAssign tagWindow = new TagAssign(allTags, currentTags, !conn.getNotebookTable().isLinked(currentNote.getNotebookGuid()));
\r
1487 if (tagWindow.okClicked()) {
\r
1488 currentTags.clear();
\r
1489 StringBuffer tagDisplay = new StringBuffer();
\r
1491 List<QListWidgetItem> newTags = tagWindow.getTagList()
\r
1493 for (int i = 0; i < newTags.size(); i++) {
\r
1494 currentTags.add(newTags.get(i).text());
\r
1495 tagDisplay.append(newTags.get(i).text());
\r
1496 if (i < newTags.size() - 1) {
\r
1497 tagDisplay.append(Global.tagDelimeter + " ");
\r
1500 tagEdit.setText(tagDisplay.toString());
\r
1501 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1505 // Tag line has been modified by typing text
\r
1506 @SuppressWarnings("unused")
\r
1507 private void modifyTagsTyping() {
\r
1508 String completionText = "";
\r
1509 if (tagEdit.currentCompleterSelection != null && !tagEdit.currentCompleterSelection.equals("")) {
\r
1510 completionText = tagEdit.currentCompleterSelection;
\r
1511 tagEdit.currentCompleterSelection = "";
\r
1514 if (tagEdit.text().equalsIgnoreCase(saveTagList))
\r
1517 // We know something has changed...
\r
1518 String oldTagArray[] = saveTagList.split(Global.tagDelimeter);
\r
1519 String newTagArray[];
\r
1520 if (!completionText.equals("")) {
\r
1521 String before = tagEdit.text().substring(0,tagEdit.cursorPosition());
\r
1522 int lastDelimiter = before.lastIndexOf(Global.tagDelimeter);
\r
1523 if (lastDelimiter > 0)
\r
1524 before = before.substring(0,before.lastIndexOf(Global.tagDelimeter));
\r
1527 String after = tagEdit.text().substring(tagEdit.cursorPosition());
\r
1528 newTagArray = (before+Global.tagDelimeter+completionText+Global.tagDelimeter+after).split(Global.tagDelimeter);
\r
1531 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1534 // Remove any traling or leading blanks
\r
1535 for (int i=0; i<newTagArray.length; i++)
\r
1536 newTagArray[i] = newTagArray[i].trim().replaceAll("^\\s+", "");;
\r
1538 // Remove any potential duplicates from the new list
\r
1539 for (int i=0; i<newTagArray.length; i++) {
\r
1540 boolean foundOnce = false;
\r
1541 for (int j=0; j<newTagArray.length; j++) {
\r
1542 if (newTagArray[j].equalsIgnoreCase(newTagArray[i])) {
\r
1546 newTagArray[j] = "";
\r
1551 List<String> newTagList = new ArrayList<String>();
\r
1552 List<String> oldTagList = new ArrayList<String>();
\r
1554 for (int i = 0; i < oldTagArray.length; i++)
\r
1555 if (!oldTagArray[i].trim().equals(""))
\r
1556 oldTagList.add(oldTagArray[i]);
\r
1557 for (int i = 0; i < newTagArray.length; i++)
\r
1558 if (!newTagArray[i].trim().equals(""))
\r
1559 newTagList.add(newTagArray[i]);
\r
1561 if (conn.getNotebookTable().isLinked(currentNote.getNotebookGuid())) {
\r
1562 for (int i=newTagList.size()-1; i>=0; i--) {
\r
1563 boolean found = false;
\r
1564 for (int j=0; j<allTags.size(); j++) {
\r
1565 if (allTags.get(j).getName().equalsIgnoreCase(newTagList.get(i))) {
\r
1571 newTagList.remove(i);
\r
1575 // Let's cleanup the appearance of the tag list
\r
1576 Collections.sort(newTagList);
\r
1577 String newDisplay = "";
\r
1578 for (int i=0; i<newTagList.size(); i++) {
\r
1579 newDisplay = newDisplay+newTagList.get(i);
\r
1580 if (i<newTagList.size()-1)
\r
1581 newDisplay = newDisplay+Global.tagDelimeter +" ";
\r
1583 tagEdit.blockSignals(true);
\r
1584 tagEdit.setText(newDisplay);
\r
1585 tagEdit.blockSignals(false);
\r
1587 // We now have lists of the new & old. Remove duplicates. If all
\r
1588 // are removed from both then nothing has really changed
\r
1589 for (int i = newTagList.size() - 1; i >= 0; i--) {
\r
1590 String nTag = newTagList.get(i);
\r
1591 for (int j = oldTagList.size() - 1; j >= 0; j--) {
\r
1592 String oTag = oldTagList.get(j);
\r
1593 if (oTag.equalsIgnoreCase(nTag)) {
\r
1594 oldTagList.remove(j);
\r
1595 newTagList.remove(i);
\r
1601 if (oldTagList.size() != 0 || newTagList.size() != 0) {
\r
1602 currentTags.clear();
\r
1603 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1604 for (int i = 0; i < newTagArray.length; i++)
\r
1605 if (!newTagArray[i].trim().equals(""))
\r
1606 currentTags.add(newTagArray[i].trim());
\r
1608 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1613 // Tab button was pressed
\r
1614 public void tabPressed() {
\r
1615 if (!insideList) {
\r
1616 String script_start = new String(
\r
1617 "document.execCommand('insertHtml', false, ' ');");
\r
1618 browser.page().mainFrame().evaluateJavaScript(script_start);
\r
1623 public void backtabPressed() {
\r
1628 public void setInsideList() {
\r
1629 insideList = true;
\r
1632 // The title has been edited
\r
1633 @SuppressWarnings("unused")
\r
1634 private void titleEdited() {
\r
1635 // If we don't have a good note, or if the current title
\r
1636 // matches the old title then we don't need to do anything
\r
1637 if (currentNote == null)
\r
1639 if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))
\r
1642 // If we have a real change, we need to save it.
\r
1643 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text());
\r
1644 currentNote.setTitle(titleLabel.text());
\r
1645 saveNoteTitle = titleLabel.text();
\r
1649 // Set the list of note tags
\r
1650 public void setAllTags(List<Tag> l) {
\r
1652 tagEdit.setTagList(l);
\r
1655 // Setter for the current tags
\r
1656 public void setCurrentTags(List<String> s) {
\r
1660 // Save the list of notebooks
\r
1661 public void setNotebookList(List<Notebook> n) {
\r
1663 loadNotebookList();
\r
1666 // Load the notebook list and select the current notebook
\r
1667 private void loadNotebookList() {
\r
1668 if (notebookBox.count() != 0)
\r
1669 notebookBox.clear();
\r
1670 if (notebookList == null)
\r
1673 for (int i = 0; i < notebookList.size(); i++) {
\r
1674 notebookBox.addItem(notebookList.get(i).getName());
\r
1675 if (currentNote != null) {
\r
1676 if (currentNote.getNotebookGuid().equals(
\r
1677 notebookList.get(i).getGuid())) {
\r
1678 notebookBox.setCurrentIndex(i);
\r
1685 // Set the notebook for a note
\r
1686 public void setNotebook(String notebook) {
\r
1687 currentNote.setNotebookGuid(notebook);
\r
1688 loadNotebookList();
\r
1691 // Get the contents of the editor
\r
1692 public String getContent() {
\r
1693 return browser.page().currentFrame().toHtml();
\r
1696 // The note contents have changed
\r
1697 public void contentChanged() {
\r
1698 String content = getContent();
\r
1700 noteSignal.noteChanged.emit(currentNote.getGuid(), content);
\r
1703 // The notebook selection has changed
\r
1704 @SuppressWarnings("unused")
\r
1705 private void notebookChanged() {
\r
1706 boolean changed = false;
\r
1707 String n = notebookBox.currentText();
\r
1708 for (int i = 0; i < notebookList.size(); i++) {
\r
1709 if (n.equals(notebookList.get(i).getName())) {
\r
1710 if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {
\r
1711 String guid = conn.getNotebookTable().findNotebookByName(n);
\r
1712 if (conn.getNotebookTable().isLinked(guid)) {
\r
1713 tagEdit.setText("");
\r
1714 noteSignal.tagsChanged.emit(currentNote.getGuid(), new ArrayList<String>());
\r
1715 FilterEditorTags t = new FilterEditorTags(conn, logger);
\r
1716 setAllTags(t.getValidTags(currentNote));
\r
1718 currentNote.setNotebookGuid(notebookList.get(i).getGuid());
\r
1721 i = notebookList.size();
\r
1725 // If the notebook changed, signal the update
\r
1727 noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote
\r
1728 .getNotebookGuid());
\r
1731 // Check the note title
\r
1732 private void checkNoteTitle() {
\r
1733 String text = browser.page().currentFrame().toPlainText();
\r
1734 if (saveNoteTitle.trim().equals("") || saveNoteTitle.trim().equals("Untitled Note")) {
\r
1735 int newLine = text.indexOf("\n");
\r
1736 if (newLine > 0) {
\r
1737 text = text.substring(0, newLine);
\r
1738 if (text.trim().equals(""))
\r
1739 text = tr("Untitled Note");
\r
1740 titleLabel.setText(text);
\r
1742 if (text.length() > Constants.EDAM_NOTE_TITLE_LEN_MAX)
\r
1743 titleLabel.setText(text.substring(0, Constants.EDAM_NOTE_TITLE_LEN_MAX));
\r
1745 titleLabel.blockSignals(true);
\r
1746 if (text.trim().equals(""))
\r
1747 titleLabel.setText(tr("Untitled Note"));
\r
1749 titleLabel.setText(text);
\r
1750 titleLabel.blockSignals(false);
\r
1753 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel
\r
1758 // Return the note contents so we can email them
\r
1759 public String getContentsToEmail() {
\r
1760 return browser.page().currentFrame().toPlainText().trim();
\r
1762 * int body = browser.page().currentFrame().toHtml().indexOf("<body>");
\r
1763 * String temp = browser.page().currentFrame().toHtml(); if (body == -1)
\r
1764 * temp = "<html><body><b>Test</b></body></html>"; else temp =
\r
1765 * "<html>"+temp.substring(body); return temp; // return
\r
1766 * urlEncode(browser.page().currentFrame().toHtml());
\r
1770 // Insert an image into the editor
\r
1771 private void insertImage(QMimeData mime) {
\r
1772 logger.log(logger.EXTREME, "Entering insertImage");
\r
1773 QImage img = (QImage) mime.imageData();
\r
1774 String script_start = new String(
\r
1775 "document.execCommand('insertHTML', false, '");
\r
1776 String script_end = new String("');");
\r
1778 long now = new Date().getTime();
\r
1779 String path = Global.getFileManager().getResDirPath(
\r
1780 (new Long(now).toString()) + ".jpg");
\r
1782 // This block is just a hack to make sure we wait at least 1ms so we
\r
1784 // have collisions on image names
\r
1785 long i = new Date().getTime();
\r
1787 i = new Date().getTime();
\r
1789 // Open the file & write the data
\r
1790 QFile tfile = new QFile(path);
\r
1791 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1792 if (!img.save(tfile)) {
\r
1798 Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);
\r
1799 if (newRes == null)
\r
1801 currentNote.getResources().add(newRes);
\r
1803 // do the actual insert into the note
\r
1804 StringBuffer buffer = new StringBuffer(100);
\r
1805 buffer.append("<img src=\"");
\r
1806 buffer.append(tfile.fileName());
\r
1807 buffer.append("\" en-tag=en-media type=\"image/jpeg\""
\r
1808 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1809 +" guid=\"" +newRes.getGuid() +"\""
\r
1810 // +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1811 +" onContextMenu=\"window.jambi.imageContextMenu(&." +tfile.fileName() +"&.);\""
\r
1814 browser.page().mainFrame().evaluateJavaScript(
\r
1815 script_start + buffer + script_end);
\r
1820 // Handle URLs that are trying to be pasted
\r
1821 public void handleUrls(QMimeData mime) {
\r
1822 logger.log(logger.EXTREME, "Starting handleUrls");
\r
1823 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1825 List<QUrl> urlList = mime.urls();
\r
1826 String url = new String();
\r
1827 String script_start = new String(
\r
1828 "document.execCommand('createLink', false, '");
\r
1829 String script_end = new String("');");
\r
1831 for (int i = 0; i < urlList.size(); i++) {
\r
1832 url = urlList.get(i).toString();
\r
1833 // Find out what type of file we have
\r
1834 String mimeType = fileNameMap.getContentTypeFor(url);
\r
1836 // If null returned, we need to guess at the file type
\r
1837 if (mimeType == null)
\r
1838 mimeType = "application/"
\r
1839 + url.substring(url.lastIndexOf(".") + 1);
\r
1841 // Check if we have an image or some other type of file
\r
1842 if (url.substring(0, 5).equalsIgnoreCase("file:")
\r
1843 && mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1844 handleLocalImageURLPaste(mime, mimeType);
\r
1847 String[] type = mimeType.split("/");
\r
1848 boolean valid = validAttachment(type[1]);
\r
1849 boolean smallEnough = checkFileAttachmentSize(url);
\r
1850 if (smallEnough && valid
\r
1851 && url.substring(0, 5).equalsIgnoreCase("file:")
\r
1852 && !mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1853 handleLocalAttachment(mime, mimeType);
\r
1856 browser.page().mainFrame().evaluateJavaScript(
\r
1857 script_start + url + script_end);
\r
1862 // If a URL being pasted is an image URL, then attach the image
\r
1863 private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {
\r
1864 List<QUrl> urlList = mime.urls();
\r
1865 String url = new String();
\r
1866 String script_start_image = new String(
\r
1867 "document.execCommand('insertHtml', false, '");
\r
1868 String script_end = new String("');");
\r
1869 StringBuffer buffer;
\r
1871 // Copy the image over into the resource directory and create a new resource
\r
1872 // record for each url pasted
\r
1873 for (int i = 0; i < urlList.size(); i++) {
\r
1874 url = urlList.get(i).toString();
\r
1876 Resource newRes = createResource(url, i, mimeType, false);
\r
1877 if (newRes == null)
\r
1879 currentNote.getResources().add(newRes);
\r
1880 buffer = new StringBuffer(100);
\r
1882 // Open the file & write the data
\r
1883 String fileName = Global.getFileManager().getResDirPath(newRes.getGuid());
\r
1884 QFile tfile = new QFile(fileName);
\r
1885 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1886 tfile.write(newRes.getData().getBody());
\r
1888 buffer.append(script_start_image);
\r
1889 buffer.append("<img src=\"" + FileUtils.toForwardSlashedPath(fileName));
\r
1890 // if (mimeType.equalsIgnoreCase("image/jpg"))
\r
1891 // mimeType = "image/jpeg";
\r
1892 buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""
\r
1893 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1894 +" guid=\"" +newRes.getGuid() +"\""
\r
1895 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1897 buffer.append(script_end);
\r
1898 browser.page().mainFrame().evaluateJavaScript(buffer.toString());
\r
1904 // If a URL being pasted is a local file URL, then attach the file
\r
1905 private void handleLocalAttachment(QMimeData mime, String mimeType) {
\r
1906 logger.log(logger.EXTREME, "Attaching local file");
\r
1907 List<QUrl> urlList = mime.urls();
\r
1908 String script_start = new String(
\r
1909 "document.execCommand('insertHtml', false, '");
\r
1910 String script_end = new String("');");
\r
1911 StringBuffer buffer;
\r
1913 String[] type = mimeType.split("/");
\r
1914 String icon = findIcon(type[1]);
\r
1915 if (icon.equals("attachment.png"))
\r
1916 icon = findIcon(type[0]);
\r
1917 buffer = new StringBuffer(100);
\r
1919 for (int i = 0; i < urlList.size(); i++) {
\r
1920 String url = urlList.get(i).toString();
\r
1922 // Start building the HTML
\r
1923 if (icon.equals("attachment.png"))
\r
1924 icon = findIcon(url.substring(url.lastIndexOf(".")+1));
\r
1925 String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));
\r
1927 logger.log(logger.EXTREME, "Creating resource ");
\r
1928 Resource newRes = createResource(url, i, mimeType, true);
\r
1929 if (newRes == null)
\r
1931 logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());
\r
1932 currentNote.getResources().add(newRes);
\r
1934 String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();
\r
1935 // If we have a PDF, we need to setup the preview.
\r
1936 if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {
\r
1937 logger.log(logger.EXTREME, "Setting up PDF preview");
\r
1938 if (newRes.getAttributes() != null &&
\r
1939 newRes.getAttributes().getFileName() != null &&
\r
1940 !newRes.getAttributes().getFileName().trim().equals(""))
\r
1941 fileName = newRes.getGuid()+Global.attachmentNameDelimeter+
\r
1942 newRes.getAttributes().getFileName();
\r
1944 fileName = newRes.getGuid()+".pdf";
\r
1945 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
1946 QFile.OpenMode mode = new QFile.OpenMode();
\r
1947 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
1949 QDataStream out = new QDataStream(file);
\r
1950 // Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);
\r
1951 QByteArray binData = new QByteArray(newRes.getData().getBody());
\r
1952 // resBinary = null;
\r
1953 out.writeBytes(binData.toByteArray());
\r
1956 PDFPreview pdfPreview = new PDFPreview();
\r
1957 if (pdfPreview.setupPreview(Global.getFileManager().getResDirPath(fileName), "pdf",0)) {
\r
1958 imageURL = file.fileName() + ".png";
\r
1962 logger.log(logger.EXTREME, "Generating link tags");
\r
1963 buffer.delete(0, buffer.length());
\r
1964 buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");
\r
1965 buffer.append(" onContextMenu=\"window.jambi.imageContextMenu('")
\r
1966 .append(Global.getFileManager().getResDirPath(fileName))
\r
1967 .append("');\" "); buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");
\r
1968 buffer.append("<img src=\"" + imageURL + "\" title=\"" +newRes.getAttributes().getFileName());
\r
1969 buffer.append("\"></img>");
\r
1970 buffer.append("</a>");
\r
1971 browser.page().mainFrame().evaluateJavaScript(
\r
1972 script_start + buffer.toString() + script_end);
\r
1977 private Resource createResource(String url, int sequence, String mime, boolean attachment) {
\r
1978 logger.log(logger.EXTREME, "Inside create resource");
\r
1979 QFile resourceFile;
\r
1980 String urlTest = new QUrl(url).toLocalFile();
\r
1981 if (!urlTest.equals(""))
\r
1983 url = url.replace("/", File.separator);
\r
1984 resourceFile = new QFile(url);
\r
1985 resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));
\r
1986 byte[] fileData = resourceFile.readAll().toByteArray();
\r
1987 resourceFile.close();
\r
1988 if (fileData.length == 0)
\r
1992 md = MessageDigest.getInstance("MD5");
\r
1993 md.update(fileData);
\r
1994 byte[] hash = md.digest();
\r
1996 Resource r = new Resource();
\r
1997 Calendar time = new GregorianCalendar();
\r
1998 long prevTime = time.getTimeInMillis();
\r
1999 while (prevTime == time.getTimeInMillis()) {
\r
2000 time = new GregorianCalendar();
\r
2002 r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());
\r
2003 r.setNoteGuid(currentNote.getGuid());
\r
2005 r.setActive(true);
\r
2006 r.setUpdateSequenceNum(0);
\r
2007 r.setWidth((short) 0);
\r
2008 r.setHeight((short) 0);
\r
2009 r.setDuration((short) 0);
\r
2011 Data d = new Data();
\r
2012 d.setBody(fileData);
\r
2013 d.setBodyIsSet(true);
\r
2014 d.setBodyHash(hash);
\r
2015 d.setBodyHashIsSet(true);
\r
2017 d.setSize(fileData.length);
\r
2019 int fileNamePos = url.lastIndexOf(File.separator);
\r
2020 if (fileNamePos == -1)
\r
2021 fileNamePos = url.lastIndexOf("/");
\r
2022 String fileName = url.substring(fileNamePos+1);
\r
2023 ResourceAttributes a = new ResourceAttributes();
\r
2025 a.setAltitudeIsSet(false);
\r
2026 a.setLongitude(0);
\r
2027 a.setLongitudeIsSet(false);
\r
2029 a.setLatitudeIsSet(false);
\r
2030 a.setCameraMake("");
\r
2031 a.setCameraMakeIsSet(false);
\r
2032 a.setCameraModel("");
\r
2033 a.setCameraModelIsSet(false);
\r
2034 a.setAttachment(attachment);
\r
2035 a.setAttachmentIsSet(true);
\r
2036 a.setClientWillIndex(false);
\r
2037 a.setClientWillIndexIsSet(true);
\r
2038 a.setRecoType("");
\r
2039 a.setRecoTypeIsSet(false);
\r
2040 a.setSourceURL(url);
\r
2041 a.setSourceURLIsSet(true);
\r
2042 a.setTimestamp(0);
\r
2043 a.setTimestampIsSet(false);
\r
2044 a.setFileName(fileName);
\r
2045 a.setFileNameIsSet(true);
\r
2046 r.setAttributes(a);
\r
2048 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
2050 } catch (NoSuchAlgorithmException e1) {
\r
2051 e1.printStackTrace();
\r
2057 // find the appropriate icon for an attachment
\r
2058 private String findIcon(String appl) {
\r
2059 appl = appl.toLowerCase();
\r
2060 File f = Global.getFileManager().getImageDirFile(appl + ".png");
\r
2062 return appl+".png";
\r
2063 return "attachment.png";
\r
2066 // Check if the account supports this type of attachment
\r
2067 private boolean validAttachment(String type) {
\r
2068 if (Global.isPremium())
\r
2070 if (type.equalsIgnoreCase("JPG"))
\r
2072 if (type.equalsIgnoreCase("PNG"))
\r
2074 if (type.equalsIgnoreCase("GIF"))
\r
2076 if (type.equalsIgnoreCase("MP3"))
\r
2078 if (type.equalsIgnoreCase("WAV"))
\r
2080 if (type.equalsIgnoreCase("AMR"))
\r
2082 if (type.equalsIgnoreCase("PDF"))
\r
2084 String error = tr("Non-premium accounts can only attach JPG, PNG, GIF, MP3, WAV, AMR, or PDF files.");
\r
2085 QMessageBox.information(this, tr("Non-Premium Account"), error);
\r
2090 // Check the file attachment to be sure it isn't over 25 mb
\r
2091 private boolean checkFileAttachmentSize(String url) {
\r
2092 String fileName = url.substring(8);
\r
2093 QFile resourceFile = new QFile(fileName);
\r
2094 resourceFile.open(new QIODevice.OpenMode(
\r
2095 QIODevice.OpenModeFlag.ReadOnly));
\r
2096 long size = resourceFile.size();
\r
2097 resourceFile.close();
\r
2098 size = size / 1024 / 1024;
\r
2099 if (size < 50 && Global.isPremium())
\r
2104 String error = tr("A file attachment may not exceed 25MB.");
\r
2105 QMessageBox.information(this, tr("Attachment Size"), error);
\r
2110 @SuppressWarnings("unused")
\r
2111 private void createdChanged() {
\r
2112 QDateTime dt = new QDateTime();
\r
2113 dt.setDate(createdDate.date());
\r
2114 dt.setTime(createdTime.time());
\r
2115 noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);
\r
2119 @SuppressWarnings("unused")
\r
2120 private void alteredChanged() {
\r
2121 QDateTime dt = new QDateTime();
\r
2122 dt.setDate(alteredDate.date());
\r
2123 dt.setTime(alteredTime.time());
\r
2124 noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);
\r
2127 @SuppressWarnings("unused")
\r
2128 private void subjectDateTimeChanged() {
\r
2129 QDateTime dt = new QDateTime();
\r
2130 dt.setDate(subjectDate.date());
\r
2131 dt.setTime(subjectTime.time());
\r
2132 noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);
\r
2136 @SuppressWarnings("unused")
\r
2137 private void sourceUrlChanged() {
\r
2138 noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());
\r
2141 @SuppressWarnings("unused")
\r
2142 private void authorChanged() {
\r
2143 noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());
\r
2146 @SuppressWarnings("unused")
\r
2147 private void geoBoxChanged() {
\r
2148 int index = geoBox.currentIndex();
\r
2149 geoBox.setCurrentIndex(0);
\r
2151 GeoDialog box = new GeoDialog();
\r
2152 box.setLongitude(currentNote.getAttributes().getLongitude());
\r
2153 box.setLatitude(currentNote.getAttributes().getLatitude());
\r
2154 box.setAltitude(currentNote.getAttributes().getAltitude());
\r
2156 if (!box.okPressed())
\r
2158 double alt = box.getAltitude();
\r
2159 double lat = box.getLatitude();
\r
2160 double lon = box.getLongitude();
\r
2161 if (alt != currentNote.getAttributes().getAltitude() ||
\r
2162 lon != currentNote.getAttributes().getLongitude() ||
\r
2163 lat != currentNote.getAttributes().getLatitude()) {
\r
2164 noteSignal.geoChanged.emit(currentNote.getGuid(), lon, lat, alt);
\r
2165 currentNote.getAttributes().setAltitude(alt);
\r
2166 currentNote.getAttributes().setLongitude(lon);
\r
2167 currentNote.getAttributes().setLatitude(lat);
\r
2172 noteSignal.geoChanged.emit(currentNote.getGuid(), 0.0, 0.0, 0.0);
\r
2173 currentNote.getAttributes().setAltitude(0.0);
\r
2174 currentNote.getAttributes().setLongitude(0.0);
\r
2175 currentNote.getAttributes().setLatitude(0.0);
\r
2178 if (index == 3 || index == 0) {
\r
2179 QDesktopServices.openUrl(new QUrl("http://maps.google.com/maps?z=6&q="+currentNote.getAttributes().getLatitude() +"," +currentNote.getAttributes().getLongitude()));
\r
2183 // ************************************************************
\r
2184 // * User chose to save an attachment. Pares out the request *
\r
2185 // * into a guid & file. Save the result. *
\r
2186 // ************************************************************
\r
2187 public void downloadAttachment(QNetworkRequest request) {
\r
2189 QFileDialog fd = new QFileDialog(this);
\r
2190 fd.setFileMode(FileMode.AnyFile);
\r
2191 fd.setConfirmOverwrite(true);
\r
2192 fd.setWindowTitle(tr("Save File"));
\r
2193 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2194 fd.setDirectory(System.getProperty("user.home"));
\r
2195 String name = request.url().toString();
\r
2197 int pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2199 guid = name.substring(0, pos).replace("nnres://", "");
\r
2200 name = name.substring(pos +Global.attachmentNameDelimeter.length());
\r
2201 fd.selectFile(name);
\r
2202 pos = name.lastIndexOf('.');
\r
2204 String mimeType = "(*." + name.substring(pos + 1)
\r
2205 + ");; All Files (*)";
\r
2206 fd.setFilter(tr(mimeType));
\r
2212 // Strip URL prefix and base dir
\r
2213 guid = guid.replace("nnres://", "")
\r
2214 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2215 guid = guid.replace("file://", "").replace("/", "")
\r
2216 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2218 pos = guid.lastIndexOf('.');
\r
2220 guid = guid.substring(0,pos);
\r
2221 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2222 name = name.replace('\\', '/');
\r
2223 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2224 QFile saveFile = new QFile(fd.selectedFiles().get(0));
\r
2225 QFile.OpenMode mode = new QFile.OpenMode();
\r
2226 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2227 saveFile.open(mode);
\r
2228 QDataStream saveOut = new QDataStream(saveFile);
\r
2229 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2230 saveOut.writeBytes(binData.toByteArray());
\r
2237 // ************************************************************
\r
2238 // * User chose to save an attachment. Pares out the request *
\r
2239 // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!
\r
2240 // ************************************************************
\r
2241 public void downloadImage(QNetworkRequest request) {
\r
2242 QFileDialog fd = new QFileDialog(this);
\r
2243 fd.setFileMode(FileMode.AnyFile);
\r
2244 fd.setConfirmOverwrite(true);
\r
2245 fd.setWindowTitle(tr("Save File"));
\r
2246 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2247 fd.setDirectory(System.getProperty("user.home"));
\r
2248 String name = request.url().toString();
\r
2249 name = name.replace("nnres://", "");
\r
2250 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
\r
2251 name = name.replace(dPath, "");
\r
2252 int pos = name.lastIndexOf('.');
\r
2253 String guid = name;
\r
2255 String mimeType = "(*." + name.substring(pos + 1)
\r
2256 + ");; All Files (*)";
\r
2257 fd.setFilter(tr(mimeType));
\r
2258 guid = guid.substring(0,pos);
\r
2260 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2262 guid = name.substring(0, pos);
\r
2263 fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));
\r
2265 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2266 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2267 String fileName = fd.selectedFiles().get(0);
\r
2268 QFile saveFile = new QFile(fileName);
\r
2269 QFile.OpenMode mode = new QFile.OpenMode();
\r
2270 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2271 saveFile.open(mode);
\r
2272 QDataStream saveOut = new QDataStream(saveFile);
\r
2273 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2274 saveOut.writeBytes(binData.toByteArray());
\r
2280 // *************************************************************
\r
2281 // * decrypt any hidden text. We could do an XML parse, but
\r
2282 // * it is quicker here just to scan for an <img tag & do the fix
\r
2283 // * the manual way
\r
2284 // *************************************************************
\r
2285 private void removeEncryption(String id, String plainText, boolean permanent, String slot) {
\r
2287 plainText = " <table class=\"en-crypt-temp\" slot=\""
\r
2290 +"border=1 width=100%><tbody><tr><td>"
\r
2291 +plainText+"</td></tr></tbody></table>";
\r
2294 String html = browser.page().mainFrame().toHtml();
\r
2295 String text = html;
\r
2296 int imagePos = html.indexOf("<img");
\r
2298 for ( ;imagePos>0; ) {
\r
2299 // Find the end tag
\r
2300 endPos = text.indexOf(">", imagePos);
\r
2301 String tag = text.substring(imagePos-1,endPos);
\r
2302 if (tag.indexOf("id=\""+id+"\"") > -1) {
\r
2303 text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);
\r
2304 QTextCodec codec = QTextCodec.codecForName("UTF-8");
\r
2305 QByteArray unicode = codec.fromUnicode(text);
\r
2306 browser.setContent(unicode);
\r
2310 imagePos = text.indexOf("<img", imagePos+1);
\r
2315 //****************************************************************
\r
2316 //* Focus shortcuts
\r
2317 //****************************************************************
\r
2318 @SuppressWarnings("unused")
\r
2319 private void focusTitle() {
\r
2320 titleLabel.setFocus();
\r
2322 @SuppressWarnings("unused")
\r
2323 private void focusTag() {
\r
2324 tagEdit.setFocus();
\r
2326 @SuppressWarnings("unused")
\r
2327 private void focusNote() {
\r
2328 browser.setFocus();
\r
2330 @SuppressWarnings("unused")
\r
2331 private void focusAuthor() {
\r
2332 authorLabel.setFocus();
\r
2334 @SuppressWarnings("unused")
\r
2335 private void focusUrl() {
\r
2336 urlLabel.setFocus();
\r
2340 //*****************************************************************
\r
2341 //* Set the document background color
\r
2342 //*****************************************************************
\r
2343 public void setBackgroundColor(String color) {
\r
2344 String js = "function changeBackground(color) {"
\r
2345 +"document.body.style.background = color;"
\r
2347 +"changeBackground('" +color+"');";
\r
2348 browser.page().mainFrame().evaluateJavaScript(js);
\r
2353 //****************************************************************
\r
2354 //* MicroFocus changed
\r
2355 //****************************************************************
\r
2356 private void microFocusChanged() {
\r
2357 boldButton.setDown(false);
\r
2358 italicButton.setDown(false);
\r
2359 underlineButton.setDown(false);
\r
2360 browser.openAction.setEnabled(false);
\r
2361 browser.downloadAttachment.setEnabled(false);
\r
2362 browser.downloadImage.setEnabled(false);
\r
2363 browser.rotateImageLeft.setEnabled(false);
\r
2364 browser.rotateImageRight.setEnabled(false);
\r
2365 browser.insertTableAction.setEnabled(true);
\r
2366 browser.insertTableRowAction.setEnabled(false);
\r
2367 browser.deleteTableRowAction.setEnabled(false);
\r
2368 browser.insertLinkAction.setText(tr("Insert Hyperlink"));
\r
2369 insertHyperlink = true;
\r
2370 currentHyperlink ="";
\r
2371 insideList = false;
\r
2372 forceTextPaste = false;
\r
2374 String js = new String( "function getCursorPos() {"
\r
2376 +"if (window.getSelection) {"
\r
2377 +" var selObj = window.getSelection();"
\r
2378 +" var selRange = selObj.getRangeAt(0);"
\r
2379 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2380 +" while(workingNode != null) { "
\r
2381 // +" window.jambi.printNode(workingNode.nodeName);"
\r
2382 +" if (workingNode.nodeName=='TABLE') { if (workingNode.getAttribute('class').toLowerCase() == 'en-crypt-temp') window.jambi.forceTextPaste(); }"
\r
2383 +" if (workingNode.nodeName=='B') window.jambi.boldActive();"
\r
2384 +" if (workingNode.nodeName=='I') window.jambi.italicActive();"
\r
2385 +" if (workingNode.nodeName=='U') window.jambi.underlineActive();"
\r
2386 +" if (workingNode.nodeName=='UL') window.jambi.setInsideList();"
\r
2387 +" if (workingNode.nodeName=='OL') window.jambi.setInsideList();"
\r
2388 +" if (workingNode.nodeName=='LI') window.jambi.setInsideList();"
\r
2389 +" if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"
\r
2390 +" 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
2391 +" if (workingNode.nodeName=='SPAN') {"
\r
2392 +" if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"
\r
2394 +" workingNode = workingNode.parentNode;"
\r
2397 +"} getCursorPos();");
\r
2398 browser.page().mainFrame().evaluateJavaScript(js);
\r
2401 public void printNode(String n) {
\r
2402 System.out.println("Node Vaule: " +n);
\r
2406 //****************************************************************
\r
2407 //* Insert a table row
\r
2408 //****************************************************************
\r
2409 public void insertTableRow() {
\r
2411 String js = new String( "function insertTableRow() {"
\r
2412 +" var selObj = window.getSelection();"
\r
2413 +" var selRange = selObj.getRangeAt(0);"
\r
2414 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2415 +" var cellCount = 0;"
\r
2416 +" while(workingNode != null) { "
\r
2417 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2418 +" row = document.createElement('TR');"
\r
2419 +" var nodes = workingNode.getElementsByTagName('td');"
\r
2420 +" for (j=0; j<nodes.length; j=j+1) {"
\r
2421 +" cell = document.createElement('TD');"
\r
2422 +" cell.innerHTML=' ';"
\r
2423 +" row.appendChild(cell);"
\r
2425 +" workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"
\r
2428 +" workingNode = workingNode.parentNode;"
\r
2430 +"} insertTableRow();");
\r
2431 browser.page().mainFrame().evaluateJavaScript(js);
\r
2434 //****************************************************************
\r
2435 //* Insert a table row
\r
2436 //****************************************************************
\r
2437 public void deleteTableRow() {
\r
2439 String js = new String( "function deleteTableRow() {"
\r
2440 +" var selObj = window.getSelection();"
\r
2441 +" var selRange = selObj.getRangeAt(0);"
\r
2442 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2443 +" var cellCount = 0;"
\r
2444 +" while(workingNode != null) { "
\r
2445 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2446 +" workingNode.parentNode.removeChild(workingNode);"
\r
2449 +" workingNode = workingNode.parentNode;"
\r
2451 +"} deleteTableRow();");
\r
2452 browser.page().mainFrame().evaluateJavaScript(js);
\r
2455 public void setInsideTable() {
\r
2456 browser.insertTableRowAction.setEnabled(true);
\r
2457 browser.deleteTableRowAction.setEnabled(true);
\r
2458 browser.insertTableAction.setEnabled(false);
\r
2459 browser.encryptAction.setEnabled(false);
\r
2462 public void setInsideLink(String link) {
\r
2463 browser.insertLinkAction.setText(tr("Edit Hyperlink"));
\r
2464 currentHyperlink = link;
\r
2465 insertHyperlink = false;
\r
2468 public void italicActive() {
\r
2469 italicButton.setDown(true);
\r
2471 public void boldActive() {
\r
2472 boldButton.setDown(true);
\r
2474 public void underlineActive() {
\r
2475 underlineButton.setDown(true);
\r
2477 public void forceTextPaste() {
\r
2478 forceTextPaste = true;
\r
2480 public void imageContextMenu(String f) {
\r
2481 browser.downloadImage.setEnabled(true);
\r
2482 browser.rotateImageRight.setEnabled(true);
\r
2483 browser.rotateImageLeft.setEnabled(true);
\r
2484 browser.openAction.setEnabled(true);
\r
2487 public void rotateImageRight() {
\r
2488 QWebSettings.setMaximumPagesInCache(0);
\r
2489 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2490 QImage image = new QImage(selectedFile);
\r
2491 QMatrix matrix = new QMatrix();
\r
2492 matrix.rotate( 90.0 );
\r
2493 image = image.transformed(matrix);
\r
2494 image.save(selectedFile);
\r
2495 QWebSettings.setMaximumPagesInCache(0);
\r
2496 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2497 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2500 // resourceSignal.contentChanged.emit(selectedFile);
\r
2503 public void rotateImageLeft() {
\r
2504 QImage image = new QImage(selectedFile);
\r
2505 QMatrix matrix = new QMatrix();
\r
2506 matrix.rotate( -90.0 );
\r
2507 image = image.transformed(matrix);
\r
2508 image.save(selectedFile);
\r
2509 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2512 // resourceSignal.contentChanged.emit(selectedFile);
\r
2514 public void resourceContextMenu(String f) {
\r
2515 browser.downloadAttachment.setEnabled(true);
\r
2516 browser.openAction.setEnabled(true);
\r
2521 //****************************************************************
\r
2522 //* Apply CSS style to specified word
\r
2523 //****************************************************************
\r
2524 /* public void applyStyleToWords(String word, String style) {
\r
2525 QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");
\r
2526 script.open(OpenModeFlag.ReadOnly);
\r
2527 String s = script.readAll().toString();
\r
2528 String js = new String(s +" findit('"+word+"', '"+style+"');");
\r
2529 browser.page().mainFrame().evaluateJavaScript(js);
\r
2530 System.out.println(getContent());
\r
2533 //****************************************************************
\r
2534 //* Someone tried to paste a resource between notes, so we need *
\r
2535 //* to do some special handling. *
\r
2536 //****************************************************************
\r
2537 private String fixInternotePaste(String text) {
\r
2538 logger.log(logger.EXTREME, "Fixing internote paste");
\r
2539 String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");
\r
2540 return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");
\r
2542 private String fixInternotePasteSearch(String text, String type, String locTag) {
\r
2544 // First, let's fix the images.
\r
2545 int startPos = text.indexOf(type);
\r
2547 for (; startPos>=0;) {
\r
2548 endPos = text.indexOf(">", startPos+1);
\r
2549 String segment = text.substring(startPos, endPos);
\r
2550 if (segment.indexOf("en-tag") > -1) {
\r
2551 String newSegment = segment;
\r
2553 int guidStartPos = segment.indexOf("guid=\"");
\r
2554 int guidEndPos = segment.indexOf("\"", guidStartPos+7);
\r
2555 String guid = segment.substring(guidStartPos+6,guidEndPos);
\r
2557 int mimeStartPos = segment.indexOf("type");
\r
2558 int mimeEndPos = segment.indexOf("\"", mimeStartPos+7);
\r
2559 String mime = segment.substring(mimeStartPos+6,mimeEndPos);
\r
2561 int srcStartPos = segment.indexOf("src");
\r
2562 int srcEndPos = segment.indexOf("\"", srcStartPos+6);
\r
2563 String src = segment.substring(srcStartPos+5,srcEndPos);
\r
2565 Calendar currentTime = new GregorianCalendar();
\r
2566 Long l = new Long(currentTime.getTimeInMillis());
\r
2567 long prevTime = l;
\r
2568 while (l==prevTime) {
\r
2569 currentTime = new GregorianCalendar();
\r
2570 l= new Long(currentTime.getTimeInMillis());
\r
2573 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2574 // if r==null, then the image doesn't exist (it was probably cut out of another note, so
\r
2575 // we need to recereate it
\r
2577 r = createResource(src, 1, mime, false);
\r
2581 String randint = new String(Long.toString(l));
\r
2582 String extension = null;
\r
2583 if (r.getMime()!= null) {
\r
2584 extension = r.getMime().toLowerCase();
\r
2585 if (extension.indexOf("/")>-1)
\r
2586 extension = extension.substring(extension.indexOf("/")+1);
\r
2588 String newFile = randint;
\r
2589 if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")
\r
2590 if (!locTag.startsWith("src"))
\r
2591 newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();
\r
2592 r.setNoteGuid(currentNote.getGuid());
\r
2594 r.setGuid(randint);
\r
2595 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
2596 QFile f = new QFile(Global.getFileManager().getResDirPath(newFile));
\r
2597 QByteArray bin = new QByteArray(r.getData().getBody());
\r
2598 f.open(QFile.OpenModeFlag.WriteOnly);
\r
2601 newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);
\r
2602 currentNote.getResources().add(r);
\r
2604 int startSrcPos = newSegment.indexOf(locTag);
\r
2605 int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);
\r
2607 if (locTag.startsWith("src")) {
\r
2608 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2609 newSegment = newSegment.replace(source,
\r
2610 FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath(newFile)));
\r
2612 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2613 newSegment = newSegment.replace(source, newFile);
\r
2616 text = text.substring(0,startPos) + newSegment + text.substring(endPos);
\r
2618 startPos = text.indexOf(type, startPos+1);
\r
2624 public void nextPage(String file) {
\r
2625 logger.log(logger.EXTREME, "Starting nextPage()");
\r
2627 Integer pageNumber;
\r
2628 if (previewPageList.containsKey(file))
\r
2629 pageNumber = previewPageList.get(file)+1;
\r
2632 previewPageList.remove(file);
\r
2633 previewPageList.put(file, pageNumber);
\r
2634 PDFPreview pdfPreview = new PDFPreview();
\r
2635 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2636 if (goodPreview) {
\r
2638 // String html = getContent();
\r
2639 QWebSettings.setMaximumPagesInCache(0);
\r
2640 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2641 // browser.setContent(new QByteArray());
\r
2642 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2644 // browser.setContent(new QByteArray(html));
\r
2645 // browser.triggerPageAction(WebAction.Reload);
\r
2646 // pdfMouseOver(selectedFile);
\r
2650 public void previousPage(String file) {
\r
2651 logger.log(logger.EXTREME, "Starting previousPage()");
\r
2653 Integer pageNumber;
\r
2654 if (previewPageList.containsKey(file))
\r
2655 pageNumber = previewPageList.get(file)-1;
\r
2658 previewPageList.remove(file);
\r
2659 previewPageList.put(file, pageNumber);
\r
2660 PDFPreview pdfPreview = new PDFPreview();
\r
2661 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2662 if (goodPreview) {
\r
2664 // String html = getContent();
\r
2665 QWebSettings.setMaximumPagesInCache(0);
\r
2666 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2667 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2669 // browser.setContent(new QByteArray(html));
\r
2670 // browser.triggerPageAction(WebAction.Reload);
\r
2674 /* public void pdfMouseOver(String name) {
\r
2676 if (previewPageList.containsKey(selectedFile))
\r
2677 pageNumber = previewPageList.get(selectedFile)+1;
\r
2681 if (pageNumber <= 1)
\r
2682 browser.previousPageAction.setEnabled(false);
\r
2684 browser.previousPageAction.setEnabled(true);
\r
2686 PDFPreview pdf = new PDFPreview();
\r
2687 int totalPages = pdf.getPageCount(name);
\r
2688 if (previewPageList.containsKey(selectedFile))
\r
2689 pageNumber = previewPageList.get(selectedFile)+1;
\r
2692 if (totalPages > pageNumber)
\r
2693 browser.nextPageAction.setEnabled(true);
\r
2695 browser.nextPageAction.setEnabled(false);
\r
2699 public void pdfMouseOut() {
\r
2700 // browser.nextPageAction.setVisible(false);
\r
2701 // browser.previousPageAction.setVisible(false);
\r
2705 @SuppressWarnings("unused")
\r
2706 private void toggleUndoVisible(Boolean toggle) {
\r
2707 undoAction.setVisible(toggle);
\r
2708 Global.saveEditorButtonsVisible("undo", toggle);
\r
2710 @SuppressWarnings("unused")
\r
2711 private void toggleRedoVisible(Boolean toggle) {
\r
2712 redoAction.setVisible(toggle);
\r
2713 Global.saveEditorButtonsVisible("redo", toggle);
\r
2715 @SuppressWarnings("unused")
\r
2716 private void toggleCutVisible(Boolean toggle) {
\r
2717 cutAction.setVisible(toggle);
\r
2718 Global.saveEditorButtonsVisible("cut", toggle);
\r
2720 @SuppressWarnings("unused")
\r
2721 private void toggleCopyVisible(Boolean toggle) {
\r
2722 copyAction.setVisible(toggle);
\r
2723 Global.saveEditorButtonsVisible("copy", toggle);
\r
2725 @SuppressWarnings("unused")
\r
2726 private void togglePasteVisible(Boolean toggle) {
\r
2727 pasteAction.setVisible(toggle);
\r
2728 Global.saveEditorButtonsVisible("paste", toggle);
\r
2730 @SuppressWarnings("unused")
\r
2731 private void toggleBoldVisible(Boolean toggle) {
\r
2732 boldAction.setVisible(toggle);
\r
2733 Global.saveEditorButtonsVisible("bold", toggle);
\r
2735 @SuppressWarnings("unused")
\r
2736 private void toggleItalicVisible(Boolean toggle) {
\r
2737 italicAction.setVisible(toggle);
\r
2738 Global.saveEditorButtonsVisible("italic", toggle);
\r
2740 @SuppressWarnings("unused")
\r
2741 private void toggleUnderlineVisible(Boolean toggle) {
\r
2742 underlineAction.setVisible(toggle);
\r
2743 Global.saveEditorButtonsVisible("underline", toggle);
\r
2745 @SuppressWarnings("unused")
\r
2746 private void toggleStrikethroughVisible(Boolean toggle) {
\r
2747 strikethroughAction.setVisible(toggle);
\r
2748 Global.saveEditorButtonsVisible("strikethrough", toggle);
\r
2750 @SuppressWarnings("unused")
\r
2751 private void toggleLeftAlignVisible(Boolean toggle) {
\r
2752 leftAlignAction.setVisible(toggle);
\r
2753 Global.saveEditorButtonsVisible("alignLeft", toggle);
\r
2755 @SuppressWarnings("unused")
\r
2756 private void toggleRightAlignVisible(Boolean toggle) {
\r
2757 rightAlignAction.setVisible(toggle);
\r
2758 Global.saveEditorButtonsVisible("alignRight", toggle);
\r
2760 @SuppressWarnings("unused")
\r
2761 private void toggleCenterAlignVisible(Boolean toggle) {
\r
2762 centerAlignAction.setVisible(toggle);
\r
2763 Global.saveEditorButtonsVisible("alignCenter", toggle);
\r
2765 @SuppressWarnings("unused")
\r
2766 private void toggleHLineVisible(Boolean toggle) {
\r
2767 hlineAction.setVisible(toggle);
\r
2768 Global.saveEditorButtonsVisible("hline", toggle);
\r
2770 @SuppressWarnings("unused")
\r
2771 private void toggleIndentVisible(Boolean toggle) {
\r
2772 indentAction.setVisible(toggle);
\r
2773 Global.saveEditorButtonsVisible("indent", toggle);
\r
2775 @SuppressWarnings("unused")
\r
2776 private void toggleTodoVisible(Boolean toggle) {
\r
2777 todoAction.setVisible(toggle);
\r
2778 Global.saveEditorButtonsVisible("todo", toggle);
\r
2780 @SuppressWarnings("unused")
\r
2781 private void toggleOutdentVisible(Boolean toggle) {
\r
2782 outdentAction.setVisible(toggle);
\r
2783 Global.saveEditorButtonsVisible("outdent", toggle);
\r
2785 @SuppressWarnings("unused")
\r
2786 private void toggleBulletListVisible(Boolean toggle) {
\r
2787 bulletListAction.setVisible(toggle);
\r
2788 Global.saveEditorButtonsVisible("bulletList", toggle);
\r
2790 @SuppressWarnings("unused")
\r
2791 private void toggleNumberListVisible(Boolean toggle) {
\r
2792 numberListAction.setVisible(toggle);
\r
2793 Global.saveEditorButtonsVisible("numberList", toggle);
\r
2795 @SuppressWarnings("unused")
\r
2796 private void toggleFontListVisible(Boolean toggle) {
\r
2797 fontListAction.setVisible(toggle);
\r
2798 Global.saveEditorButtonsVisible("font", toggle);
\r
2800 @SuppressWarnings("unused")
\r
2801 private void toggleFontColorVisible(Boolean toggle) {
\r
2802 fontColorAction.setVisible(toggle);
\r
2803 Global.saveEditorButtonsVisible("fontColor", toggle);
\r
2805 @SuppressWarnings("unused")
\r
2806 private void toggleFontSizeVisible(Boolean toggle) {
\r
2807 fontSizeAction.setVisible(toggle);
\r
2808 Global.saveEditorButtonsVisible("fontSize", toggle);
\r
2810 @SuppressWarnings("unused")
\r
2811 private void toggleFontHilightVisible(Boolean toggle) {
\r
2812 fontHilightAction.setVisible(toggle);
\r
2813 Global.saveEditorButtonsVisible("fontHilight", toggle);
\r
2815 @SuppressWarnings("unused")
\r
2816 private void toggleSpellCheckVisible(Boolean toggle) {
\r
2817 spellCheckAction.setVisible(toggle);
\r
2818 Global.saveEditorButtonsVisible("spellCheck", toggle);
\r
2822 private void setupDictionary() {
\r
2823 File wordList = new File(Global.getFileManager().getSpellDirPath()+Locale.getDefault()+".dic");
\r
2825 dictionary = new SpellDictionaryHashMap(wordList);
\r
2826 spellChecker = new SpellChecker(dictionary);
\r
2828 File userWordList;
\r
2829 userWordList = new File(Global.getFileManager().getSpellDirPathUser()+"user.dic");
\r
2831 // Get the local user spell dictionary
\r
2833 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
2834 } catch (FileNotFoundException e) {
\r
2835 userWordList.createNewFile();
\r
2836 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
2837 } catch (IOException e) {
\r
2838 userWordList.createNewFile();
\r
2839 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
2842 spellListener = new SuggestionListener(this, spellChecker);
\r
2844 // Add the user dictionary
\r
2845 spellChecker.addSpellCheckListener(spellListener);
\r
2846 spellChecker.setUserDictionary(userDictionary);
\r
2848 } catch (FileNotFoundException e) {
\r
2849 QMessageBox.critical(this, tr("Spell Check Error"),
\r
2850 tr("Dictionary "+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
2851 ".dic was not found."));
\r
2852 } catch (IOException e) {
\r
2853 QMessageBox.critical(this, tr("Spell Check Error"),
\r
2854 tr("Dictionary "+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
2855 ".dic is invalid."));
\r
2860 // Invoke spell checker dialog
\r
2861 @SuppressWarnings("unused")
\r
2862 private void spellCheckClicked() {
\r
2864 if (spellChecker == null) {
\r
2865 setupDictionary();
\r
2868 // Read user settings
\r
2869 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREDIGITWORDS,
\r
2870 Global.getSpellSetting(Configuration.SPELL_IGNOREDIGITWORDS));
\r
2871 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREINTERNETADDRESSES,
\r
2872 Global.getSpellSetting(Configuration.SPELL_IGNOREINTERNETADDRESSES));
\r
2873 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREMIXEDCASE,
\r
2874 Global.getSpellSetting(Configuration.SPELL_IGNOREMIXEDCASE));
\r
2875 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREUPPERCASE,
\r
2876 Global.getSpellSetting(Configuration.SPELL_IGNOREUPPERCASE));
\r
2877 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNORESENTENCECAPITALIZATION,
\r
2878 Global.getSpellSetting(Configuration.SPELL_IGNORESENTENCECAPITALIZATION));
\r
2880 spellListener.abortSpellCheck = false;
\r
2881 spellListener.errorsFound = false;
\r
2882 String content = getBrowser().page().mainFrame().toPlainText();
\r
2883 StringWordTokenizer tokenizer = new StringWordTokenizer(content);
\r
2884 if (!tokenizer.hasMoreWords())
\r
2886 getBrowser().page().action(WebAction.MoveToStartOfDocument);
\r
2888 getBrowser().setFocus();
\r
2891 // Move to the start of page
\r
2892 KeyboardModifiers ctrl = new KeyboardModifiers(KeyboardModifier.ControlModifier.value());
\r
2893 QKeyEvent home = new QKeyEvent(Type.KeyPress, Key.Key_Home.value(), ctrl);
\r
2894 browser.keyPressEvent(home);
\r
2895 getBrowser().setFocus();
\r
2897 tokenizer = new StringWordTokenizer(content);
\r
2900 while(tokenizer.hasMoreWords()) {
\r
2901 word = tokenizer.nextWord();
\r
2902 found = getBrowser().page().findText(word);
\r
2903 if (found && !spellListener.abortSpellCheck) {
\r
2904 spellChecker.checkSpelling(new StringWordTokenizer(word));
\r
2905 getBrowser().setFocus();
\r
2909 // Go to the end of the document & finish up.
\r
2910 home = new QKeyEvent(Type.KeyPress, Key.Key_End.value(), ctrl);
\r
2911 browser.keyPressEvent(home);
\r
2912 if (!spellListener.errorsFound)
\r
2913 QMessageBox.information(this, tr("Spell Check Complete"),
\r
2914 tr("No Errors Found"));
\r