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.QPushButton;
\r
96 import com.trolltech.qt.gui.QShortcut;
\r
97 import com.trolltech.qt.gui.QTimeEdit;
\r
98 import com.trolltech.qt.gui.QToolButton;
\r
99 import com.trolltech.qt.gui.QToolButton.ToolButtonPopupMode;
\r
100 import com.trolltech.qt.gui.QVBoxLayout;
\r
101 import com.trolltech.qt.gui.QWidget;
\r
102 import com.trolltech.qt.network.QNetworkRequest;
\r
103 import com.trolltech.qt.webkit.QWebPage;
\r
104 import com.trolltech.qt.webkit.QWebPage.WebAction;
\r
105 import com.trolltech.qt.webkit.QWebSettings;
\r
106 import com.trolltech.qt.webkit.QWebView;
\r
108 import cx.fbn.nevernote.Global;
\r
109 import cx.fbn.nevernote.dialog.EnCryptDialog;
\r
110 import cx.fbn.nevernote.dialog.EnDecryptDialog;
\r
111 import cx.fbn.nevernote.dialog.GeoDialog;
\r
112 import cx.fbn.nevernote.dialog.InsertLinkDialog;
\r
113 import cx.fbn.nevernote.dialog.SpellCheck;
\r
114 import cx.fbn.nevernote.dialog.TableDialog;
\r
115 import cx.fbn.nevernote.dialog.TagAssign;
\r
116 import cx.fbn.nevernote.evernote.EnCrypt;
\r
117 import cx.fbn.nevernote.signals.NoteResourceSignal;
\r
118 import cx.fbn.nevernote.signals.NoteSignal;
\r
119 import cx.fbn.nevernote.sql.DatabaseConnection;
\r
120 import cx.fbn.nevernote.utilities.ApplicationLogger;
\r
121 import cx.fbn.nevernote.utilities.FileUtils;
\r
122 import cx.fbn.nevernote.utilities.Pair;
\r
124 public class BrowserWindow extends QWidget {
\r
126 public final QLineEdit titleLabel;
\r
127 private final QLineEdit urlText;
\r
128 private final QLabel authorLabel;
\r
129 private final QLineEdit authorText;
\r
130 private final QComboBox geoBox;
\r
131 public final TagLineEdit tagEdit;
\r
132 public final QLabel tagLabel;
\r
133 private final QPushButton urlLabel;
\r
134 private final QLabel alteredLabel;
\r
135 private final QDateEdit alteredDate;
\r
136 private final QTimeEdit alteredTime;
\r
137 private final QDateEdit createdDate;
\r
138 private final QTimeEdit createdTime;
\r
139 private final QLabel subjectLabel;
\r
140 private final QDateEdit subjectDate;
\r
141 private final QTimeEdit subjectTime;
\r
142 public final QComboBox notebookBox;
\r
143 private final QLabel notebookLabel;
\r
144 private final QLabel createdLabel;
\r
145 public final QComboBox fontSize;
\r
146 public final QAction fontSizeAction;
\r
147 private boolean extendedOn;
\r
148 public boolean buttonsVisible;
\r
149 private final String iconPath = new String("classpath:cx/fbn/nevernote/icons/");
\r
150 private final ContentView browser;
\r
151 private List<Tag> allTags;
\r
152 private List<String> currentTags;
\r
153 public NoteSignal noteSignal;
\r
154 private List<Notebook> notebookList;
\r
155 private Note currentNote;
\r
156 private String saveNoteTitle;
\r
157 private String saveTagList;
\r
158 private boolean insideList;
\r
159 // private String selectedText;
\r
160 private final DatabaseConnection conn;
\r
161 private final QCalendarWidget createdCalendarWidget;
\r
162 private final QCalendarWidget alteredCalendarWidget;
\r
163 private final QCalendarWidget subjectCalendarWidget;
\r
165 public final QPushButton undoButton;
\r
166 public final QAction undoAction;
\r
167 public final QPushButton redoButton;
\r
168 public final QAction redoAction;
\r
169 public final QPushButton cutButton;
\r
170 public final QAction cutAction;
\r
171 public final QPushButton copyButton;
\r
172 public final QAction copyAction;
\r
173 public final QPushButton pasteButton;
\r
174 public final QAction pasteAction;
\r
175 public final QPushButton boldButton;
\r
176 public final QAction boldAction;
\r
177 public final QPushButton underlineButton;
\r
178 public final QAction underlineAction;
\r
179 public final QPushButton italicButton;
\r
180 public final QAction italicAction;
\r
181 public final Signal0 focusLost;
\r
182 public final NoteResourceSignal resourceSignal;
\r
184 public QPushButton rightAlignButton;
\r
185 public final QAction rightAlignAction;
\r
186 public QPushButton leftAlignButton;
\r
187 public final QAction leftAlignAction;
\r
188 public QPushButton centerAlignButton;
\r
189 public final QAction centerAlignAction;
\r
191 public final QPushButton strikethroughButton;
\r
192 public final QAction strikethroughAction;
\r
193 public final QPushButton hlineButton;
\r
194 public final QAction hlineAction;
\r
195 public final QPushButton indentButton;
\r
196 public final QAction indentAction;
\r
197 public final QPushButton outdentButton;
\r
198 public final QAction outdentAction;
\r
199 public final QPushButton bulletListButton;
\r
200 public final QAction bulletListAction;
\r
201 public final QPushButton numberListButton;
\r
202 public final QAction numberListAction;
\r
203 public final QPushButton spellCheckButton;
\r
204 public final QAction spellCheckAction;
\r
205 public final QPushButton todoButton;
\r
206 public final QAction todoAction;
\r
208 public final QShortcut focusTitleShortcut;
\r
209 public final QShortcut focusTagShortcut;
\r
210 public final QShortcut focusNoteShortcut;
\r
211 public final QShortcut focusUrlShortcut;
\r
212 public final QShortcut focusAuthorShortcut;
\r
214 public EditorButtonBar buttonLayout;
\r
215 public final QComboBox fontList;
\r
216 public final QAction fontListAction;
\r
217 public final QToolButton fontColor;
\r
218 public final QAction fontColorAction;
\r
219 private final ColorMenu fontColorMenu;
\r
220 public final QToolButton fontHilight;
\r
221 public final QAction fontHilightAction;
\r
222 private final ColorMenu fontHilightColorMenu;
\r
223 public final QFileSystemWatcher fileWatcher;
\r
224 public int cursorPosition;
\r
225 private boolean forceTextPaste = false;
\r
226 private String selectedFile;
\r
227 private String currentHyperlink;
\r
228 public boolean keepPDFNavigationHidden;
\r
229 private final ApplicationLogger logger;
\r
230 SpellDictionary dictionary;
\r
231 SpellDictionary userDictionary;
\r
232 SpellChecker spellChecker;
\r
233 SuggestionListener spellListener;
\r
234 private final HashMap<String,Integer> previewPageList;
\r
237 public static class SuggestionListener implements SpellCheckListener {
\r
238 public boolean abortSpellCheck = false;
\r
239 public boolean errorsFound = false;
\r
240 private final SpellCheck spellCheckDialog;
\r
243 private final BrowserWindow parent;
\r
244 public SuggestionListener(BrowserWindow parent, SpellChecker checker) {
\r
245 this.parent = parent;
\r
246 spellCheckDialog = new SpellCheck(checker);
\r
248 public void spellingError(SpellCheckEvent event) {
\r
249 errorsFound = true;
\r
250 spellCheckDialog.setWord(event.getInvalidWord());
\r
252 List<Word> suggestions = event.getSuggestions();
\r
253 spellCheckDialog.clearSuggestions();
\r
254 if (!suggestions.isEmpty()) {
\r
255 // spellCheckDialog.setCurrentSuggestion(suggestions.get(0).getWord());
\r
256 for (int i=0; i<suggestions.size(); i++) {
\r
257 spellCheckDialog.addSuggestion(suggestions.get(i).getWord());
\r
259 spellCheckDialog.setSelectedSuggestion(0);
\r
261 spellCheckDialog.exec();
\r
262 if (spellCheckDialog.cancelPressed()) {
\r
263 abortSpellCheck = true;
\r
267 if (spellCheckDialog.replacePressed()) {
\r
268 QClipboard clipboard = QApplication.clipboard();
\r
269 clipboard.setText(spellCheckDialog.getReplacementWord());
\r
270 parent.pasteClicked();
\r
278 public BrowserWindow(DatabaseConnection c) {
\r
279 logger = new ApplicationLogger("browser.log");
\r
280 logger.log(logger.HIGH, "Setting up browser");
\r
282 fileWatcher = new QFileSystemWatcher();
\r
283 // fileWatcher.fileChanged.connect(this, "fileChanged(String)");
\r
284 noteSignal = new NoteSignal();
\r
285 titleLabel = new QLineEdit();
\r
286 titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX);
\r
287 urlText = new QLineEdit();
\r
288 authorText = new QLineEdit();
\r
289 geoBox = new QComboBox();
\r
290 urlLabel = new QPushButton();
\r
291 urlLabel.clicked.connect(this, "sourceUrlClicked()");
\r
292 authorLabel = new QLabel();
\r
295 focusLost = new Signal0();
\r
297 tagEdit = new TagLineEdit(allTags);
\r
298 tagLabel = new QLabel("Tags:");
\r
299 tagEdit.focusLost.connect(this, "modifyTagsTyping()");
\r
301 createdCalendarWidget = new QCalendarWidget();
\r
302 createdDate = new QDateEdit();
\r
303 createdDate.setDisplayFormat(Global.getDateFormat());
\r
304 createdDate.setCalendarPopup(true);
\r
305 createdDate.setCalendarWidget(createdCalendarWidget);
\r
306 createdTime = new QTimeEdit();
\r
307 createdDate.dateChanged.connect(this, "createdChanged()");
\r
308 createdTime.timeChanged.connect(this, "createdChanged()");
\r
310 alteredCalendarWidget = new QCalendarWidget();
\r
311 alteredDate = new QDateEdit();
\r
312 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
313 alteredDate.setCalendarPopup(true);
\r
314 alteredDate.setCalendarWidget(alteredCalendarWidget);
\r
315 alteredTime = new QTimeEdit();
\r
316 alteredLabel = new QLabel("Altered:");
\r
317 alteredDate.dateChanged.connect(this, "alteredChanged()");
\r
318 alteredTime.timeChanged.connect(this, "alteredChanged()");
\r
320 subjectCalendarWidget = new QCalendarWidget();
\r
321 subjectDate = new QDateEdit();
\r
322 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
323 subjectDate.setCalendarPopup(true);
\r
324 subjectDate.setCalendarWidget(subjectCalendarWidget);
\r
325 subjectTime = new QTimeEdit();
\r
326 subjectLabel = new QLabel(tr("Subject Date:"));
\r
327 subjectDate.dateChanged.connect(this, "subjectDateTimeChanged()");
\r
328 subjectTime.timeChanged.connect(this, "subjectDateTimeChanged()");
\r
329 authorText.textChanged.connect(this, "authorChanged()");
\r
330 urlText.textChanged.connect(this, "sourceUrlChanged()");
\r
332 notebookBox = new QComboBox();
\r
333 notebookLabel = new QLabel(tr("Notebook"));
\r
334 createdLabel = new QLabel(tr("Created:"));
\r
335 // selectedText = new String();
\r
337 urlLabel.setVisible(false);
\r
338 urlText.setVisible(false);
\r
339 authorLabel.setVisible(false);
\r
341 geoBox.setVisible(false);
\r
342 geoBox.addItem(new QIcon(iconPath+"globe.png"), "");
\r
343 geoBox.addItem(new String(tr("Set")));
\r
344 geoBox.addItem(new String(tr("Clear")));
\r
345 geoBox.addItem(new String(tr("View On Map")));
\r
346 geoBox.activated.connect(this, "geoBoxChanged()");
\r
348 authorText.setVisible(false);
\r
349 createdDate.setVisible(false);
\r
350 alteredLabel.setVisible(false);
\r
351 //notebookBox.setVisible(false);
\r
352 notebookLabel.setVisible(false);
\r
353 createdLabel.setVisible(false);
\r
354 createdTime.setVisible(false);
\r
355 alteredDate.setVisible(false);
\r
356 alteredTime.setVisible(false);
\r
357 subjectLabel.setVisible(false);
\r
358 subjectDate.setVisible(false);
\r
359 subjectTime.setVisible(false);
\r
360 extendedOn = false;
\r
361 buttonsVisible = true;
\r
362 setAcceptDrops(true);
\r
364 browser = new ContentView(this);
\r
365 browser.page().setLinkDelegationPolicy(
\r
366 QWebPage.LinkDelegationPolicy.DelegateAllLinks);
\r
367 browser.linkClicked.connect(this, "linkClicked(QUrl)");
\r
368 currentHyperlink = "";
\r
370 QVBoxLayout v = new QVBoxLayout();
\r
371 QFormLayout notebookLayout = new QFormLayout();
\r
372 QGridLayout dateLayout = new QGridLayout();
\r
373 titleLabel.setReadOnly(false);
\r
374 titleLabel.editingFinished.connect(this, "titleEdited()");
\r
375 browser.page().contentsChanged.connect(this, "contentChanged()");
\r
376 browser.page().selectionChanged.connect(this, "selectionChanged()");
\r
377 browser.page().mainFrame().javaScriptWindowObjectCleared.connect(this,
\r
378 "exposeToJavascript()");
\r
380 notebookBox.activated.connect(this, "notebookChanged()");
\r
381 resourceSignal = new NoteResourceSignal();
\r
383 QHBoxLayout tagLayout = new QHBoxLayout();
\r
384 v.addWidget(titleLabel, 0);
\r
385 notebookLayout.addRow(notebookLabel, notebookBox);
\r
386 tagLayout.addLayout(notebookLayout, 0);
\r
387 tagLayout.stretch(4);
\r
388 tagLayout.addWidget(tagLabel, 0);
\r
389 tagLayout.addWidget(tagEdit, 1);
\r
390 v.addLayout(tagLayout);
\r
392 QHBoxLayout urlLayout = new QHBoxLayout();
\r
393 urlLayout.addWidget(urlLabel, 0);
\r
394 urlLayout.addWidget(urlText, 0);
\r
395 v.addLayout(urlLayout);
\r
397 QHBoxLayout authorLayout = new QHBoxLayout();
\r
398 authorLayout.addWidget(authorLabel, 0);
\r
399 authorLayout.addWidget(authorText, 0);
\r
400 authorLayout.addWidget(geoBox);
\r
401 v.addLayout(authorLayout);
\r
403 dateLayout.addWidget(createdLabel, 0, 0);
\r
404 dateLayout.addWidget(createdDate, 0, 1);
\r
405 dateLayout.addWidget(createdTime, 0, 2);
\r
406 dateLayout.setColumnStretch(9, 100);
\r
407 dateLayout.addWidget(alteredLabel, 0, 3);
\r
408 dateLayout.addWidget(alteredDate, 0, 4);
\r
409 dateLayout.addWidget(alteredTime, 0, 5);
\r
410 dateLayout.addWidget(subjectLabel, 0, 6);
\r
411 dateLayout.addWidget(subjectDate, 0, 7);
\r
412 dateLayout.addWidget(subjectTime, 0, 8);
\r
413 v.addLayout(dateLayout, 0);
\r
415 undoButton = newEditorButton("undo", tr("Undo Change"));
\r
416 redoButton = newEditorButton("redo", tr("Redo Change"));
\r
417 cutButton = newEditorButton("cut", tr("Cut"));
\r
418 copyButton = newEditorButton("copy", tr("Copy"));
\r
419 pasteButton = newEditorButton("paste", tr("Paste"));
\r
420 boldButton = newEditorButton("bold", tr("Bold"));
\r
421 underlineButton = newEditorButton("underline", tr("Underline"));
\r
422 italicButton = newEditorButton("italic", tr("Italic"));
\r
424 rightAlignButton = newEditorButton("justifyRight", tr("Right Align"));
\r
425 leftAlignButton = newEditorButton("justifyLeft", tr("Left Align"));
\r
426 centerAlignButton = newEditorButton("justifyCenter", tr("Center Align"));
\r
428 strikethroughButton = newEditorButton("strikethrough", tr("Strikethrough"));
\r
429 hlineButton = newEditorButton("hline", tr("Insert Horizontal Line"));
\r
430 indentButton = newEditorButton("indent", tr("Shift Right"));
\r
431 outdentButton = newEditorButton("outdent", tr("Shift Left"));
\r
432 bulletListButton = newEditorButton("bulletList", tr("Bullet List"));
\r
433 numberListButton = newEditorButton("numberList", tr("Number List"));
\r
434 spellCheckButton = newEditorButton("spellCheck", tr("Spell Check"));
\r
435 todoButton = newEditorButton("todo", tr("To-do"));
\r
438 buttonLayout = new EditorButtonBar();
\r
439 v.addWidget(buttonLayout);
\r
441 undoAction = buttonLayout.addWidget(undoButton);
\r
442 buttonLayout.toggleUndoVisible.triggered.connect(this, "toggleUndoVisible(Boolean)");
\r
443 redoAction = buttonLayout.addWidget(redoButton);
\r
444 buttonLayout.toggleRedoVisible.triggered.connect(this, "toggleRedoVisible(Boolean)");
\r
446 buttonLayout.addWidget(newSeparator());
\r
447 cutAction = buttonLayout.addWidget(cutButton);
\r
448 buttonLayout.toggleCutVisible.triggered.connect(this, "toggleCutVisible(Boolean)");
\r
449 copyAction = buttonLayout.addWidget(copyButton);
\r
450 buttonLayout.toggleCopyVisible.triggered.connect(this, "toggleCopyVisible(Boolean)");
\r
451 pasteAction = buttonLayout.addWidget(pasteButton);
\r
452 buttonLayout.togglePasteVisible.triggered.connect(this, "togglePasteVisible(Boolean)");
\r
454 buttonLayout.addWidget(newSeparator());
\r
455 boldAction = buttonLayout.addWidget(boldButton);
\r
456 buttonLayout.toggleBoldVisible.triggered.connect(this, "toggleBoldVisible(Boolean)");
\r
457 italicAction = buttonLayout.addWidget(italicButton);
\r
458 buttonLayout.toggleItalicVisible.triggered.connect(this, "toggleItalicVisible(Boolean)");
\r
459 underlineAction = buttonLayout.addWidget(underlineButton);
\r
460 buttonLayout.toggleUnderlineVisible.triggered.connect(this, "toggleUnderlineVisible(Boolean)");
\r
461 strikethroughAction = buttonLayout.addWidget(strikethroughButton);
\r
462 buttonLayout.toggleStrikethroughVisible.triggered.connect(this, "toggleStrikethroughVisible(Boolean)");
\r
465 buttonLayout.addWidget(newSeparator());
\r
466 leftAlignAction = buttonLayout.addWidget(leftAlignButton);
\r
467 buttonLayout.toggleLeftAlignVisible.triggered.connect(this, "toggleLeftAlignVisible(Boolean)");
\r
468 centerAlignAction = buttonLayout.addWidget(centerAlignButton);
\r
469 buttonLayout.toggleCenterAlignVisible.triggered.connect(this, "toggleCenterAlignVisible(Boolean)");
\r
470 rightAlignAction = buttonLayout.addWidget(rightAlignButton);
\r
471 buttonLayout.toggleRightAlignVisible.triggered.connect(this, "toggleRightAlignVisible(Boolean)");
\r
473 buttonLayout.addWidget(newSeparator());
\r
474 hlineAction = buttonLayout.addWidget(hlineButton);
\r
475 buttonLayout.toggleHLineVisible.triggered.connect(this, "toggleHLineVisible(Boolean)");
\r
477 indentAction = buttonLayout.addWidget(indentButton);
\r
478 buttonLayout.toggleIndentVisible.triggered.connect(this, "toggleIndentVisible(Boolean)");
\r
479 outdentAction = buttonLayout.addWidget(outdentButton);
\r
480 buttonLayout.toggleOutdentVisible.triggered.connect(this, "toggleOutdentVisible(Boolean)");
\r
481 bulletListAction = buttonLayout.addWidget(bulletListButton);
\r
482 buttonLayout.toggleBulletListVisible.triggered.connect(this, "toggleBulletListVisible(Boolean)");
\r
483 numberListAction = buttonLayout.addWidget(numberListButton);
\r
484 buttonLayout.toggleNumberListVisible.triggered.connect(this, "toggleNumberListVisible(Boolean)");
\r
486 // Setup the font & font size combo boxes
\r
487 buttonLayout.addWidget(newSeparator());
\r
488 fontList = new QComboBox();
\r
489 fontSize = new QComboBox();
\r
490 fontList.setToolTip("Font");
\r
491 fontSize.setToolTip("Font Size");
\r
492 fontList.activated.connect(this, "fontChanged(String)");
\r
493 fontSize.activated.connect(this, "fontSizeChanged(String)");
\r
494 fontListAction = buttonLayout.addWidget(fontList);
\r
495 buttonLayout.toggleFontVisible.triggered.connect(this, "toggleFontListVisible(Boolean)");
\r
496 fontSizeAction = buttonLayout.addWidget(fontSize);
\r
497 buttonLayout.toggleFontSizeVisible.triggered.connect(this, "toggleFontSizeVisible(Boolean)");
\r
498 QFontDatabase fonts = new QFontDatabase();
\r
499 List<String> fontFamilies = fonts.families();
\r
500 for (int i = 0; i < fontFamilies.size(); i++) {
\r
501 fontList.addItem(fontFamilies.get(i));
\r
503 loadFontSize(fontFamilies.get(i));
\r
507 // buttonLayout.addWidget(newSeparator(), 0);
\r
508 fontColor = newToolButton("fontColor", tr("Font Color"));
\r
509 fontColorMenu = new ColorMenu(this);
\r
510 fontColor.setMenu(fontColorMenu.getMenu());
\r
511 fontColor.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
512 fontColor.setAutoRaise(false);
\r
513 fontColorMenu.getMenu().triggered.connect(this, "fontColorClicked()");
\r
514 fontColorAction = buttonLayout.addWidget(fontColor);
\r
515 buttonLayout.toggleFontColorVisible.triggered.connect(this, "toggleFontColorVisible(Boolean)");
\r
516 fontHilight = newToolButton("fontHilight", tr("Font Hilight Color"));
\r
517 fontHilight.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
518 fontHilight.setAutoRaise(false);
\r
519 fontHilightColorMenu = new ColorMenu(this);
\r
520 fontHilightColorMenu.setDefault(QColor.yellow);
\r
521 fontHilight.setMenu(fontHilightColorMenu.getMenu());
\r
522 fontHilightColorMenu.getMenu().triggered.connect(this, "fontHilightClicked()");
\r
523 fontHilightAction = buttonLayout.addWidget(fontHilight);
\r
524 fontHilightColorMenu.setDefault(QColor.yellow);
\r
525 buttonLayout.toggleFontHilight.triggered.connect(this, "toggleFontHilightVisible(Boolean)");
\r
527 spellCheckAction = buttonLayout.addWidget(spellCheckButton);
\r
528 buttonLayout.toggleNumberListVisible.triggered.connect(this, "spellCheckClicked()");
\r
529 buttonLayout.toggleSpellCheck.triggered.connect(this, "toggleSpellCheckVisible(Boolean)");
\r
531 todoAction = buttonLayout.addWidget(todoButton);
\r
532 buttonLayout.toggleNumberListVisible.triggered.connect(this, "todoClicked()");
\r
533 buttonLayout.toggleTodo.triggered.connect(this, "toggleTodoVisible(Boolean)");
\r
536 // buttonLayout.addWidget(new QLabel(), 1);
\r
537 v.addWidget(browser, 1);
\r
540 browser.downloadAttachmentRequested.connect(this,
\r
541 "downloadAttachment(QNetworkRequest)");
\r
542 browser.downloadImageRequested.connect(this,
\r
543 "downloadImage(QNetworkRequest)");
\r
544 setTabOrder(notebookBox, tagEdit);
\r
545 setTabOrder(tagEdit, browser);
\r
547 focusNoteShortcut = new QShortcut(this);
\r
548 setupShortcut(focusNoteShortcut, "Focus_Note");
\r
549 focusNoteShortcut.activated.connect(this, "focusNote()");
\r
550 focusTitleShortcut = new QShortcut(this);
\r
551 setupShortcut(focusTitleShortcut, "Focus_Title");
\r
552 focusTitleShortcut.activated.connect(this, "focusTitle()");
\r
553 focusTagShortcut = new QShortcut(this);
\r
554 setupShortcut(focusTagShortcut, "Focus_Tag");
\r
555 focusTagShortcut.activated.connect(this, "focusTag()");
\r
556 focusAuthorShortcut = new QShortcut(this);
\r
557 setupShortcut(focusAuthorShortcut, "Focus_Author");
\r
558 focusAuthorShortcut.activated.connect(this, "focusAuthor()");
\r
559 focusUrlShortcut = new QShortcut(this);
\r
560 setupShortcut(focusUrlShortcut, "Focus_Url");
\r
561 focusUrlShortcut.activated.connect(this, "focusUrl()");
\r
563 browser.page().mainFrame().setTextSizeMultiplier(Global.getTextSizeMultiplier());
\r
564 browser.page().mainFrame().setZoomFactor(Global.getZoomFactor());
\r
566 previewPageList = new HashMap<String,Integer>();
\r
568 browser.page().microFocusChanged.connect(this, "microFocusChanged()");
\r
570 logger.log(logger.HIGH, "Browser setup complete");
\r
575 private void setupShortcut(QShortcut action, String text) {
\r
576 if (!Global.shortcutKeys.containsAction(text))
\r
578 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
\r
584 // Getter for the QWebView
\r
585 public QWebView getBrowser() {
\r
589 // Block signals while loading data or things are flagged as dirty by
\r
591 public void loadingData(boolean val) {
\r
592 logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val);
\r
593 notebookBox.blockSignals(val);
\r
594 browser.page().blockSignals(val);
\r
595 browser.page().mainFrame().blockSignals(val);
\r
596 titleLabel.blockSignals(val);
\r
597 alteredDate.blockSignals(val);
\r
598 alteredTime.blockSignals(val);
\r
599 createdTime.blockSignals(val);
\r
600 createdDate.blockSignals(val);
\r
601 subjectDate.blockSignals(val);
\r
602 subjectTime.blockSignals(val);
\r
603 urlText.blockSignals(val);
\r
604 authorText.blockSignals(val);
\r
606 exposeToJavascript();
\r
607 logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val);
\r
611 public void setReadOnly(boolean v) {
\r
613 titleLabel.setEnabled(!v);
\r
614 notebookBox.setEnabled(!v);
\r
615 tagEdit.setEnabled(!v);
\r
616 authorLabel.setEnabled(!v);
\r
617 geoBox.setEnabled(!v);
\r
618 urlText.setEnabled(!v);
\r
619 createdDate.setEnabled(!v);
\r
620 subjectDate.setEnabled(!v);
\r
621 alteredDate.setEnabled(!v);
\r
622 getBrowser().setEnabled(true);
\r
625 // expose this class to Javascript on the web page
\r
626 private void exposeToJavascript() {
\r
627 browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this);
\r
630 // Custom event queue
\r
632 public boolean event(QEvent e) {
\r
633 if (e.type().equals(QEvent.Type.FocusOut)) {
\r
634 logger.log(logger.EXTREME, "Focus lost");
\r
637 return super.event(e);
\r
640 // clear out browser
\r
641 public void clear() {
\r
642 logger.log(logger.EXTREME, "Entering BrowserWindow.clear()");
\r
644 browser.setContent(new QByteArray());
\r
645 tagEdit.setText("");
\r
646 tagEdit.tagCompleter.reset();
\r
647 urlLabel.setText(tr("Source URL:"));
\r
648 titleLabel.setText("");
\r
649 logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()");
\r
652 // get/set current note
\r
653 public void setNote(Note n) {
\r
657 saveNoteTitle = n.getTitle();
\r
661 public Note getNote() {
\r
662 return currentNote;
\r
665 // New Editor Button
\r
666 private QPushButton newEditorButton(String name, String toolTip) {
\r
667 QPushButton button = new QPushButton();
\r
668 // QIcon icon = new QIcon(iconPath + name + ".gif");
\r
669 QIcon icon = new QIcon(iconPath + name + ".png");
\r
670 button.setIcon(icon);
\r
671 button.setToolTip(toolTip);
\r
672 button.clicked.connect(this, name + "Clicked()");
\r
675 // New Editor Button
\r
676 private QToolButton newToolButton(String name, String toolTip) {
\r
677 QToolButton button = new QToolButton();
\r
678 // QIcon icon = new QIcon(iconPath + name + ".gif");
\r
679 QIcon icon = new QIcon(iconPath + name + ".png");
\r
680 button.setIcon(icon);
\r
681 button.setToolTip(toolTip);
\r
682 button.clicked.connect(this, name + "Clicked()");
\r
687 private QLabel newSeparator() {
\r
688 return new QLabel(" ");
\r
691 // Set the title in the window
\r
692 public void setTitle(String t) {
\r
693 titleLabel.setText(t);
\r
698 // Return the current text title
\r
699 public String getTitle() {
\r
700 return titleLabel.text();
\r
703 // Set the tag name string
\r
704 public void setTag(String t) {
\r
706 tagEdit.setText(t);
\r
707 tagEdit.tagCompleter.reset();
\r
710 // Set the source URL
\r
711 public void setUrl(String t) {
\r
712 urlLabel.setText(tr("Source URL:\t"));
\r
713 urlText.setText(t);
\r
716 // The user want's to launch a web browser on the source of the URL
\r
717 public void sourceUrlClicked() {
\r
718 // Make sure we have a valid URL
\r
719 if (urlText.text().trim().equals(""))
\r
722 String url = urlText.text();
\r
723 if (!url.toLowerCase().startsWith(tr("http://")))
\r
724 url = tr("http://") +url;
\r
726 if (!QDesktopServices.openUrl(new QUrl(url))) {
\r
727 logger.log(logger.LOW, "Error opening file :" +url);
\r
731 public void setAuthor(String t) {
\r
732 authorLabel.setText(tr("Author:\t"));
\r
733 authorText.setText(t);
\r
736 // Set the creation date
\r
737 public void setCreation(long date) {
\r
738 QDateTime dt = new QDateTime();
\r
739 dt.setTime_t((int) (date / 1000));
\r
740 createdDate.setDateTime(dt);
\r
741 createdTime.setDateTime(dt);
\r
742 createdDate.setDisplayFormat(Global.getDateFormat());
\r
743 createdTime.setDisplayFormat(Global.getTimeFormat());
\r
746 // Set the creation date
\r
747 public void setAltered(long date) {
\r
748 QDateTime dt = new QDateTime();
\r
749 dt.setTime_t((int) (date / 1000));
\r
750 alteredDate.setDateTime(dt);
\r
751 alteredTime.setDateTime(dt);
\r
752 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
753 alteredTime.setDisplayFormat(Global.getTimeFormat());
\r
756 // Set the subject date
\r
757 public void setSubjectDate(long date) {
\r
758 QDateTime dt = new QDateTime();
\r
759 dt.setTime_t((int) (date / 1000));
\r
760 subjectDate.setDateTime(dt);
\r
761 subjectTime.setDateTime(dt);
\r
762 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
763 subjectTime.setDisplayFormat(Global.getTimeFormat());
\r
766 // Toggle the extended attribute information
\r
767 public void toggleInformation() {
\r
769 extendedOn = false;
\r
773 urlLabel.setVisible(extendedOn);
\r
774 urlText.setVisible(extendedOn);
\r
775 authorText.setVisible(extendedOn);
\r
776 geoBox.setVisible(extendedOn);
\r
777 authorLabel.setVisible(extendedOn);
\r
778 createdDate.setVisible(extendedOn);
\r
779 createdTime.setVisible(extendedOn);
\r
780 createdLabel.setVisible(extendedOn);
\r
781 alteredLabel.setVisible(extendedOn);
\r
782 alteredDate.setVisible(extendedOn);
\r
783 alteredTime.setVisible(extendedOn);
\r
784 //notebookBox.setVisible(extendedOn);
\r
785 notebookLabel.setVisible(extendedOn);
\r
786 subjectLabel.setVisible(extendedOn);
\r
787 subjectDate.setVisible(extendedOn);
\r
788 subjectTime.setVisible(extendedOn);
\r
791 public void hideButtons() {
\r
793 undoButton.parentWidget().setVisible(false);
\r
794 buttonsVisible = false;
\r
798 // Is the extended view on?
\r
799 public boolean isExtended() {
\r
803 // Listener for when a link is clicked
\r
804 @SuppressWarnings("unused")
\r
805 private void openFile() {
\r
806 logger.log(logger.EXTREME, "Starting openFile()");
\r
807 File fileHandle = new File(selectedFile);
\r
808 URI fileURL = fileHandle.toURI();
\r
809 String localURL = fileURL.toString();
\r
810 QUrl url = new QUrl(localURL);
\r
811 QFile file = new QFile(selectedFile);
\r
813 logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName());
\r
814 fileWatcher.addPath(file.fileName());
\r
816 if (!QDesktopServices.openUrl(url)) {
\r
817 logger.log(logger.LOW, "Error opening file :" +url);
\r
822 // Listener for when a link is clicked
\r
823 @SuppressWarnings("unused")
\r
824 private void linkClicked(QUrl url) {
\r
825 logger.log(logger.EXTREME, "URL Clicked: " +url.toString());
\r
826 if (url.toString().substring(0,8).equals("nnres://")) {
\r
827 logger.log(logger.EXTREME, "URL is NN resource");
\r
828 if (url.toString().endsWith("/vnd.evernote.ink")) {
\r
829 logger.log(logger.EXTREME, "Unable to open ink note");
\r
830 QMessageBox.information(this, tr("Unable Open"), tr("This is an ink note.\n"+
\r
831 "Ink notes are not supported since Evernote has not\n published any specifications on them\n" +
\r
832 "and I'm too lazy to figure them out by myself."));
\r
835 String fullName = url.toString().substring(8);
\r
836 int index = fullName.indexOf(".");
\r
840 type = fullName.substring(index+1);
\r
841 guid = fullName.substring(0,index);
\r
843 index = guid.indexOf(Global.attachmentNameDelimeter);
\r
845 guid = guid.substring(0,index);
\r
847 List<Resource> resList = currentNote.getResources();
\r
848 Resource res = null;
\r
849 for (int i=0; i<resList.size(); i++) {
\r
850 if (resList.get(i).getGuid().equals(guid)) {
\r
851 res = resList.get(i);
\r
856 String resGuid = Global.resourceMap.get(guid);
\r
857 if (resGuid != null)
\r
858 res = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, true);
\r
862 if (res.getAttributes() != null &&
\r
863 res.getAttributes().getFileName() != null &&
\r
864 !res.getAttributes().getFileName().trim().equals(""))
\r
865 fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();
\r
867 fileName = res.getGuid()+"."+type;
\r
868 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
869 QFile.OpenMode mode = new QFile.OpenMode();
\r
870 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
871 boolean openResult = file.open(mode);
\r
872 logger.log(logger.EXTREME, "File opened:" +openResult);
\r
873 QDataStream out = new QDataStream(file);
\r
874 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);
\r
875 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
877 logger.log(logger.EXTREME, "Writing resource");
\r
878 out.writeBytes(binData.toByteArray());
\r
881 String whichOS = System.getProperty("os.name");
\r
882 if (whichOS.contains("Windows"))
\r
883 url.setUrl("file:///"+file.fileName());
\r
885 url.setUrl("file://"+file.fileName());
\r
886 // fileWatcher.removePath(file.fileName());
\r
887 logger.log(logger.EXTREME, "Adding file watcher " +file.fileName());
\r
888 fileWatcher.addPath(file.fileName());
\r
890 // If we can't open it, then prompt the user to save it.
\r
891 if (!QDesktopServices.openUrl(url)) {
\r
892 logger.log(logger.EXTREME, "We can't handle this. Where do we put it?");
\r
893 QFileDialog dialog = new QFileDialog();
\r
895 if (dialog.exec()!=0) {
\r
896 List<String> fileNames = dialog.selectedFiles(); //gets all selected filenames
\r
897 if (fileNames.size() == 0)
\r
899 String sf = fileNames.get(0);
\r
900 QFile saveFile = new QFile(sf);
\r
901 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
902 saveFile.open(mode);
\r
903 QDataStream saveOut = new QDataStream(saveFile);
\r
904 saveOut.writeBytes(binData.toByteArray());
\r
912 logger.log(logger.EXTREME, "Launching URL");
\r
913 QDesktopServices.openUrl(url);
\r
916 // Listener for when BOLD is clicked
\r
917 @SuppressWarnings("unused")
\r
918 private void undoClicked() {
\r
919 browser.page().triggerAction(WebAction.Undo);
\r
920 browser.setFocus();
\r
923 // Listener for when BOLD is clicked
\r
924 @SuppressWarnings("unused")
\r
925 private void redoClicked() {
\r
926 browser.page().triggerAction(WebAction.Redo);
\r
927 browser.setFocus();
\r
930 // Listener for when BOLD is clicked
\r
931 @SuppressWarnings("unused")
\r
932 private void boldClicked() {
\r
933 browser.page().triggerAction(WebAction.ToggleBold);
\r
934 microFocusChanged();
\r
935 browser.setFocus();
\r
938 // Listener for when Italics is clicked
\r
939 @SuppressWarnings("unused")
\r
940 private void italicClicked() {
\r
941 browser.page().triggerAction(WebAction.ToggleItalic);
\r
942 microFocusChanged();
\r
943 browser.setFocus();
\r
946 // Listener for when UNDERLINE is clicked
\r
947 @SuppressWarnings("unused")
\r
948 private void underlineClicked() {
\r
949 browser.page().triggerAction(WebAction.ToggleUnderline);
\r
950 microFocusChanged();
\r
951 browser.setFocus();
\r
954 // Listener for when Strikethrough is clicked
\r
955 @SuppressWarnings("unused")
\r
956 private void strikethroughClicked() {
\r
957 browser.page().mainFrame().evaluateJavaScript(
\r
958 "document.execCommand('strikeThrough', false, '');");
\r
959 browser.setFocus();
\r
962 // Listener for when cut is clicked
\r
963 @SuppressWarnings("unused")
\r
964 private void cutClicked() {
\r
965 browser.page().triggerAction(WebAction.Cut);
\r
966 browser.setFocus();
\r
969 // Listener when COPY is clicked
\r
970 @SuppressWarnings("unused")
\r
971 private void copyClicked() {
\r
972 browser.page().triggerAction(WebAction.Copy);
\r
973 browser.setFocus();
\r
976 // Listener when PASTE is clicked
\r
977 public void pasteClicked() {
\r
978 logger.log(logger.EXTREME, "Paste Clicked");
\r
979 if (forceTextPaste) {
\r
980 pasteWithoutFormattingClicked();
\r
983 QClipboard clipboard = QApplication.clipboard();
\r
984 QMimeData mime = clipboard.mimeData();
\r
986 // String x = mime.html();
\r
988 if (mime.hasImage()) {
\r
989 logger.log(logger.EXTREME, "Image paste found");
\r
990 browser.setFocus();
\r
992 browser.setFocus();
\r
996 if (mime.hasUrls()) {
\r
997 logger.log(logger.EXTREME, "URL paste found");
\r
999 browser.setFocus();
\r
1003 String text = mime.html();
\r
1004 if (text.contains("en-tag") && mime.hasHtml()) {
\r
1005 logger.log(logger.EXTREME, "Intra-note paste found");
\r
1006 text = fixInternotePaste(text);
\r
1007 mime.setHtml(text);
\r
1008 clipboard.setMimeData(mime);
\r
1011 logger.log(logger.EXTREME, "Final paste choice encountered");
\r
1012 browser.page().triggerAction(WebAction.Paste);
\r
1013 browser.setFocus();
\r
1017 // Paste text without formatting
\r
1018 private void pasteWithoutFormattingClicked() {
\r
1019 logger.log(logger.EXTREME, "Paste without format clipped");
\r
1020 QClipboard clipboard = QApplication.clipboard();
\r
1021 QMimeData mime = clipboard.mimeData();
\r
1022 if (!mime.hasText())
\r
1024 String text = mime.text();
\r
1025 clipboard.setText(text);
\r
1026 browser.page().triggerAction(WebAction.Paste);
\r
1027 QApplication.clipboard().setMimeData(mime);
\r
1028 browser.setFocus();
\r
1032 // insert date/time
\r
1033 @SuppressWarnings("unused")
\r
1034 private void insertDateTime() {
\r
1035 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
\r
1036 String dateTimeFormat = new String(fmt);
\r
1037 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
\r
1038 Calendar cal = Calendar.getInstance();
\r
1040 browser.page().mainFrame().evaluateJavaScript(
\r
1041 "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");
\r
1043 browser.setFocus();
\r
1047 // Listener when Left is clicked
\r
1048 @SuppressWarnings("unused")
\r
1049 private void justifyLeftClicked() {
\r
1050 browser.page().mainFrame().evaluateJavaScript(
\r
1051 "document.execCommand('JustifyLeft', false, '');");
\r
1052 browser.setFocus();
\r
1055 // Listener when Center is clicked
\r
1056 @SuppressWarnings("unused")
\r
1057 private void justifyCenterClicked() {
\r
1058 browser.page().mainFrame().evaluateJavaScript(
\r
1059 "document.execCommand('JustifyCenter', false, '');");
\r
1060 browser.setFocus();
\r
1063 // Listener when Left is clicked
\r
1064 @SuppressWarnings("unused")
\r
1065 private void justifyRightClicked() {
\r
1066 browser.page().mainFrame().evaluateJavaScript(
\r
1067 "document.execCommand('JustifyRight', false, '');");
\r
1068 browser.setFocus();
\r
1071 // Listener when HLINE is clicked
\r
1072 @SuppressWarnings("unused")
\r
1073 private void hlineClicked() {
\r
1074 browser.page().mainFrame().evaluateJavaScript(
\r
1075 "document.execCommand('insertHorizontalRule', false, '');");
\r
1076 browser.setFocus();
\r
1079 // Listener when outdent is clicked
\r
1080 private void outdentClicked() {
\r
1081 browser.page().mainFrame().evaluateJavaScript(
\r
1082 "document.execCommand('outdent', false, '');");
\r
1083 browser.setFocus();
\r
1086 // Listener when a bullet list is clicked
\r
1087 @SuppressWarnings("unused")
\r
1088 private void bulletListClicked() {
\r
1089 browser.page().mainFrame().evaluateJavaScript(
\r
1090 "document.execCommand('InsertUnorderedList', false, '');");
\r
1091 browser.setFocus();
\r
1094 // Listener when a bullet list is clicked
\r
1095 @SuppressWarnings("unused")
\r
1096 private void numberListClicked() {
\r
1097 browser.page().mainFrame().evaluateJavaScript(
\r
1098 "document.execCommand('InsertOrderedList', false, '');");
\r
1099 browser.setFocus();
\r
1102 // Listener when indent is clicked
\r
1103 private void indentClicked() {
\r
1104 browser.page().mainFrame().evaluateJavaScript(
\r
1105 "document.execCommand('indent', false, '');");
\r
1106 browser.setFocus();
\r
1109 // Listener when the font name is changed
\r
1110 @SuppressWarnings("unused")
\r
1111 private void fontChanged(String font) {
\r
1112 browser.page().mainFrame().evaluateJavaScript(
\r
1113 "document.execCommand('fontName',false,'" + font + "');");
\r
1114 browser.setFocus();
\r
1117 // Listener when a font size is changed
\r
1118 @SuppressWarnings("unused")
\r
1119 private void fontSizeChanged(String font) {
\r
1120 String text = browser.selectedText();
\r
1121 if (text.trim().equalsIgnoreCase(""))
\r
1124 String selectedText = browser.selectedText();
\r
1125 String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";
\r
1126 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1127 browser.page().mainFrame().evaluateJavaScript(script);
\r
1128 /* browser.page().mainFrame().evaluateJavaScript(
\r
1129 "document.execCommand('fontSize',false,'"
\r
1132 browser.setFocus();
\r
1135 // Load the font combo box based upon the font selected
\r
1136 private void loadFontSize(String name) {
\r
1137 QFontDatabase db = new QFontDatabase();
\r
1139 List<Integer> points = db.pointSizes(name);
\r
1140 for (int i=0; i<points.size(); i++) {
\r
1141 fontSize.addItem(points.get(i).toString());
\r
1144 fontSize.addItem("x-small");
\r
1145 fontSize.addItem("small");
\r
1146 fontSize.addItem("medium");
\r
1147 fontSize.addItem("large");
\r
1148 fontSize.addItem("x-large");
\r
1149 fontSize.addItem("xx-large");
\r
1150 fontSize.addItem("xxx-large");
\r
1154 // Listener when a font size is changed
\r
1155 @SuppressWarnings("unused")
\r
1156 private void fontColorClicked() {
\r
1157 // QColorDialog dialog = new QColorDialog();
\r
1158 // QColor color = QColorDialog.getColor();
\r
1159 QColor color = fontColorMenu.getColor();
\r
1160 if (color.isValid())
\r
1161 browser.page().mainFrame().evaluateJavaScript(
\r
1162 "document.execCommand('foreColor',false,'" + color.name()
\r
1164 browser.setFocus();
\r
1167 // Listener for when a background color change is requested
\r
1168 @SuppressWarnings("unused")
\r
1169 private void fontHilightClicked() {
\r
1170 // QColorDialog dialog = new QColorDialog();
\r
1171 // QColor color = QColorDialog.getColor();
\r
1172 QColor color = fontHilightColorMenu.getColor();
\r
1173 if (color.isValid())
\r
1174 browser.page().mainFrame().evaluateJavaScript(
\r
1175 "document.execCommand('backColor',false,'" + color.name()
\r
1177 browser.setFocus();
\r
1180 // Listener for when a background color change is requested
\r
1181 @SuppressWarnings("unused")
\r
1182 private void superscriptClicked() {
\r
1183 browser.page().mainFrame().evaluateJavaScript(
\r
1184 "document.execCommand('superscript');");
\r
1185 browser.setFocus();
\r
1188 // Listener for when a background color change is requested
\r
1189 @SuppressWarnings("unused")
\r
1190 private void subscriptClicked() {
\r
1191 browser.page().mainFrame().evaluateJavaScript(
\r
1192 "document.execCommand('subscript');");
\r
1193 browser.setFocus();
\r
1195 // Insert a to-do checkbox
\r
1196 @SuppressWarnings("unused")
\r
1197 private void todoClicked() {
\r
1198 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1199 String script_start = new String(
\r
1200 "document.execCommand('insertHtml', false, '");
\r
1201 String script_end = new String("');");
\r
1202 String todo = new String(
\r
1203 "<input TYPE=\"CHECKBOX\" value=\"false\" onClick=\"value=checked; window.jambi.contentChanged(); \" />");
\r
1204 browser.page().mainFrame().evaluateJavaScript(
\r
1205 script_start + todo + script_end);
\r
1206 browser.setFocus();
\r
1209 // Encrypt the selected text
\r
1210 @SuppressWarnings("unused")
\r
1211 private void encryptText() {
\r
1212 String text = browser.selectedText();
\r
1213 if (text.trim().equalsIgnoreCase(""))
\r
1215 text = new String(text.replaceAll("\n", "<br/>"));
\r
1217 EnCryptDialog dialog = new EnCryptDialog();
\r
1219 if (!dialog.okPressed()) {
\r
1223 EnCrypt crypt = new EnCrypt();
\r
1224 String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);
\r
1225 String decrypted = crypt.decrypt(encrypted, dialog.getPassword().trim(), 64);
\r
1227 if (encrypted.trim().equals("")) {
\r
1228 QMessageBox.information(this, tr("Error"), tr("Error Encrypting String"));
\r
1231 StringBuffer buffer = new StringBuffer(encrypted.length() + 100);
\r
1232 buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""
\r
1233 + dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");
\r
1234 buffer.append("contentEditable=\"false\" alt=\"");
\r
1235 buffer.append(encrypted);
\r
1236 buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png") +"\""));
\r
1237 Global.cryptCounter++;
\r
1238 buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");
\r
1239 buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");
\r
1240 buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString()
\r
1241 +"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&apos;")+"\\');\"");
\r
1242 buffer.append("style=\"display:block\" />");
\r
1244 String script_start = new String(
\r
1245 "document.execCommand('insertHtml', false, '");
\r
1246 String script_end = new String("');");
\r
1247 browser.page().mainFrame().evaluateJavaScript(
\r
1248 script_start + buffer.toString() + script_end);
\r
1252 // Insert a hyperlink
\r
1253 public void insertLink() {
\r
1254 logger.log(logger.EXTREME, "Inserting link");
\r
1255 String text = browser.selectedText();
\r
1256 if (text.trim().equalsIgnoreCase(""))
\r
1259 InsertLinkDialog dialog = new InsertLinkDialog();
\r
1260 if (currentHyperlink != null && currentHyperlink != "") {
\r
1261 dialog.setUrl(currentHyperlink);
\r
1264 if (!dialog.okPressed()) {
\r
1265 logger.log(logger.EXTREME, "Insert link canceled");
\r
1268 if (browser.insertLinkAction.text().equalsIgnoreCase("Insert Hyperlink")) {
\r
1269 String selectedText = browser.selectedText();
\r
1270 logger.log(logger.EXTREME, "Inserting link on text "+selectedText);
\r
1271 logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim());
\r
1272 String dUrl = StringUtils.replace(dialog.getUrl().trim(), "'", "\\'");
\r
1273 String url = "<a href=\"" +dUrl
\r
1274 +"\" title=" +dUrl
\r
1275 +" >"+selectedText +"</a>";
\r
1276 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1277 browser.page().mainFrame().evaluateJavaScript(script);
\r
1280 String js = new String( "function getCursorPos() {"
\r
1282 +"if (window.getSelection) {"
\r
1283 +" var selObj = window.getSelection();"
\r
1284 +" var selRange = selObj.getRangeAt(0);"
\r
1285 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1286 +" while(workingNode != null) { "
\r
1287 +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');"
\r
1288 +" workingNode = workingNode.parentNode;"
\r
1291 +"} getCursorPos();");
\r
1292 browser.page().mainFrame().evaluateJavaScript(js);
\r
1299 public void insertTable() {
\r
1300 TableDialog dialog = new TableDialog();
\r
1302 if (!dialog.okPressed()) {
\r
1306 int cols = dialog.getCols();
\r
1307 int rows = dialog.getRows();
\r
1308 int width = dialog.getWidth();
\r
1309 boolean percent = dialog.isPercent();
\r
1311 String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();
\r
1313 newHTML = newHTML +"%";
\r
1314 newHTML = newHTML + "\"><tbody>";
\r
1316 for (int i=0; i<rows; i++) {
\r
1317 newHTML = newHTML +"<tr>";
\r
1318 for (int j=0; j<cols; j++) {
\r
1319 newHTML = newHTML +"<td> </td>";
\r
1321 newHTML = newHTML +"</tr>";
\r
1323 newHTML = newHTML+"</tbody></table>";
\r
1325 String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";
\r
1326 browser.page().mainFrame().evaluateJavaScript(script);
\r
1330 // Text content changed
\r
1331 @SuppressWarnings("unused")
\r
1332 private void selectionChanged() {
\r
1333 browser.encryptAction.setEnabled(true);
\r
1334 browser.insertLinkAction.setEnabled(true);
\r
1335 String scriptStart = "var selection_text = (window.getSelection()).toString();"
\r
1336 + "var range = (window.getSelection()).getRangeAt(0);"
\r
1337 + "var parent_html = range.commonAncestorContainer.innerHTML;"
\r
1338 + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"
\r
1339 + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"
\r
1340 + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"
\r
1341 + "var start = parent_html.indexOf(first_text);"
\r
1342 + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"
\r
1343 + "var value = parent_html.substring(start,end);"
\r
1344 + "window.jambi.saveSelectedText(value);" ;
\r
1345 browser.page().mainFrame().evaluateJavaScript(scriptStart);
\r
1349 public void saveSelectedText(String text) {
\r
1350 boolean enabled = true;
\r
1351 if (text.trim().length() == 0)
\r
1353 if (text.indexOf("en-tag=\"en-crypt\"") >= 0)
\r
1355 if (text.indexOf("<img en-tag=\"en-media\"") >= 0)
\r
1357 if (text.indexOf("<a en-tag=\"en-media\"") >= 0)
\r
1359 if (text.indexOf("<input ") >= 0)
\r
1362 browser.encryptAction.setEnabled(enabled);
\r
1363 browser.insertLinkAction.setEnabled(enabled);
\r
1364 // selectedText = text;
\r
1367 // Decrypt clicked text
\r
1368 public void decryptText(String id, String text, String hint) {
\r
1369 EnCrypt crypt = new EnCrypt();
\r
1370 String plainText = null;
\r
1371 Calendar currentTime = new GregorianCalendar();
\r
1372 Long l = new Long(currentTime.getTimeInMillis());
\r
1373 String slot = new String(Long.toString(l));
\r
1375 // First, try to decrypt with any keys we already have
\r
1376 for (int i=0; i<Global.passwordRemember.size(); i++) {
\r
1377 plainText = crypt.decrypt(text, Global.passwordRemember.get(i).getFirst(), 64);
\r
1378 if (plainText != null) {
\r
1379 slot = new String(Long.toString(l));
\r
1380 Pair<String,String> passwordPair = new Pair<String,String>();
\r
1381 Global.passwordSafe.put(slot, Global.passwordRemember.get(i));
\r
1382 removeEncryption(id, plainText, false, slot);
\r
1388 EnDecryptDialog dialog = new EnDecryptDialog();
\r
1389 dialog.setHint(hint);
\r
1390 while (plainText == null || !dialog.okPressed()) {
\r
1392 if (!dialog.okPressed()) {
\r
1395 plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);
\r
1396 if (plainText == null) {
\r
1397 QMessageBox.warning(this, "Incorrect Password", "The password entered is not correct");
\r
1400 Pair<String,String> passwordPair = new Pair<String,String>();
\r
1401 passwordPair.setFirst(dialog.getPassword());
\r
1402 passwordPair.setSecond(dialog.getHint());
\r
1403 Global.passwordSafe.put(slot, passwordPair);
\r
1404 // removeEncryption(id, plainText.replaceAll("\n", "<br/>"), dialog.permanentlyDecrypt(), slot);
\r
1405 removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);
\r
1406 if (dialog.rememberPassword()) {
\r
1407 Pair<String, String> pair = new Pair<String,String>();
\r
1408 pair.setFirst(dialog.getPassword());
\r
1409 pair.setSecond(dialog.getHint());
\r
1410 Global.passwordRemember.add(pair);
\r
1415 // Get the editor tag line
\r
1416 public TagLineEdit getTagLine() {
\r
1420 // Modify a note's tags
\r
1421 @SuppressWarnings("unused")
\r
1422 private void modifyTags() {
\r
1423 TagAssign tagWindow = new TagAssign(allTags, currentTags);
\r
1425 if (tagWindow.okClicked()) {
\r
1426 currentTags.clear();
\r
1427 StringBuffer tagDisplay = new StringBuffer();
\r
1429 List<QListWidgetItem> newTags = tagWindow.getTagList()
\r
1431 for (int i = 0; i < newTags.size(); i++) {
\r
1432 currentTags.add(newTags.get(i).text());
\r
1433 tagDisplay.append(newTags.get(i).text());
\r
1434 if (i < newTags.size() - 1) {
\r
1435 tagDisplay.append(Global.tagDelimeter + " ");
\r
1438 tagEdit.setText(tagDisplay.toString());
\r
1439 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1443 // Tag line has been modified by typing text
\r
1444 @SuppressWarnings("unused")
\r
1445 private void modifyTagsTyping() {
\r
1446 String completionText = "";
\r
1447 if (tagEdit.currentCompleterSelection != null && !tagEdit.currentCompleterSelection.equals("")) {
\r
1448 completionText = tagEdit.currentCompleterSelection;
\r
1449 tagEdit.currentCompleterSelection = "";
\r
1452 if (tagEdit.text().equalsIgnoreCase(saveTagList))
\r
1455 // We know something has changed...
\r
1456 String oldTagArray[] = saveTagList.split(Global.tagDelimeter);
\r
1457 String newTagArray[];
\r
1458 if (!completionText.equals("")) {
\r
1459 String before = tagEdit.text().substring(0,tagEdit.cursorPosition());
\r
1460 int lastDelimiter = before.lastIndexOf(Global.tagDelimeter);
\r
1461 if (lastDelimiter > 0)
\r
1462 before = before.substring(0,before.lastIndexOf(Global.tagDelimeter));
\r
1465 String after = tagEdit.text().substring(tagEdit.cursorPosition());
\r
1466 newTagArray = (before+Global.tagDelimeter+completionText+Global.tagDelimeter+after).split(Global.tagDelimeter);
\r
1469 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1472 // Remove any traling or leading blanks
\r
1473 for (int i=0; i<newTagArray.length; i++)
\r
1474 newTagArray[i] = newTagArray[i].trim().replaceAll("^\\s+", "");;
\r
1476 // Remove any potential duplicates from the new list
\r
1477 for (int i=0; i<newTagArray.length; i++) {
\r
1478 boolean foundOnce = false;
\r
1479 for (int j=0; j<newTagArray.length; j++) {
\r
1480 if (newTagArray[j].equalsIgnoreCase(newTagArray[i])) {
\r
1484 newTagArray[j] = "";
\r
1489 List<String> newTagList = new ArrayList<String>();
\r
1490 List<String> oldTagList = new ArrayList<String>();
\r
1492 for (int i = 0; i < oldTagArray.length; i++)
\r
1493 if (!oldTagArray[i].trim().equals(""))
\r
1494 oldTagList.add(oldTagArray[i]);
\r
1495 for (int i = 0; i < newTagArray.length; i++)
\r
1496 if (!newTagArray[i].trim().equals(""))
\r
1497 newTagList.add(newTagArray[i]);
\r
1499 // Let's cleanup the appearance of the tag list
\r
1500 Collections.sort(newTagList);
\r
1501 String newDisplay = "";
\r
1502 for (int i=0; i<newTagList.size(); i++) {
\r
1503 newDisplay = newDisplay+newTagList.get(i);
\r
1504 if (i<newTagList.size()-1)
\r
1505 newDisplay = newDisplay+Global.tagDelimeter +" ";
\r
1507 tagEdit.blockSignals(true);
\r
1508 tagEdit.setText(newDisplay);
\r
1509 tagEdit.blockSignals(false);
\r
1511 // We now have lists of the new & old. Remove duplicates. If all
\r
1512 // are removed from both then nothing has really changed
\r
1513 for (int i = newTagList.size() - 1; i >= 0; i--) {
\r
1514 String nTag = newTagList.get(i);
\r
1515 for (int j = oldTagList.size() - 1; j >= 0; j--) {
\r
1516 String oTag = oldTagList.get(j);
\r
1517 if (oTag.equalsIgnoreCase(nTag)) {
\r
1518 oldTagList.remove(j);
\r
1519 newTagList.remove(i);
\r
1525 if (oldTagList.size() != 0 || newTagList.size() != 0) {
\r
1526 currentTags.clear();
\r
1527 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1528 for (int i = 0; i < newTagArray.length; i++)
\r
1529 if (!newTagArray[i].trim().equals(""))
\r
1530 currentTags.add(newTagArray[i].trim());
\r
1532 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1537 // Tab button was pressed
\r
1538 public void tabPressed() {
\r
1539 if (!insideList) {
\r
1540 String script_start = new String(
\r
1541 "document.execCommand('insertHtml', false, ' ');");
\r
1542 browser.page().mainFrame().evaluateJavaScript(script_start);
\r
1547 public void backtabPressed() {
\r
1552 public void setInsideList() {
\r
1553 insideList = true;
\r
1556 // The title has been edited
\r
1557 @SuppressWarnings("unused")
\r
1558 private void titleEdited() {
\r
1559 // If we don't have a good note, or if the current title
\r
1560 // matches the old title then we don't need to do anything
\r
1561 if (currentNote == null)
\r
1563 if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))
\r
1566 // If we have a real change, we need to save it.
\r
1567 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text());
\r
1568 currentNote.setTitle(titleLabel.text());
\r
1569 saveNoteTitle = titleLabel.text();
\r
1573 // Set the list of note tags
\r
1574 public void setAllTags(List<Tag> l) {
\r
1576 tagEdit.setTagList(l);
\r
1579 // Setter for the current tags
\r
1580 public void setCurrentTags(List<String> s) {
\r
1584 // Save the list of notebooks
\r
1585 public void setNotebookList(List<Notebook> n) {
\r
1587 loadNotebookList();
\r
1590 // Load the notebook list and select the current notebook
\r
1591 private void loadNotebookList() {
\r
1592 if (notebookBox.count() != 0)
\r
1593 notebookBox.clear();
\r
1594 if (notebookList == null)
\r
1597 for (int i = 0; i < notebookList.size(); i++) {
\r
1598 notebookBox.addItem(notebookList.get(i).getName());
\r
1599 if (currentNote != null) {
\r
1600 if (currentNote.getNotebookGuid().equals(
\r
1601 notebookList.get(i).getGuid())) {
\r
1602 notebookBox.setCurrentIndex(i);
\r
1609 // Set the notebook for a note
\r
1610 public void setNotebook(String notebook) {
\r
1611 currentNote.setNotebookGuid(notebook);
\r
1612 loadNotebookList();
\r
1615 // Get the contents of the editor
\r
1616 public String getContent() {
\r
1617 return browser.page().currentFrame().toHtml();
\r
1620 // The note contents have changed
\r
1621 public void contentChanged() {
\r
1622 String content = getContent();
\r
1624 noteSignal.noteChanged.emit(currentNote.getGuid(), content);
\r
1627 // The notebook selection has changed
\r
1628 @SuppressWarnings("unused")
\r
1629 private void notebookChanged() {
\r
1630 boolean changed = false;
\r
1631 String n = notebookBox.currentText();
\r
1632 for (int i = 0; i < notebookList.size(); i++) {
\r
1633 if (n.equals(notebookList.get(i).getName())) {
\r
1634 if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {
\r
1635 currentNote.setNotebookGuid(notebookList.get(i).getGuid());
\r
1638 i = notebookList.size();
\r
1642 // If the notebook changed, signal the update
\r
1644 noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote
\r
1645 .getNotebookGuid());
\r
1648 // Check the note title
\r
1649 private void checkNoteTitle() {
\r
1650 String text = browser.page().currentFrame().toPlainText();
\r
1651 if (saveNoteTitle.trim().equals("") || saveNoteTitle.trim().equals("Untitled Note")) {
\r
1652 int newLine = text.indexOf("\n");
\r
1653 if (newLine > 0) {
\r
1654 text = text.substring(0, newLine);
\r
1655 if (text.trim().equals(""))
\r
1656 text = tr("Untitled Note");
\r
1657 titleLabel.setText(text);
\r
1659 if (text.length() > Constants.EDAM_NOTE_TITLE_LEN_MAX)
\r
1660 titleLabel.setText(text.substring(0, Constants.EDAM_NOTE_TITLE_LEN_MAX));
\r
1662 titleLabel.blockSignals(true);
\r
1663 if (text.trim().equals(""))
\r
1664 titleLabel.setText(tr("Untitled Note"));
\r
1666 titleLabel.setText(text);
\r
1667 titleLabel.blockSignals(false);
\r
1670 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel
\r
1675 // Return the note contents so we can email them
\r
1676 public String getContentsToEmail() {
\r
1677 return browser.page().currentFrame().toPlainText().trim();
\r
1679 * int body = browser.page().currentFrame().toHtml().indexOf("<body>");
\r
1680 * String temp = browser.page().currentFrame().toHtml(); if (body == -1)
\r
1681 * temp = "<html><body><b>Test</b></body></html>"; else temp =
\r
1682 * "<html>"+temp.substring(body); return temp; // return
\r
1683 * urlEncode(browser.page().currentFrame().toHtml());
\r
1687 // Insert an image into the editor
\r
1688 private void insertImage(QMimeData mime) {
\r
1689 logger.log(logger.EXTREME, "Entering insertImage");
\r
1690 QImage img = (QImage) mime.imageData();
\r
1691 String script_start = new String(
\r
1692 "document.execCommand('insertHTML', false, '");
\r
1693 String script_end = new String("');");
\r
1695 long now = new Date().getTime();
\r
1696 String path = Global.getFileManager().getResDirPath(
\r
1697 (new Long(now).toString()) + ".jpg");
\r
1699 // This block is just a hack to make sure we wait at least 1ms so we
\r
1701 // have collisions on image names
\r
1702 long i = new Date().getTime();
\r
1704 i = new Date().getTime();
\r
1706 // Open the file & write the data
\r
1707 QFile tfile = new QFile(path);
\r
1708 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1709 if (!img.save(tfile)) {
\r
1715 Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);
\r
1716 if (newRes == null)
\r
1718 currentNote.getResources().add(newRes);
\r
1720 // do the actual insert into the note
\r
1721 StringBuffer buffer = new StringBuffer(100);
\r
1722 buffer.append("<img src=\"");
\r
1723 buffer.append(tfile.fileName());
\r
1724 buffer.append("\" en-tag=en-media type=\"image/jpeg\""
\r
1725 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1726 +" guid=\"" +newRes.getGuid() +"\""
\r
1727 // +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1728 +" onContextMenu=\"window.jambi.imageContextMenu(&." +tfile.fileName() +"&.);\""
\r
1731 browser.page().mainFrame().evaluateJavaScript(
\r
1732 script_start + buffer + script_end);
\r
1737 // Handle URLs that are trying to be pasted
\r
1738 public void handleUrls(QMimeData mime) {
\r
1739 logger.log(logger.EXTREME, "Starting handleUrls");
\r
1740 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1742 List<QUrl> urlList = mime.urls();
\r
1743 String url = new String();
\r
1744 String script_start = new String(
\r
1745 "document.execCommand('createLink', false, '");
\r
1746 String script_end = new String("');");
\r
1748 for (int i = 0; i < urlList.size(); i++) {
\r
1749 url = urlList.get(i).toString();
\r
1750 // Find out what type of file we have
\r
1751 String mimeType = fileNameMap.getContentTypeFor(url);
\r
1753 // If null returned, we need to guess at the file type
\r
1754 if (mimeType == null)
\r
1755 mimeType = "application/"
\r
1756 + url.substring(url.lastIndexOf(".") + 1);
\r
1758 // Check if we have an image or some other type of file
\r
1759 if (url.substring(0, 5).equalsIgnoreCase("file:")
\r
1760 && mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1761 handleLocalImageURLPaste(mime, mimeType);
\r
1764 String[] type = mimeType.split("/");
\r
1765 boolean valid = validAttachment(type[1]);
\r
1766 boolean smallEnough = checkFileAttachmentSize(url);
\r
1767 if (smallEnough && valid
\r
1768 && url.substring(0, 5).equalsIgnoreCase("file:")
\r
1769 && !mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1770 handleLocalAttachment(mime, mimeType);
\r
1773 browser.page().mainFrame().evaluateJavaScript(
\r
1774 script_start + url + script_end);
\r
1779 // If a URL being pasted is an image URL, then attach the image
\r
1780 private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {
\r
1781 List<QUrl> urlList = mime.urls();
\r
1782 String url = new String();
\r
1783 String script_start_image = new String(
\r
1784 "document.execCommand('insertHtml', false, '");
\r
1785 String script_end = new String("');");
\r
1786 StringBuffer buffer;
\r
1788 // Copy the image over into the resource directory and create a new resource
\r
1789 // record for each url pasted
\r
1790 for (int i = 0; i < urlList.size(); i++) {
\r
1791 url = urlList.get(i).toString();
\r
1793 Resource newRes = createResource(url, i, mimeType, false);
\r
1794 if (newRes == null)
\r
1796 currentNote.getResources().add(newRes);
\r
1797 buffer = new StringBuffer(100);
\r
1799 // Open the file & write the data
\r
1800 String fileName = Global.getFileManager().getResDirPath(newRes.getGuid());
\r
1801 QFile tfile = new QFile(fileName);
\r
1802 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1803 tfile.write(newRes.getData().getBody());
\r
1805 buffer.append(script_start_image);
\r
1806 buffer.append("<img src=\"" + FileUtils.toForwardSlashedPath(fileName));
\r
1807 // if (mimeType.equalsIgnoreCase("image/jpg"))
\r
1808 // mimeType = "image/jpeg";
\r
1809 buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""
\r
1810 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1811 +" guid=\"" +newRes.getGuid() +"\""
\r
1812 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1814 buffer.append(script_end);
\r
1815 browser.page().mainFrame().evaluateJavaScript(buffer.toString());
\r
1821 // If a URL being pasted is a local file URL, then attach the file
\r
1822 private void handleLocalAttachment(QMimeData mime, String mimeType) {
\r
1823 logger.log(logger.EXTREME, "Attaching local file");
\r
1824 List<QUrl> urlList = mime.urls();
\r
1825 String script_start = new String(
\r
1826 "document.execCommand('insertHtml', false, '");
\r
1827 String script_end = new String("');");
\r
1828 StringBuffer buffer;
\r
1830 String[] type = mimeType.split("/");
\r
1831 String icon = findIcon(type[1]);
\r
1832 if (icon.equals("attachment.png"))
\r
1833 icon = findIcon(type[0]);
\r
1834 buffer = new StringBuffer(100);
\r
1836 for (int i = 0; i < urlList.size(); i++) {
\r
1837 String url = urlList.get(i).toString();
\r
1839 // Start building the HTML
\r
1840 if (icon.equals("attachment.png"))
\r
1841 icon = findIcon(url.substring(url.lastIndexOf(".")+1));
\r
1842 String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));
\r
1844 logger.log(logger.EXTREME, "Creating resource ");
\r
1845 Resource newRes = createResource(url, i, mimeType, true);
\r
1846 if (newRes == null)
\r
1848 logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());
\r
1849 currentNote.getResources().add(newRes);
\r
1851 String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();
\r
1852 // If we have a PDF, we need to setup the preview.
\r
1853 if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {
\r
1854 logger.log(logger.EXTREME, "Setting up PDF preview");
\r
1855 if (newRes.getAttributes() != null &&
\r
1856 newRes.getAttributes().getFileName() != null &&
\r
1857 !newRes.getAttributes().getFileName().trim().equals(""))
\r
1858 fileName = newRes.getGuid()+Global.attachmentNameDelimeter+
\r
1859 newRes.getAttributes().getFileName();
\r
1861 fileName = newRes.getGuid()+".pdf";
\r
1862 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
1863 QFile.OpenMode mode = new QFile.OpenMode();
\r
1864 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
1866 QDataStream out = new QDataStream(file);
\r
1867 // Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);
\r
1868 QByteArray binData = new QByteArray(newRes.getData().getBody());
\r
1869 // resBinary = null;
\r
1870 out.writeBytes(binData.toByteArray());
\r
1873 PDFPreview pdfPreview = new PDFPreview();
\r
1874 if (pdfPreview.setupPreview(Global.getFileManager().getResDirPath(fileName), "pdf",0)) {
\r
1875 imageURL = file.fileName() + ".png";
\r
1879 logger.log(logger.EXTREME, "Generating link tags");
\r
1880 buffer.delete(0, buffer.length());
\r
1881 buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");
\r
1882 buffer.append(" onContextMenu=\"window.jambi.imageContextMenu('")
\r
1883 .append(Global.getFileManager().getResDirPath(fileName))
\r
1884 .append("');\" "); buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");
\r
1885 buffer.append("<img src=\"" + imageURL + "\" title=\"" +newRes.getAttributes().getFileName());
\r
1886 buffer.append("\"></img>");
\r
1887 buffer.append("</a>");
\r
1888 browser.page().mainFrame().evaluateJavaScript(
\r
1889 script_start + buffer.toString() + script_end);
\r
1894 private Resource createResource(String url, int sequence, String mime, boolean attachment) {
\r
1895 logger.log(logger.EXTREME, "Inside create resource");
\r
1896 QFile resourceFile;
\r
1897 String urlTest = new QUrl(url).toLocalFile();
\r
1898 if (!urlTest.equals(""))
\r
1900 url = url.replace("/", File.separator);
\r
1901 resourceFile = new QFile(url);
\r
1902 resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));
\r
1903 byte[] fileData = resourceFile.readAll().toByteArray();
\r
1904 resourceFile.close();
\r
1905 if (fileData.length == 0)
\r
1909 md = MessageDigest.getInstance("MD5");
\r
1910 md.update(fileData);
\r
1911 byte[] hash = md.digest();
\r
1913 Resource r = new Resource();
\r
1914 Calendar time = new GregorianCalendar();
\r
1915 long prevTime = time.getTimeInMillis();
\r
1916 while (prevTime == time.getTimeInMillis()) {
\r
1917 time = new GregorianCalendar();
\r
1919 r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());
\r
1920 r.setNoteGuid(currentNote.getGuid());
\r
1922 r.setActive(true);
\r
1923 r.setUpdateSequenceNum(0);
\r
1924 r.setWidth((short) 0);
\r
1925 r.setHeight((short) 0);
\r
1926 r.setDuration((short) 0);
\r
1928 Data d = new Data();
\r
1929 d.setBody(fileData);
\r
1930 d.setBodyIsSet(true);
\r
1931 d.setBodyHash(hash);
\r
1932 d.setBodyHashIsSet(true);
\r
1934 d.setSize(fileData.length);
\r
1936 int fileNamePos = url.lastIndexOf(File.separator);
\r
1937 if (fileNamePos == -1)
\r
1938 fileNamePos = url.lastIndexOf("/");
\r
1939 String fileName = url.substring(fileNamePos+1);
\r
1940 ResourceAttributes a = new ResourceAttributes();
\r
1942 a.setAltitudeIsSet(false);
\r
1943 a.setLongitude(0);
\r
1944 a.setLongitudeIsSet(false);
\r
1946 a.setLatitudeIsSet(false);
\r
1947 a.setCameraMake("");
\r
1948 a.setCameraMakeIsSet(false);
\r
1949 a.setCameraModel("");
\r
1950 a.setCameraModelIsSet(false);
\r
1951 a.setAttachment(attachment);
\r
1952 a.setAttachmentIsSet(true);
\r
1953 a.setClientWillIndex(false);
\r
1954 a.setClientWillIndexIsSet(true);
\r
1955 a.setRecoType("");
\r
1956 a.setRecoTypeIsSet(false);
\r
1957 a.setSourceURL(url);
\r
1958 a.setSourceURLIsSet(true);
\r
1959 a.setTimestamp(0);
\r
1960 a.setTimestampIsSet(false);
\r
1961 a.setFileName(fileName);
\r
1962 a.setFileNameIsSet(true);
\r
1963 r.setAttributes(a);
\r
1965 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
1967 } catch (NoSuchAlgorithmException e1) {
\r
1968 e1.printStackTrace();
\r
1974 // find the appropriate icon for an attachment
\r
1975 private String findIcon(String appl) {
\r
1976 appl = appl.toLowerCase();
\r
1977 File f = Global.getFileManager().getImageDirFile(appl + ".png");
\r
1979 return appl+".png";
\r
1980 return "attachment.png";
\r
1983 // Check if the account supports this type of attachment
\r
1984 private boolean validAttachment(String type) {
\r
1985 if (Global.isPremium())
\r
1987 if (type.equalsIgnoreCase("JPG"))
\r
1989 if (type.equalsIgnoreCase("PNG"))
\r
1991 if (type.equalsIgnoreCase("GIF"))
\r
1993 if (type.equalsIgnoreCase("MP3"))
\r
1995 if (type.equalsIgnoreCase("WAV"))
\r
1997 if (type.equalsIgnoreCase("AMR"))
\r
1999 if (type.equalsIgnoreCase("PDF"))
\r
2001 String error = tr("Non-premium accounts can only attach JPG, PNG, GIF, MP3, WAV, AMR, or PDF files.");
\r
2002 QMessageBox.information(this, tr("Non-Premium Account"), error);
\r
2007 // Check the file attachment to be sure it isn't over 25 mb
\r
2008 private boolean checkFileAttachmentSize(String url) {
\r
2009 String fileName = url.substring(8);
\r
2010 QFile resourceFile = new QFile(fileName);
\r
2011 resourceFile.open(new QIODevice.OpenMode(
\r
2012 QIODevice.OpenModeFlag.ReadOnly));
\r
2013 long size = resourceFile.size();
\r
2014 resourceFile.close();
\r
2015 size = size / 1024 / 1024;
\r
2016 if (size < 50 && Global.isPremium())
\r
2021 String error = tr("A file attachment may not exceed 25MB.");
\r
2022 QMessageBox.information(this, tr("Attachment Size"), error);
\r
2027 @SuppressWarnings("unused")
\r
2028 private void createdChanged() {
\r
2029 QDateTime dt = new QDateTime();
\r
2030 dt.setDate(createdDate.date());
\r
2031 dt.setTime(createdTime.time());
\r
2032 noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);
\r
2036 @SuppressWarnings("unused")
\r
2037 private void alteredChanged() {
\r
2038 QDateTime dt = new QDateTime();
\r
2039 dt.setDate(alteredDate.date());
\r
2040 dt.setTime(alteredTime.time());
\r
2041 noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);
\r
2044 @SuppressWarnings("unused")
\r
2045 private void subjectDateTimeChanged() {
\r
2046 QDateTime dt = new QDateTime();
\r
2047 dt.setDate(subjectDate.date());
\r
2048 dt.setTime(subjectTime.time());
\r
2049 noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);
\r
2053 @SuppressWarnings("unused")
\r
2054 private void sourceUrlChanged() {
\r
2055 noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());
\r
2058 @SuppressWarnings("unused")
\r
2059 private void authorChanged() {
\r
2060 noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());
\r
2063 @SuppressWarnings("unused")
\r
2064 private void geoBoxChanged() {
\r
2065 int index = geoBox.currentIndex();
\r
2066 geoBox.setCurrentIndex(0);
\r
2068 GeoDialog box = new GeoDialog();
\r
2069 box.setLongitude(currentNote.getAttributes().getLongitude());
\r
2070 box.setLatitude(currentNote.getAttributes().getLatitude());
\r
2071 box.setAltitude(currentNote.getAttributes().getAltitude());
\r
2073 if (!box.okPressed())
\r
2075 double alt = box.getAltitude();
\r
2076 double lat = box.getLatitude();
\r
2077 double lon = box.getLongitude();
\r
2078 if (alt != currentNote.getAttributes().getAltitude() ||
\r
2079 lon != currentNote.getAttributes().getLongitude() ||
\r
2080 lat != currentNote.getAttributes().getLatitude()) {
\r
2081 noteSignal.geoChanged.emit(currentNote.getGuid(), lon, lat, alt);
\r
2082 currentNote.getAttributes().setAltitude(alt);
\r
2083 currentNote.getAttributes().setLongitude(lon);
\r
2084 currentNote.getAttributes().setLatitude(lat);
\r
2089 noteSignal.geoChanged.emit(currentNote.getGuid(), 0.0, 0.0, 0.0);
\r
2090 currentNote.getAttributes().setAltitude(0.0);
\r
2091 currentNote.getAttributes().setLongitude(0.0);
\r
2092 currentNote.getAttributes().setLatitude(0.0);
\r
2095 if (index == 3 || index == 0) {
\r
2096 QDesktopServices.openUrl(new QUrl("http://maps.google.com/maps?z=6&q="+currentNote.getAttributes().getLatitude() +"," +currentNote.getAttributes().getLongitude()));
\r
2100 // ************************************************************
\r
2101 // * User chose to save an attachment. Pares out the request *
\r
2102 // * into a guid & file. Save the result. *
\r
2103 // ************************************************************
\r
2104 public void downloadAttachment(QNetworkRequest request) {
\r
2106 QFileDialog fd = new QFileDialog(this);
\r
2107 fd.setFileMode(FileMode.AnyFile);
\r
2108 fd.setConfirmOverwrite(true);
\r
2109 fd.setWindowTitle(tr("Save File"));
\r
2110 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2111 fd.setDirectory(System.getProperty("user.home"));
\r
2112 String name = request.url().toString();
\r
2114 int pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2116 guid = name.substring(0, pos).replace("nnres://", "");
\r
2117 name = name.substring(pos +Global.attachmentNameDelimeter.length());
\r
2118 fd.selectFile(name);
\r
2119 pos = name.lastIndexOf('.');
\r
2121 String mimeType = "(*." + name.substring(pos + 1)
\r
2122 + ");; All Files (*)";
\r
2123 fd.setFilter(tr(mimeType));
\r
2129 // Strip URL prefix and base dir
\r
2130 guid = guid.replace("nnres://", "")
\r
2131 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2133 pos = guid.lastIndexOf('.');
\r
2135 guid = guid.substring(0,pos);
\r
2136 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2137 name = name.replace('\\', '/');
\r
2138 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2139 QFile saveFile = new QFile(fd.selectedFiles().get(0));
\r
2140 QFile.OpenMode mode = new QFile.OpenMode();
\r
2141 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2142 saveFile.open(mode);
\r
2143 QDataStream saveOut = new QDataStream(saveFile);
\r
2144 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2145 saveOut.writeBytes(binData.toByteArray());
\r
2152 // ************************************************************
\r
2153 // * User chose to save an attachment. Pares out the request *
\r
2154 // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!
\r
2155 // ************************************************************
\r
2156 public void downloadImage(QNetworkRequest request) {
\r
2157 QFileDialog fd = new QFileDialog(this);
\r
2158 fd.setFileMode(FileMode.AnyFile);
\r
2159 fd.setConfirmOverwrite(true);
\r
2160 fd.setWindowTitle(tr("Save File"));
\r
2161 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2162 fd.setDirectory(System.getProperty("user.home"));
\r
2163 String name = request.url().toString();
\r
2164 name = name.replace("nnres://", "");
\r
2165 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
\r
2166 name = name.replace(dPath, "");
\r
2167 int pos = name.lastIndexOf('.');
\r
2168 String guid = name;
\r
2170 String mimeType = "(*." + name.substring(pos + 1)
\r
2171 + ");; All Files (*)";
\r
2172 fd.setFilter(tr(mimeType));
\r
2173 guid = guid.substring(0,pos);
\r
2175 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2177 guid = name.substring(0, pos);
\r
2178 fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));
\r
2180 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2181 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2182 String fileName = fd.selectedFiles().get(0);
\r
2183 QFile saveFile = new QFile(fileName);
\r
2184 QFile.OpenMode mode = new QFile.OpenMode();
\r
2185 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2186 saveFile.open(mode);
\r
2187 QDataStream saveOut = new QDataStream(saveFile);
\r
2188 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2189 saveOut.writeBytes(binData.toByteArray());
\r
2195 // *************************************************************
\r
2196 // * decrypt any hidden text. We could do an XML parse, but
\r
2197 // * it is quicker here just to scan for an <img tag & do the fix
\r
2198 // * the manual way
\r
2199 // *************************************************************
\r
2200 private void removeEncryption(String id, String plainText, boolean permanent, String slot) {
\r
2202 plainText = " <table class=\"en-crypt-temp\" slot=\""
\r
2205 +"border=1 width=100%><tbody><tr><td>"
\r
2206 +plainText+"</td></tr></tbody></table>";
\r
2209 String html = browser.page().mainFrame().toHtml();
\r
2210 String text = html;
\r
2211 int imagePos = html.indexOf("<img");
\r
2213 for ( ;imagePos>0; ) {
\r
2214 // Find the end tag
\r
2215 endPos = text.indexOf(">", imagePos);
\r
2216 String tag = text.substring(imagePos-1,endPos);
\r
2217 if (tag.indexOf("id=\""+id+"\"") > -1) {
\r
2218 text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);
\r
2219 QTextCodec codec = QTextCodec.codecForName("UTF-8");
\r
2220 QByteArray unicode = codec.fromUnicode(text);
\r
2221 browser.setContent(unicode);
\r
2225 imagePos = text.indexOf("<img", imagePos+1);
\r
2230 //****************************************************************
\r
2231 //* Focus shortcuts
\r
2232 //****************************************************************
\r
2233 @SuppressWarnings("unused")
\r
2234 private void focusTitle() {
\r
2235 titleLabel.setFocus();
\r
2237 @SuppressWarnings("unused")
\r
2238 private void focusTag() {
\r
2239 tagEdit.setFocus();
\r
2241 @SuppressWarnings("unused")
\r
2242 private void focusNote() {
\r
2243 browser.setFocus();
\r
2245 @SuppressWarnings("unused")
\r
2246 private void focusAuthor() {
\r
2247 authorLabel.setFocus();
\r
2249 @SuppressWarnings("unused")
\r
2250 private void focusUrl() {
\r
2251 urlLabel.setFocus();
\r
2255 //*****************************************************************
\r
2256 //* Set the document background color
\r
2257 //*****************************************************************
\r
2258 public void setBackgroundColor(String color) {
\r
2259 String js = "function changeBackground(color) {"
\r
2260 +"document.body.style.background = color;"
\r
2262 +"changeBackground('" +color+"');";
\r
2263 browser.page().mainFrame().evaluateJavaScript(js);
\r
2268 //****************************************************************
\r
2269 //* MicroFocus changed
\r
2270 //****************************************************************
\r
2271 private void microFocusChanged() {
\r
2272 boldButton.setDown(false);
\r
2273 italicButton.setDown(false);
\r
2274 underlineButton.setDown(false);
\r
2275 browser.openAction.setEnabled(false);
\r
2276 browser.downloadAttachment.setEnabled(false);
\r
2277 browser.downloadImage.setEnabled(false);
\r
2278 browser.rotateImageLeft.setEnabled(false);
\r
2279 browser.rotateImageRight.setEnabled(false);
\r
2280 browser.insertTableAction.setEnabled(true);
\r
2281 browser.insertTableRowAction.setEnabled(false);
\r
2282 browser.deleteTableRowAction.setEnabled(false);
\r
2283 browser.insertLinkAction.setText(tr("Insert Hyperlink"));
\r
2284 currentHyperlink ="";
\r
2285 insideList = false;
\r
2286 forceTextPaste = false;
\r
2288 String js = new String( "function getCursorPos() {"
\r
2290 +"if (window.getSelection) {"
\r
2291 +" var selObj = window.getSelection();"
\r
2292 +" var selRange = selObj.getRangeAt(0);"
\r
2293 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2294 +" while(workingNode != null) { "
\r
2295 // +" window.jambi.printNode(workingNode.nodeName);"
\r
2296 +" if (workingNode.nodeName=='TABLE') { if (workingNode.getAttribute('class').toLowerCase() == 'en-crypt-temp') window.jambi.forceTextPaste(); }"
\r
2297 +" if (workingNode.nodeName=='B') window.jambi.boldActive();"
\r
2298 +" if (workingNode.nodeName=='I') window.jambi.italicActive();"
\r
2299 +" if (workingNode.nodeName=='U') window.jambi.underlineActive();"
\r
2300 +" if (workingNode.nodeName=='UL') window.jambi.setInsideList();"
\r
2301 +" if (workingNode.nodeName=='OL') window.jambi.setInsideList();"
\r
2302 +" if (workingNode.nodeName=='LI') window.jambi.setInsideList();"
\r
2303 +" if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"
\r
2304 +" 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
2305 +" if (workingNode.nodeName=='SPAN') {"
\r
2306 +" if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"
\r
2308 +" workingNode = workingNode.parentNode;"
\r
2311 +"} getCursorPos();");
\r
2312 browser.page().mainFrame().evaluateJavaScript(js);
\r
2315 public void printNode(String n) {
\r
2316 System.out.println("Node Vaule: " +n);
\r
2320 //****************************************************************
\r
2321 //* Insert a table row
\r
2322 //****************************************************************
\r
2323 public void insertTableRow() {
\r
2325 String js = new String( "function insertTableRow() {"
\r
2326 +" var selObj = window.getSelection();"
\r
2327 +" var selRange = selObj.getRangeAt(0);"
\r
2328 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2329 +" var cellCount = 0;"
\r
2330 +" while(workingNode != null) { "
\r
2331 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2332 +" row = document.createElement('TR');"
\r
2333 +" var nodes = workingNode.getElementsByTagName('td');"
\r
2334 +" for (j=0; j<nodes.length; j=j+1) {"
\r
2335 +" cell = document.createElement('TD');"
\r
2336 +" cell.innerHTML=' ';"
\r
2337 +" row.appendChild(cell);"
\r
2339 +" workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"
\r
2342 +" workingNode = workingNode.parentNode;"
\r
2344 +"} insertTableRow();");
\r
2345 browser.page().mainFrame().evaluateJavaScript(js);
\r
2348 //****************************************************************
\r
2349 //* Insert a table row
\r
2350 //****************************************************************
\r
2351 public void deleteTableRow() {
\r
2353 String js = new String( "function deleteTableRow() {"
\r
2354 +" var selObj = window.getSelection();"
\r
2355 +" var selRange = selObj.getRangeAt(0);"
\r
2356 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2357 +" var cellCount = 0;"
\r
2358 +" while(workingNode != null) { "
\r
2359 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2360 +" workingNode.parentNode.removeChild(workingNode);"
\r
2363 +" workingNode = workingNode.parentNode;"
\r
2365 +"} deleteTableRow();");
\r
2366 browser.page().mainFrame().evaluateJavaScript(js);
\r
2369 public void setInsideTable() {
\r
2370 browser.insertTableRowAction.setEnabled(true);
\r
2371 browser.deleteTableRowAction.setEnabled(true);
\r
2372 browser.insertTableAction.setEnabled(false);
\r
2373 browser.encryptAction.setEnabled(false);
\r
2376 public void setInsideLink(String link) {
\r
2377 browser.insertLinkAction.setText(tr("Edit Hyperlink"));
\r
2378 currentHyperlink = link;
\r
2381 public void italicActive() {
\r
2382 italicButton.setDown(true);
\r
2384 public void boldActive() {
\r
2385 boldButton.setDown(true);
\r
2387 public void underlineActive() {
\r
2388 underlineButton.setDown(true);
\r
2390 public void forceTextPaste() {
\r
2391 forceTextPaste = true;
\r
2393 public void imageContextMenu(String f) {
\r
2394 browser.downloadImage.setEnabled(true);
\r
2395 browser.rotateImageRight.setEnabled(true);
\r
2396 browser.rotateImageLeft.setEnabled(true);
\r
2397 browser.openAction.setEnabled(true);
\r
2400 public void rotateImageRight() {
\r
2401 QWebSettings.setMaximumPagesInCache(0);
\r
2402 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2403 QImage image = new QImage(selectedFile);
\r
2404 QMatrix matrix = new QMatrix();
\r
2405 matrix.rotate( 90.0 );
\r
2406 image = image.transformed(matrix);
\r
2407 image.save(selectedFile);
\r
2408 QWebSettings.setMaximumPagesInCache(0);
\r
2409 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2410 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2413 // resourceSignal.contentChanged.emit(selectedFile);
\r
2416 public void rotateImageLeft() {
\r
2417 QImage image = new QImage(selectedFile);
\r
2418 QMatrix matrix = new QMatrix();
\r
2419 matrix.rotate( -90.0 );
\r
2420 image = image.transformed(matrix);
\r
2421 image.save(selectedFile);
\r
2422 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2425 // resourceSignal.contentChanged.emit(selectedFile);
\r
2427 public void resourceContextMenu(String f) {
\r
2428 browser.downloadAttachment.setEnabled(true);
\r
2429 browser.openAction.setEnabled(true);
\r
2434 //****************************************************************
\r
2435 //* Apply CSS style to specified word
\r
2436 //****************************************************************
\r
2437 /* public void applyStyleToWords(String word, String style) {
\r
2438 QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");
\r
2439 script.open(OpenModeFlag.ReadOnly);
\r
2440 String s = script.readAll().toString();
\r
2441 String js = new String(s +" findit('"+word+"', '"+style+"');");
\r
2442 browser.page().mainFrame().evaluateJavaScript(js);
\r
2443 System.out.println(getContent());
\r
2446 //****************************************************************
\r
2447 //* Someone tried to paste a resource between notes, so we need *
\r
2448 //* to do some special handling. *
\r
2449 //****************************************************************
\r
2450 private String fixInternotePaste(String text) {
\r
2451 logger.log(logger.EXTREME, "Fixing internote paste");
\r
2452 String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");
\r
2453 return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");
\r
2455 private String fixInternotePasteSearch(String text, String type, String locTag) {
\r
2457 // First, let's fix the images.
\r
2458 int startPos = text.indexOf(type);
\r
2460 for (; startPos>=0;) {
\r
2461 endPos = text.indexOf(">", startPos+1);
\r
2462 String segment = text.substring(startPos, endPos);
\r
2463 if (segment.indexOf("en-tag") > -1) {
\r
2464 String newSegment = segment;
\r
2466 int guidStartPos = segment.indexOf("guid=\"");
\r
2467 int guidEndPos = segment.indexOf("\"", guidStartPos+7);
\r
2468 String guid = segment.substring(guidStartPos+6,guidEndPos);
\r
2470 int mimeStartPos = segment.indexOf("type");
\r
2471 int mimeEndPos = segment.indexOf("\"", mimeStartPos+7);
\r
2472 String mime = segment.substring(mimeStartPos+6,mimeEndPos);
\r
2474 int srcStartPos = segment.indexOf("src");
\r
2475 int srcEndPos = segment.indexOf("\"", srcStartPos+6);
\r
2476 String src = segment.substring(srcStartPos+5,srcEndPos);
\r
2478 Calendar currentTime = new GregorianCalendar();
\r
2479 Long l = new Long(currentTime.getTimeInMillis());
\r
2480 long prevTime = l;
\r
2481 while (l==prevTime) {
\r
2482 currentTime = new GregorianCalendar();
\r
2483 l= new Long(currentTime.getTimeInMillis());
\r
2486 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2487 // if r==null, then the image doesn't exist (it was probably cut out of another note, so
\r
2488 // we need to recereate it
\r
2490 r = createResource(src, 1, mime, false);
\r
2494 String randint = new String(Long.toString(l));
\r
2495 String extension = null;
\r
2496 if (r.getMime()!= null) {
\r
2497 extension = r.getMime().toLowerCase();
\r
2498 if (extension.indexOf("/")>-1)
\r
2499 extension = extension.substring(extension.indexOf("/")+1);
\r
2501 String newFile = randint;
\r
2502 if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")
\r
2503 if (!locTag.startsWith("src"))
\r
2504 newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();
\r
2505 r.setNoteGuid(currentNote.getGuid());
\r
2507 r.setGuid(randint);
\r
2508 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
2509 QFile f = new QFile(Global.getFileManager().getResDirPath(newFile));
\r
2510 QByteArray bin = new QByteArray(r.getData().getBody());
\r
2511 f.open(QFile.OpenModeFlag.WriteOnly);
\r
2514 newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);
\r
2515 currentNote.getResources().add(r);
\r
2517 int startSrcPos = newSegment.indexOf(locTag);
\r
2518 int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);
\r
2520 if (locTag.startsWith("src")) {
\r
2521 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2522 newSegment = newSegment.replace(source,
\r
2523 FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath(newFile)));
\r
2525 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2526 newSegment = newSegment.replace(source, newFile);
\r
2529 text = text.substring(0,startPos) + newSegment + text.substring(endPos);
\r
2531 startPos = text.indexOf(type, startPos+1);
\r
2537 public void nextPage(String file) {
\r
2538 logger.log(logger.EXTREME, "Starting nextPage()");
\r
2540 Integer pageNumber;
\r
2541 if (previewPageList.containsKey(file))
\r
2542 pageNumber = previewPageList.get(file)+1;
\r
2545 previewPageList.remove(file);
\r
2546 previewPageList.put(file, pageNumber);
\r
2547 PDFPreview pdfPreview = new PDFPreview();
\r
2548 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2549 if (goodPreview) {
\r
2551 // String html = getContent();
\r
2552 QWebSettings.setMaximumPagesInCache(0);
\r
2553 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2554 // browser.setContent(new QByteArray());
\r
2555 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2557 // browser.setContent(new QByteArray(html));
\r
2558 // browser.triggerPageAction(WebAction.Reload);
\r
2559 // pdfMouseOver(selectedFile);
\r
2563 public void previousPage(String file) {
\r
2564 logger.log(logger.EXTREME, "Starting previousPage()");
\r
2566 Integer pageNumber;
\r
2567 if (previewPageList.containsKey(file))
\r
2568 pageNumber = previewPageList.get(file)-1;
\r
2571 previewPageList.remove(file);
\r
2572 previewPageList.put(file, pageNumber);
\r
2573 PDFPreview pdfPreview = new PDFPreview();
\r
2574 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2575 if (goodPreview) {
\r
2577 // String html = getContent();
\r
2578 QWebSettings.setMaximumPagesInCache(0);
\r
2579 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2580 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2582 // browser.setContent(new QByteArray(html));
\r
2583 // browser.triggerPageAction(WebAction.Reload);
\r
2587 /* public void pdfMouseOver(String name) {
\r
2589 if (previewPageList.containsKey(selectedFile))
\r
2590 pageNumber = previewPageList.get(selectedFile)+1;
\r
2594 if (pageNumber <= 1)
\r
2595 browser.previousPageAction.setEnabled(false);
\r
2597 browser.previousPageAction.setEnabled(true);
\r
2599 PDFPreview pdf = new PDFPreview();
\r
2600 int totalPages = pdf.getPageCount(name);
\r
2601 if (previewPageList.containsKey(selectedFile))
\r
2602 pageNumber = previewPageList.get(selectedFile)+1;
\r
2605 if (totalPages > pageNumber)
\r
2606 browser.nextPageAction.setEnabled(true);
\r
2608 browser.nextPageAction.setEnabled(false);
\r
2612 public void pdfMouseOut() {
\r
2613 // browser.nextPageAction.setVisible(false);
\r
2614 // browser.previousPageAction.setVisible(false);
\r
2618 private void toggleUndoVisible(Boolean toggle) {
\r
2619 undoAction.setVisible(toggle);
\r
2620 Global.saveEditorButtonsVisible("undo", toggle);
\r
2622 private void toggleRedoVisible(Boolean toggle) {
\r
2623 redoAction.setVisible(toggle);
\r
2624 Global.saveEditorButtonsVisible("redo", toggle);
\r
2626 private void toggleCutVisible(Boolean toggle) {
\r
2627 cutAction.setVisible(toggle);
\r
2628 Global.saveEditorButtonsVisible("cut", toggle);
\r
2630 private void toggleCopyVisible(Boolean toggle) {
\r
2631 copyAction.setVisible(toggle);
\r
2632 Global.saveEditorButtonsVisible("copy", toggle);
\r
2634 private void togglePasteVisible(Boolean toggle) {
\r
2635 pasteAction.setVisible(toggle);
\r
2636 Global.saveEditorButtonsVisible("paste", toggle);
\r
2638 private void toggleBoldVisible(Boolean toggle) {
\r
2639 boldAction.setVisible(toggle);
\r
2640 Global.saveEditorButtonsVisible("bold", toggle);
\r
2642 private void toggleItalicVisible(Boolean toggle) {
\r
2643 italicAction.setVisible(toggle);
\r
2644 Global.saveEditorButtonsVisible("italic", toggle);
\r
2646 private void toggleUnderlineVisible(Boolean toggle) {
\r
2647 underlineAction.setVisible(toggle);
\r
2648 Global.saveEditorButtonsVisible("underline", toggle);
\r
2650 private void toggleStrikethroughVisible(Boolean toggle) {
\r
2651 strikethroughAction.setVisible(toggle);
\r
2652 Global.saveEditorButtonsVisible("strikethrough", toggle);
\r
2654 private void toggleLeftAlignVisible(Boolean toggle) {
\r
2655 leftAlignAction.setVisible(toggle);
\r
2656 Global.saveEditorButtonsVisible("alignLeft", toggle);
\r
2658 private void toggleRightAlignVisible(Boolean toggle) {
\r
2659 rightAlignAction.setVisible(toggle);
\r
2660 Global.saveEditorButtonsVisible("alignRight", toggle);
\r
2662 private void toggleCenterAlignVisible(Boolean toggle) {
\r
2663 centerAlignAction.setVisible(toggle);
\r
2664 Global.saveEditorButtonsVisible("alignCenter", toggle);
\r
2666 private void toggleHLineVisible(Boolean toggle) {
\r
2667 hlineAction.setVisible(toggle);
\r
2668 Global.saveEditorButtonsVisible("hline", toggle);
\r
2670 private void toggleIndentVisible(Boolean toggle) {
\r
2671 indentAction.setVisible(toggle);
\r
2672 Global.saveEditorButtonsVisible("indent", toggle);
\r
2674 private void toggleTodoVisible(Boolean toggle) {
\r
2675 todoAction.setVisible(toggle);
\r
2676 Global.saveEditorButtonsVisible("todo", toggle);
\r
2678 private void toggleOutdentVisible(Boolean toggle) {
\r
2679 outdentAction.setVisible(toggle);
\r
2680 Global.saveEditorButtonsVisible("outdent", toggle);
\r
2682 private void toggleBulletListVisible(Boolean toggle) {
\r
2683 bulletListAction.setVisible(toggle);
\r
2684 Global.saveEditorButtonsVisible("bulletList", toggle);
\r
2686 private void toggleNumberListVisible(Boolean toggle) {
\r
2687 numberListAction.setVisible(toggle);
\r
2688 Global.saveEditorButtonsVisible("numberList", toggle);
\r
2690 private void toggleFontListVisible(Boolean toggle) {
\r
2691 fontListAction.setVisible(toggle);
\r
2692 Global.saveEditorButtonsVisible("font", toggle);
\r
2694 private void toggleFontColorVisible(Boolean toggle) {
\r
2695 fontColorAction.setVisible(toggle);
\r
2696 Global.saveEditorButtonsVisible("fontColor", toggle);
\r
2698 private void toggleFontSizeVisible(Boolean toggle) {
\r
2699 fontSizeAction.setVisible(toggle);
\r
2700 Global.saveEditorButtonsVisible("fontSize", toggle);
\r
2702 private void toggleFontHilightVisible(Boolean toggle) {
\r
2703 fontHilightAction.setVisible(toggle);
\r
2704 Global.saveEditorButtonsVisible("fontHilight", toggle);
\r
2706 private void toggleSpellCheckVisible(Boolean toggle) {
\r
2707 spellCheckAction.setVisible(toggle);
\r
2708 Global.saveEditorButtonsVisible("spellCheck", toggle);
\r
2712 private void setupDictionary() {
\r
2713 File wordList = new File(Global.getFileManager().getSpellDirPath()+Locale.getDefault()+".dic");
\r
2715 dictionary = new SpellDictionaryHashMap(wordList);
\r
2716 spellChecker = new SpellChecker(dictionary);
\r
2718 File userWordList;
\r
2719 userWordList = new File(Global.getFileManager().getSpellDirPathUser()+"user.dic");
\r
2721 // Get the local user spell dictionary
\r
2723 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
2724 } catch (FileNotFoundException e) {
\r
2725 userWordList.createNewFile();
\r
2726 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
2727 } catch (IOException e) {
\r
2728 userWordList.createNewFile();
\r
2729 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
2732 spellListener = new SuggestionListener(this, spellChecker);
\r
2734 // Add the user dictionary
\r
2735 spellChecker.addSpellCheckListener(spellListener);
\r
2736 spellChecker.setUserDictionary(userDictionary);
\r
2738 } catch (FileNotFoundException e) {
\r
2739 QMessageBox.critical(this, tr("Spell Check Error"),
\r
2740 tr("Dictionary "+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
2741 ".dic was not found."));
\r
2742 } catch (IOException e) {
\r
2743 QMessageBox.critical(this, tr("Spell Check Error"),
\r
2744 tr("Dictionary "+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
2745 ".dic is invalid."));
\r
2750 // Invoke spell checker dialog
\r
2751 private void spellCheckClicked() {
\r
2753 if (spellChecker == null) {
\r
2754 setupDictionary();
\r
2757 // Read user settings
\r
2758 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREDIGITWORDS,
\r
2759 Global.getSpellSetting(Configuration.SPELL_IGNOREDIGITWORDS));
\r
2760 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREINTERNETADDRESSES,
\r
2761 Global.getSpellSetting(Configuration.SPELL_IGNOREINTERNETADDRESSES));
\r
2762 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREMIXEDCASE,
\r
2763 Global.getSpellSetting(Configuration.SPELL_IGNOREMIXEDCASE));
\r
2764 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREUPPERCASE,
\r
2765 Global.getSpellSetting(Configuration.SPELL_IGNOREUPPERCASE));
\r
2766 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNORESENTENCECAPITALIZATION,
\r
2767 Global.getSpellSetting(Configuration.SPELL_IGNORESENTENCECAPITALIZATION));
\r
2769 spellListener.abortSpellCheck = false;
\r
2770 spellListener.errorsFound = false;
\r
2771 String content = getBrowser().page().mainFrame().toPlainText();
\r
2772 StringWordTokenizer tokenizer = new StringWordTokenizer(content);
\r
2773 if (!tokenizer.hasMoreWords())
\r
2775 getBrowser().page().action(WebAction.MoveToStartOfDocument);
\r
2777 getBrowser().setFocus();
\r
2780 // Move to the start of page
\r
2781 KeyboardModifiers ctrl = new KeyboardModifiers(KeyboardModifier.ControlModifier.value());
\r
2782 QKeyEvent home = new QKeyEvent(Type.KeyPress, Key.Key_Home.value(), ctrl);
\r
2783 browser.keyPressEvent(home);
\r
2784 getBrowser().setFocus();
\r
2786 tokenizer = new StringWordTokenizer(content);
\r
2789 while(tokenizer.hasMoreWords()) {
\r
2790 word = tokenizer.nextWord();
\r
2791 found = getBrowser().page().findText(word);
\r
2792 if (found && !spellListener.abortSpellCheck) {
\r
2793 spellChecker.checkSpelling(new StringWordTokenizer(word));
\r
2794 getBrowser().setFocus();
\r
2798 // Go to the end of the document & finish up.
\r
2799 home = new QKeyEvent(Type.KeyPress, Key.Key_End.value(), ctrl);
\r
2800 browser.keyPressEvent(home);
\r
2801 if (!spellListener.errorsFound)
\r
2802 QMessageBox.information(this, tr("Spell Check Complete"),
\r
2803 tr("No Errors Found"));
\r