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 com.evernote.edam.limits.Constants;
\r
41 import com.evernote.edam.type.Data;
\r
42 import com.evernote.edam.type.Note;
\r
43 import com.evernote.edam.type.Notebook;
\r
44 import com.evernote.edam.type.Resource;
\r
45 import com.evernote.edam.type.ResourceAttributes;
\r
46 import com.evernote.edam.type.Tag;
\r
47 import com.swabunga.spell.engine.SpellDictionary;
\r
48 import com.swabunga.spell.engine.SpellDictionaryHashMap;
\r
49 import com.swabunga.spell.engine.Word;
\r
50 import com.swabunga.spell.event.SpellCheckEvent;
\r
51 import com.swabunga.spell.event.SpellCheckListener;
\r
52 import com.swabunga.spell.event.SpellChecker;
\r
53 import com.swabunga.spell.event.StringWordTokenizer;
\r
54 import com.trolltech.qt.core.QByteArray;
\r
55 import com.trolltech.qt.core.QDataStream;
\r
56 import com.trolltech.qt.core.QDateTime;
\r
57 import com.trolltech.qt.core.QEvent;
\r
58 import com.trolltech.qt.core.QFile;
\r
59 import com.trolltech.qt.core.QFileSystemWatcher;
\r
60 import com.trolltech.qt.core.QIODevice;
\r
61 import com.trolltech.qt.core.QMimeData;
\r
62 import com.trolltech.qt.core.QUrl;
\r
63 import com.trolltech.qt.gui.QAction;
\r
64 import com.trolltech.qt.gui.QApplication;
\r
65 import com.trolltech.qt.gui.QCalendarWidget;
\r
66 import com.trolltech.qt.gui.QClipboard;
\r
67 import com.trolltech.qt.gui.QColor;
\r
68 import com.trolltech.qt.gui.QComboBox;
\r
69 import com.trolltech.qt.gui.QDateEdit;
\r
70 import com.trolltech.qt.gui.QDesktopServices;
\r
71 import com.trolltech.qt.gui.QFileDialog;
\r
72 import com.trolltech.qt.gui.QFileDialog.AcceptMode;
\r
73 import com.trolltech.qt.gui.QFileDialog.FileMode;
\r
74 import com.trolltech.qt.gui.QFontDatabase;
\r
75 import com.trolltech.qt.gui.QFormLayout;
\r
76 import com.trolltech.qt.gui.QGridLayout;
\r
77 import com.trolltech.qt.gui.QHBoxLayout;
\r
78 import com.trolltech.qt.gui.QIcon;
\r
79 import com.trolltech.qt.gui.QImage;
\r
80 import com.trolltech.qt.gui.QKeySequence;
\r
81 import com.trolltech.qt.gui.QLabel;
\r
82 import com.trolltech.qt.gui.QLineEdit;
\r
83 import com.trolltech.qt.gui.QListWidgetItem;
\r
84 import com.trolltech.qt.gui.QMatrix;
\r
85 import com.trolltech.qt.gui.QMessageBox;
\r
86 import com.trolltech.qt.gui.QPushButton;
\r
87 import com.trolltech.qt.gui.QShortcut;
\r
88 import com.trolltech.qt.gui.QTimeEdit;
\r
89 import com.trolltech.qt.gui.QToolButton;
\r
90 import com.trolltech.qt.gui.QToolButton.ToolButtonPopupMode;
\r
91 import com.trolltech.qt.gui.QVBoxLayout;
\r
92 import com.trolltech.qt.gui.QWidget;
\r
93 import com.trolltech.qt.network.QNetworkRequest;
\r
94 import com.trolltech.qt.webkit.QWebPage;
\r
95 import com.trolltech.qt.webkit.QWebPage.WebAction;
\r
96 import com.trolltech.qt.webkit.QWebSettings;
\r
97 import com.trolltech.qt.webkit.QWebView;
\r
99 import cx.fbn.nevernote.Global;
\r
100 import cx.fbn.nevernote.dialog.EnCryptDialog;
\r
101 import cx.fbn.nevernote.dialog.EnDecryptDialog;
\r
102 import cx.fbn.nevernote.dialog.GeoDialog;
\r
103 import cx.fbn.nevernote.dialog.InsertLinkDialog;
\r
104 import cx.fbn.nevernote.dialog.SpellCheck;
\r
105 import cx.fbn.nevernote.dialog.TableDialog;
\r
106 import cx.fbn.nevernote.dialog.TagAssign;
\r
107 import cx.fbn.nevernote.evernote.EnCrypt;
\r
108 import cx.fbn.nevernote.signals.NoteResourceSignal;
\r
109 import cx.fbn.nevernote.signals.NoteSignal;
\r
110 import cx.fbn.nevernote.sql.DatabaseConnection;
\r
111 import cx.fbn.nevernote.utilities.ApplicationLogger;
\r
112 import cx.fbn.nevernote.utilities.FileUtils;
\r
114 public class BrowserWindow extends QWidget {
\r
116 public final QLineEdit titleLabel;
\r
117 private final QLineEdit urlText;
\r
118 private final QLabel authorLabel;
\r
119 private final QLineEdit authorText;
\r
120 private final QComboBox geoBox;
\r
121 public final TagLineEdit tagEdit;
\r
122 public final QLabel tagLabel;
\r
123 private final QPushButton urlLabel;
\r
124 private final QLabel alteredLabel;
\r
125 private final QDateEdit alteredDate;
\r
126 private final QTimeEdit alteredTime;
\r
127 private final QDateEdit createdDate;
\r
128 private final QTimeEdit createdTime;
\r
129 private final QLabel subjectLabel;
\r
130 private final QDateEdit subjectDate;
\r
131 private final QTimeEdit subjectTime;
\r
132 public final QComboBox notebookBox;
\r
133 private final QLabel notebookLabel;
\r
134 private final QLabel createdLabel;
\r
135 public final QComboBox fontSize;
\r
136 public final QAction fontSizeAction;
\r
137 private boolean extendedOn;
\r
138 public boolean buttonsVisible;
\r
139 private final String iconPath = new String("classpath:cx/fbn/nevernote/icons/");
\r
140 private final ContentView browser;
\r
141 private List<Tag> allTags;
\r
142 private List<String> currentTags;
\r
143 public NoteSignal noteSignal;
\r
144 private List<Notebook> notebookList;
\r
145 private Note currentNote;
\r
146 private String saveNoteTitle;
\r
147 private String saveTagList;
\r
148 private boolean insideList;
\r
149 // private String selectedText;
\r
150 private final DatabaseConnection conn;
\r
151 private final QCalendarWidget createdCalendarWidget;
\r
152 private final QCalendarWidget alteredCalendarWidget;
\r
153 private final QCalendarWidget subjectCalendarWidget;
\r
155 public final QPushButton undoButton;
\r
156 public final QAction undoAction;
\r
157 public final QPushButton redoButton;
\r
158 public final QAction redoAction;
\r
159 public final QPushButton cutButton;
\r
160 public final QAction cutAction;
\r
161 public final QPushButton copyButton;
\r
162 public final QAction copyAction;
\r
163 public final QPushButton pasteButton;
\r
164 public final QAction pasteAction;
\r
165 public final QPushButton boldButton;
\r
166 public final QAction boldAction;
\r
167 public final QPushButton underlineButton;
\r
168 public final QAction underlineAction;
\r
169 public final QPushButton italicButton;
\r
170 public final QAction italicAction;
\r
171 public final Signal0 focusLost;
\r
172 public final NoteResourceSignal resourceSignal;
\r
174 public QPushButton rightAlignButton;
\r
175 public final QAction rightAlignAction;
\r
176 public QPushButton leftAlignButton;
\r
177 public final QAction leftAlignAction;
\r
178 public QPushButton centerAlignButton;
\r
179 public final QAction centerAlignAction;
\r
181 public final QPushButton strikethroughButton;
\r
182 public final QAction strikethroughAction;
\r
183 public final QPushButton hlineButton;
\r
184 public final QAction hlineAction;
\r
185 public final QPushButton indentButton;
\r
186 public final QAction indentAction;
\r
187 public final QPushButton outdentButton;
\r
188 public final QAction outdentAction;
\r
189 public final QPushButton bulletListButton;
\r
190 public final QAction bulletListAction;
\r
191 public final QPushButton numberListButton;
\r
192 public final QAction numberListAction;
\r
194 public final QShortcut focusTitleShortcut;
\r
195 public final QShortcut focusTagShortcut;
\r
196 public final QShortcut focusNoteShortcut;
\r
197 public final QShortcut focusUrlShortcut;
\r
198 public final QShortcut focusAuthorShortcut;
\r
200 public EditorButtonBar buttonLayout;
\r
201 public final QComboBox fontList;
\r
202 public final QAction fontListAction;
\r
204 public final QToolButton fontColor;
\r
205 public final QAction fontColorAction;
\r
206 private final ColorMenu fontColorMenu;
\r
207 public final QToolButton fontHilight;
\r
208 public final QAction fontHilightAction;
\r
210 public final QPushButton fontColor;
\r
211 public final QAction fontColorAction;
\r
212 private final ColorMenu fontColorMenu;
\r
213 public final QPushButton fontHilight;
\r
214 public final QAction fontHilightAction;
\r
215 // public final ColorComboBox fontHilight;
\r
216 >>>>>>> 14a0afe3faba057afbddf62aa8ed25139750d68b
217 private final ColorMenu fontHilightColorMenu;
\r
218 public final QFileSystemWatcher fileWatcher;
\r
219 public int cursorPosition;
\r
220 private boolean forceTextPaste = false;
\r
221 private String selectedFile;
\r
222 private String currentHyperlink;
\r
223 public boolean keepPDFNavigationHidden;
\r
224 private final ApplicationLogger logger;
\r
226 private final HashMap<String,Integer> previewPageList;
\r
229 public static class SuggestionListener implements SpellCheckListener {
\r
230 public boolean abortSpellCheck = false;
\r
231 public boolean errorsFound = false;
\r
233 private final BrowserWindow parent;
\r
234 public SuggestionListener(BrowserWindow parent) {
\r
235 this.parent = parent;
\r
237 public void spellingError(SpellCheckEvent event) {
\r
238 errorsFound = true;
\r
239 SpellCheck dialog = new SpellCheck();
\r
240 dialog.setWord(event.getInvalidWord());
\r
242 List<Word> suggestions = event.getSuggestions();
\r
243 if (suggestions.isEmpty()) {
\r
244 dialog.setNoSuggestions(true);
\r
246 dialog.setCurrentSuggestion(suggestions.get(0).getWord());
\r
247 for (int i=0; i<suggestions.size(); i++) {
\r
248 dialog.addSuggestion(suggestions.get(i).getWord());
\r
250 dialog.setSelectedSuggestion(0);
\r
253 if (dialog.cancelPressed()) {
\r
254 abortSpellCheck = true;
\r
257 if (dialog.replacePressed()) {
\r
258 QClipboard clipboard = QApplication.clipboard();
\r
259 clipboard.setText(dialog.getReplacementWord());
\r
260 parent.pasteClicked();
\r
267 public BrowserWindow(DatabaseConnection c) {
\r
268 logger = new ApplicationLogger("browser.log");
\r
269 logger.log(logger.HIGH, "Setting up browser");
\r
271 fileWatcher = new QFileSystemWatcher();
\r
272 // fileWatcher.fileChanged.connect(this, "fileChanged(String)");
\r
273 noteSignal = new NoteSignal();
\r
274 titleLabel = new QLineEdit();
\r
275 titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX);
\r
276 urlText = new QLineEdit();
\r
277 authorText = new QLineEdit();
\r
278 geoBox = new QComboBox();
\r
279 urlLabel = new QPushButton();
\r
280 urlLabel.clicked.connect(this, "sourceUrlClicked()");
\r
281 authorLabel = new QLabel();
\r
284 focusLost = new Signal0();
\r
286 tagEdit = new TagLineEdit(allTags);
\r
287 tagLabel = new QLabel("Tags:");
\r
288 tagEdit.focusLost.connect(this, "modifyTagsTyping()");
\r
290 createdCalendarWidget = new QCalendarWidget();
\r
291 createdDate = new QDateEdit();
\r
292 createdDate.setDisplayFormat(Global.getDateFormat());
\r
293 createdDate.setCalendarPopup(true);
\r
294 createdDate.setCalendarWidget(createdCalendarWidget);
\r
295 createdTime = new QTimeEdit();
\r
296 createdDate.dateChanged.connect(this, "createdChanged()");
\r
297 createdTime.timeChanged.connect(this, "createdChanged()");
\r
299 alteredCalendarWidget = new QCalendarWidget();
\r
300 alteredDate = new QDateEdit();
\r
301 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
302 alteredDate.setCalendarPopup(true);
\r
303 alteredDate.setCalendarWidget(alteredCalendarWidget);
\r
304 alteredTime = new QTimeEdit();
\r
305 alteredLabel = new QLabel("Altered:");
\r
306 alteredDate.dateChanged.connect(this, "alteredChanged()");
\r
307 alteredTime.timeChanged.connect(this, "alteredChanged()");
\r
309 subjectCalendarWidget = new QCalendarWidget();
\r
310 subjectDate = new QDateEdit();
\r
311 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
312 subjectDate.setCalendarPopup(true);
\r
313 subjectDate.setCalendarWidget(subjectCalendarWidget);
\r
314 subjectTime = new QTimeEdit();
\r
315 subjectLabel = new QLabel(tr("Subject Date:"));
\r
316 subjectDate.dateChanged.connect(this, "subjectDateTimeChanged()");
\r
317 subjectTime.timeChanged.connect(this, "subjectDateTimeChanged()");
\r
318 authorText.textChanged.connect(this, "authorChanged()");
\r
319 urlText.textChanged.connect(this, "sourceUrlChanged()");
\r
321 notebookBox = new QComboBox();
\r
322 notebookLabel = new QLabel(tr("Notebook"));
\r
323 createdLabel = new QLabel(tr("Created:"));
\r
324 // selectedText = new String();
\r
326 urlLabel.setVisible(false);
\r
327 urlText.setVisible(false);
\r
328 authorLabel.setVisible(false);
\r
330 geoBox.setVisible(false);
\r
331 geoBox.addItem(new QIcon(iconPath+"globe.png"), "");
\r
332 geoBox.addItem(new String(tr("Set")));
\r
333 geoBox.addItem(new String(tr("Clear")));
\r
334 geoBox.addItem(new String(tr("View On Map")));
\r
335 geoBox.activated.connect(this, "geoBoxChanged()");
\r
337 authorText.setVisible(false);
\r
338 createdDate.setVisible(false);
\r
339 alteredLabel.setVisible(false);
\r
340 //notebookBox.setVisible(false);
\r
341 notebookLabel.setVisible(false);
\r
342 createdLabel.setVisible(false);
\r
343 createdTime.setVisible(false);
\r
344 alteredDate.setVisible(false);
\r
345 alteredTime.setVisible(false);
\r
346 subjectLabel.setVisible(false);
\r
347 subjectDate.setVisible(false);
\r
348 subjectTime.setVisible(false);
\r
349 extendedOn = false;
\r
350 buttonsVisible = true;
\r
351 setAcceptDrops(true);
\r
353 browser = new ContentView(this);
\r
354 browser.page().setLinkDelegationPolicy(
\r
355 QWebPage.LinkDelegationPolicy.DelegateAllLinks);
\r
356 browser.linkClicked.connect(this, "linkClicked(QUrl)");
\r
357 currentHyperlink = "";
\r
359 QVBoxLayout v = new QVBoxLayout();
\r
360 QFormLayout notebookLayout = new QFormLayout();
\r
361 QGridLayout dateLayout = new QGridLayout();
\r
362 titleLabel.setReadOnly(false);
\r
363 titleLabel.editingFinished.connect(this, "titleEdited()");
\r
364 browser.page().contentsChanged.connect(this, "contentChanged()");
\r
365 browser.page().selectionChanged.connect(this, "selectionChanged()");
\r
366 browser.page().mainFrame().javaScriptWindowObjectCleared.connect(this,
\r
367 "exposeToJavascript()");
\r
369 notebookBox.activated.connect(this, "notebookChanged()");
\r
370 resourceSignal = new NoteResourceSignal();
\r
372 QHBoxLayout tagLayout = new QHBoxLayout();
\r
373 v.addWidget(titleLabel, 0);
\r
374 notebookLayout.addRow(notebookLabel, notebookBox);
\r
375 tagLayout.addLayout(notebookLayout, 0);
\r
376 tagLayout.stretch(4);
\r
377 tagLayout.addWidget(tagLabel, 0);
\r
378 tagLayout.addWidget(tagEdit, 1);
\r
379 v.addLayout(tagLayout);
\r
381 QHBoxLayout urlLayout = new QHBoxLayout();
\r
382 urlLayout.addWidget(urlLabel, 0);
\r
383 urlLayout.addWidget(urlText, 0);
\r
384 v.addLayout(urlLayout);
\r
386 QHBoxLayout authorLayout = new QHBoxLayout();
\r
387 authorLayout.addWidget(authorLabel, 0);
\r
388 authorLayout.addWidget(authorText, 0);
\r
389 authorLayout.addWidget(geoBox);
\r
390 v.addLayout(authorLayout);
\r
392 dateLayout.addWidget(createdLabel, 0, 0);
\r
393 dateLayout.addWidget(createdDate, 0, 1);
\r
394 dateLayout.addWidget(createdTime, 0, 2);
\r
395 dateLayout.setColumnStretch(9, 100);
\r
396 dateLayout.addWidget(alteredLabel, 0, 3);
\r
397 dateLayout.addWidget(alteredDate, 0, 4);
\r
398 dateLayout.addWidget(alteredTime, 0, 5);
\r
399 dateLayout.addWidget(subjectLabel, 0, 6);
\r
400 dateLayout.addWidget(subjectDate, 0, 7);
\r
401 dateLayout.addWidget(subjectTime, 0, 8);
\r
402 v.addLayout(dateLayout, 0);
\r
404 undoButton = newEditorButton("undo", tr("Undo Change"));
\r
405 redoButton = newEditorButton("redo", tr("Redo Change"));
\r
406 cutButton = newEditorButton("cut", tr("Cut"));
\r
407 copyButton = newEditorButton("copy", tr("Copy"));
\r
408 pasteButton = newEditorButton("paste", tr("Paste"));
\r
409 boldButton = newEditorButton("bold", tr("Bold"));
\r
410 underlineButton = newEditorButton("underline", tr("Underline"));
\r
411 italicButton = newEditorButton("italic", tr("Italic"));
\r
413 rightAlignButton = newEditorButton("justifyRight", tr("Right Align"));
\r
414 leftAlignButton = newEditorButton("justifyLeft", tr("Left Align"));
\r
415 centerAlignButton = newEditorButton("justifyCenter", tr("Center Align"));
\r
417 strikethroughButton = newEditorButton("strikethrough", tr("Strikethrough"));
\r
418 hlineButton = newEditorButton("hline", tr("Insert Horizontal Line"));
\r
419 indentButton = newEditorButton("indent", tr("Shift Right"));
\r
420 outdentButton = newEditorButton("outdent", tr("Shift Left"));
\r
421 bulletListButton = newEditorButton("bulletList", tr("Bullet List"));
\r
422 numberListButton = newEditorButton("numberList", tr("Number List"));
\r
425 buttonLayout = new EditorButtonBar();
\r
426 // buttonLayout.setSpacing(0);
\r
427 v.addWidget(buttonLayout);
\r
429 undoAction = buttonLayout.addWidget(undoButton);
\r
430 buttonLayout.toggleUndoVisible.triggered.connect(this, "toggleUndoVisible(Boolean)");
\r
431 redoAction = buttonLayout.addWidget(redoButton);
\r
432 buttonLayout.toggleRedoVisible.triggered.connect(this, "toggleRedoVisible(Boolean)");
\r
434 buttonLayout.addWidget(newSeparator());
\r
435 cutAction = buttonLayout.addWidget(cutButton);
\r
436 buttonLayout.toggleCutVisible.triggered.connect(this, "toggleCutVisible(Boolean)");
\r
437 copyAction = buttonLayout.addWidget(copyButton);
\r
438 buttonLayout.toggleCopyVisible.triggered.connect(this, "toggleCopyVisible(Boolean)");
\r
439 pasteAction = buttonLayout.addWidget(pasteButton);
\r
440 buttonLayout.togglePasteVisible.triggered.connect(this, "togglePasteVisible(Boolean)");
\r
442 buttonLayout.addWidget(newSeparator());
\r
443 boldAction = buttonLayout.addWidget(boldButton);
\r
444 buttonLayout.toggleBoldVisible.triggered.connect(this, "toggleBoldVisible(Boolean)");
\r
445 italicAction = buttonLayout.addWidget(italicButton);
\r
446 buttonLayout.toggleItalicVisible.triggered.connect(this, "toggleItalicVisible(Boolean)");
\r
447 underlineAction = buttonLayout.addWidget(underlineButton);
\r
448 buttonLayout.toggleUnderlineVisible.triggered.connect(this, "toggleUnderlineVisible(Boolean)");
\r
449 strikethroughAction = buttonLayout.addWidget(strikethroughButton);
\r
450 buttonLayout.toggleStrikethroughVisible.triggered.connect(this, "toggleStrikethroughVisible(Boolean)");
\r
453 buttonLayout.addWidget(newSeparator());
\r
454 leftAlignAction = buttonLayout.addWidget(leftAlignButton);
\r
455 buttonLayout.toggleLeftAlignVisible.triggered.connect(this, "toggleLeftAlignVisible(Boolean)");
\r
456 centerAlignAction = buttonLayout.addWidget(centerAlignButton);
\r
457 buttonLayout.toggleCenterAlignVisible.triggered.connect(this, "toggleCenterAlignVisible(Boolean)");
\r
458 rightAlignAction = buttonLayout.addWidget(rightAlignButton);
\r
459 buttonLayout.toggleRightAlignVisible.triggered.connect(this, "toggleRightAlignVisible(Boolean)");
\r
461 buttonLayout.addWidget(newSeparator());
\r
462 hlineAction = buttonLayout.addWidget(hlineButton);
\r
463 buttonLayout.toggleHLineVisible.triggered.connect(this, "toggleHLineVisible(Boolean)");
\r
465 indentAction = buttonLayout.addWidget(indentButton);
\r
466 buttonLayout.toggleIndentVisible.triggered.connect(this, "toggleIndentVisible(Boolean)");
\r
467 outdentAction = buttonLayout.addWidget(outdentButton);
\r
468 buttonLayout.toggleOutdentVisible.triggered.connect(this, "toggleOutdentVisible(Boolean)");
\r
469 bulletListAction = buttonLayout.addWidget(bulletListButton);
\r
470 buttonLayout.toggleBulletListVisible.triggered.connect(this, "toggleBulletListVisible(Boolean)");
\r
471 numberListAction = buttonLayout.addWidget(numberListButton);
\r
472 buttonLayout.toggleNumberListVisible.triggered.connect(this, "toggleNumberListVisible(Boolean)");
\r
474 // Setup the font & font size combo boxes
\r
475 buttonLayout.addWidget(newSeparator());
\r
476 fontList = new QComboBox();
\r
477 fontSize = new QComboBox();
\r
478 fontList.setToolTip("Font");
\r
479 fontSize.setToolTip("Font Size");
\r
480 fontList.activated.connect(this, "fontChanged(String)");
\r
481 fontSize.activated.connect(this, "fontSizeChanged(String)");
\r
482 fontListAction = buttonLayout.addWidget(fontList);
\r
483 buttonLayout.toggleFontVisible.triggered.connect(this, "toggleFontListVisible(Boolean)");
\r
484 fontSizeAction = buttonLayout.addWidget(fontSize);
\r
485 buttonLayout.toggleFontSizeVisible.triggered.connect(this, "toggleFontSizeVisible(Boolean)");
\r
486 QFontDatabase fonts = new QFontDatabase();
\r
487 List<String> fontFamilies = fonts.families();
\r
488 for (int i = 0; i < fontFamilies.size(); i++) {
\r
489 fontList.addItem(fontFamilies.get(i));
\r
491 loadFontSize(fontFamilies.get(i));
\r
495 // buttonLayout.addWidget(newSeparator(), 0);
\r
497 fontColor = newToolButton("fontColor", tr("Font Color"));
\r
499 fontColor = newEditorButton("fontColor", tr("Font Color"));
\r
500 >>>>>>> 14a0afe3faba057afbddf62aa8ed25139750d68b
501 fontColorMenu = new ColorMenu(this);
\r
502 fontColor.setMenu(fontColorMenu.getMenu());
\r
503 fontColor.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
504 fontColor.setAutoRaise(false);
\r
505 fontColorMenu.getMenu().triggered.connect(this, "fontColorClicked()");
\r
506 fontColorAction = buttonLayout.addWidget(fontColor);
\r
507 buttonLayout.toggleFontColorVisible.triggered.connect(this, "toggleFontColorVisible(Boolean)");
\r
509 fontHilight = newToolButton("fontHilight", tr("Font Hilight Color"));
\r
510 fontHilight.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
511 fontHilight.setAutoRaise(false);
\r
513 fontHilight = newEditorButton("fontHilight", tr("Font Hilight Color"));
\r
514 >>>>>>> 14a0afe3faba057afbddf62aa8ed25139750d68b
515 fontHilightColorMenu = new ColorMenu(this);
\r
516 fontHilightColorMenu.setDefault(QColor.yellow);
\r
517 fontHilight.setMenu(fontHilightColorMenu.getMenu());
\r
518 fontHilightColorMenu.getMenu().triggered.connect(this, "fontHilightClicked()");
\r
519 fontHilightAction = buttonLayout.addWidget(fontHilight);
\r
521 fontHilightColorMenu.setDefault(QColor.yellow);
\r
523 >>>>>>> 14a0afe3faba057afbddf62aa8ed25139750d68b
524 buttonLayout.toggleFontHilight.triggered.connect(this, "toggleFontHilightVisible(Boolean)");
\r
526 // buttonLayout.addWidget(new QLabel(), 1);
\r
527 v.addWidget(browser, 1);
\r
530 browser.downloadAttachmentRequested.connect(this,
\r
531 "downloadAttachment(QNetworkRequest)");
\r
532 browser.downloadImageRequested.connect(this,
\r
533 "downloadImage(QNetworkRequest)");
\r
534 setTabOrder(notebookBox, tagEdit);
\r
535 setTabOrder(tagEdit, browser);
\r
537 focusNoteShortcut = new QShortcut(this);
\r
538 setupShortcut(focusNoteShortcut, "Focus_Note");
\r
539 focusNoteShortcut.activated.connect(this, "focusNote()");
\r
540 focusTitleShortcut = new QShortcut(this);
\r
541 setupShortcut(focusTitleShortcut, "Focus_Title");
\r
542 focusTitleShortcut.activated.connect(this, "focusTitle()");
\r
543 focusTagShortcut = new QShortcut(this);
\r
544 setupShortcut(focusTagShortcut, "Focus_Tag");
\r
545 focusTagShortcut.activated.connect(this, "focusTag()");
\r
546 focusAuthorShortcut = new QShortcut(this);
\r
547 setupShortcut(focusAuthorShortcut, "Focus_Author");
\r
548 focusAuthorShortcut.activated.connect(this, "focusAuthor()");
\r
549 focusUrlShortcut = new QShortcut(this);
\r
550 setupShortcut(focusUrlShortcut, "Focus_Url");
\r
551 focusUrlShortcut.activated.connect(this, "focusUrl()");
\r
553 browser.page().mainFrame().setTextSizeMultiplier(Global.getTextSizeMultiplier());
\r
554 browser.page().mainFrame().setZoomFactor(Global.getZoomFactor());
\r
556 previewPageList = new HashMap<String,Integer>();
\r
558 browser.page().microFocusChanged.connect(this, "microFocusChanged()");
\r
559 logger.log(logger.HIGH, "Browser setup complete");
\r
564 private void setupShortcut(QShortcut action, String text) {
\r
565 if (!Global.shortcutKeys.containsAction(text))
\r
567 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
\r
573 // Getter for the QWebView
\r
574 public QWebView getBrowser() {
\r
578 // Block signals while loading data or things are flagged as dirty by
\r
580 public void loadingData(boolean val) {
\r
581 logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val);
\r
582 notebookBox.blockSignals(val);
\r
583 browser.page().blockSignals(val);
\r
584 browser.page().mainFrame().blockSignals(val);
\r
585 titleLabel.blockSignals(val);
\r
586 alteredDate.blockSignals(val);
\r
587 alteredTime.blockSignals(val);
\r
588 createdTime.blockSignals(val);
\r
589 createdDate.blockSignals(val);
\r
590 subjectDate.blockSignals(val);
\r
591 subjectTime.blockSignals(val);
\r
592 urlText.blockSignals(val);
\r
593 authorText.blockSignals(val);
\r
595 exposeToJavascript();
\r
596 logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val);
\r
600 public void setReadOnly(boolean v) {
\r
602 titleLabel.setEnabled(!v);
\r
603 notebookBox.setEnabled(!v);
\r
604 tagEdit.setEnabled(!v);
\r
605 authorLabel.setEnabled(!v);
\r
606 geoBox.setEnabled(!v);
\r
607 urlText.setEnabled(!v);
\r
608 createdDate.setEnabled(!v);
\r
609 subjectDate.setEnabled(!v);
\r
610 alteredDate.setEnabled(!v);
\r
611 getBrowser().setEnabled(true);
\r
614 // expose this class to Javascript on the web page
\r
615 private void exposeToJavascript() {
\r
616 browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this);
\r
619 // Custom event queue
\r
621 public boolean event(QEvent e) {
\r
622 if (e.type().equals(QEvent.Type.FocusOut)) {
\r
623 logger.log(logger.EXTREME, "Focus lost");
\r
626 return super.event(e);
\r
629 // clear out browser
\r
630 public void clear() {
\r
631 logger.log(logger.EXTREME, "Entering BrowserWindow.clear()");
\r
633 browser.setContent(new QByteArray());
\r
634 tagEdit.setText("");
\r
635 tagEdit.tagCompleter.reset();
\r
636 urlLabel.setText(tr("Source URL:"));
\r
637 titleLabel.setText("");
\r
638 logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()");
\r
641 // get/set current note
\r
642 public void setNote(Note n) {
\r
646 saveNoteTitle = n.getTitle();
\r
650 public Note getNote() {
\r
651 return currentNote;
\r
654 // New Editor Button
\r
655 private QPushButton newEditorButton(String name, String toolTip) {
\r
656 QPushButton button = new QPushButton();
\r
657 QIcon icon = new QIcon(iconPath + name + ".gif");
\r
658 button.setIcon(icon);
\r
659 button.setToolTip(toolTip);
\r
660 button.clicked.connect(this, name + "Clicked()");
\r
663 // New Editor Button
\r
664 private QToolButton newToolButton(String name, String toolTip) {
\r
665 QToolButton button = new QToolButton();
\r
666 QIcon icon = new QIcon(iconPath + name + ".gif");
\r
667 button.setIcon(icon);
\r
668 button.setToolTip(toolTip);
\r
669 button.clicked.connect(this, name + "Clicked()");
\r
674 private QLabel newSeparator() {
\r
675 return new QLabel(" ");
\r
678 // Set the title in the window
\r
679 public void setTitle(String t) {
\r
680 titleLabel.setText(t);
\r
685 // Return the current text title
\r
686 public String getTitle() {
\r
687 return titleLabel.text();
\r
690 // Set the tag name string
\r
691 public void setTag(String t) {
\r
693 tagEdit.setText(t);
\r
694 tagEdit.tagCompleter.reset();
\r
697 // Set the source URL
\r
698 public void setUrl(String t) {
\r
699 urlLabel.setText(tr("Source URL:\t"));
\r
700 urlText.setText(t);
\r
703 // The user want's to launch a web browser on the source of the URL
\r
704 public void sourceUrlClicked() {
\r
705 // Make sure we have a valid URL
\r
706 if (urlText.text().trim().equals(""))
\r
709 String url = urlText.text();
\r
710 if (!url.toLowerCase().startsWith(tr("http://")))
\r
711 url = tr("http://") +url;
\r
713 if (!QDesktopServices.openUrl(new QUrl(url))) {
\r
714 logger.log(logger.LOW, "Error opening file :" +url);
\r
718 public void setAuthor(String t) {
\r
719 authorLabel.setText(tr("Author:\t"));
\r
720 authorText.setText(t);
\r
723 // Set the creation date
\r
724 public void setCreation(long date) {
\r
725 QDateTime dt = new QDateTime();
\r
726 dt.setTime_t((int) (date / 1000));
\r
727 createdDate.setDateTime(dt);
\r
728 createdTime.setDateTime(dt);
\r
729 createdDate.setDisplayFormat(Global.getDateFormat());
\r
730 createdTime.setDisplayFormat(Global.getTimeFormat());
\r
733 // Set the creation date
\r
734 public void setAltered(long date) {
\r
735 QDateTime dt = new QDateTime();
\r
736 dt.setTime_t((int) (date / 1000));
\r
737 alteredDate.setDateTime(dt);
\r
738 alteredTime.setDateTime(dt);
\r
739 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
740 alteredTime.setDisplayFormat(Global.getTimeFormat());
\r
743 // Set the subject date
\r
744 public void setSubjectDate(long date) {
\r
745 QDateTime dt = new QDateTime();
\r
746 dt.setTime_t((int) (date / 1000));
\r
747 subjectDate.setDateTime(dt);
\r
748 subjectTime.setDateTime(dt);
\r
749 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
750 subjectTime.setDisplayFormat(Global.getTimeFormat());
\r
753 // Toggle the extended attribute information
\r
754 public void toggleInformation() {
\r
756 extendedOn = false;
\r
760 urlLabel.setVisible(extendedOn);
\r
761 urlText.setVisible(extendedOn);
\r
762 authorText.setVisible(extendedOn);
\r
763 geoBox.setVisible(extendedOn);
\r
764 authorLabel.setVisible(extendedOn);
\r
765 createdDate.setVisible(extendedOn);
\r
766 createdTime.setVisible(extendedOn);
\r
767 createdLabel.setVisible(extendedOn);
\r
768 alteredLabel.setVisible(extendedOn);
\r
769 alteredDate.setVisible(extendedOn);
\r
770 alteredTime.setVisible(extendedOn);
\r
771 //notebookBox.setVisible(extendedOn);
\r
772 notebookLabel.setVisible(extendedOn);
\r
773 subjectLabel.setVisible(extendedOn);
\r
774 subjectDate.setVisible(extendedOn);
\r
775 subjectTime.setVisible(extendedOn);
\r
778 public void hideButtons() {
\r
780 undoButton.parentWidget().setVisible(false);
\r
781 buttonsVisible = false;
\r
785 // Is the extended view on?
\r
786 public boolean isExtended() {
\r
790 // Listener for when a link is clicked
\r
791 @SuppressWarnings("unused")
\r
792 private void openFile() {
\r
793 logger.log(logger.EXTREME, "Starting openFile()");
\r
794 File fileHandle = new File(selectedFile);
\r
795 URI fileURL = fileHandle.toURI();
\r
796 String localURL = fileURL.toString();
\r
797 QUrl url = new QUrl(localURL);
\r
798 QFile file = new QFile(selectedFile);
\r
800 logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName());
\r
801 fileWatcher.addPath(file.fileName());
\r
803 if (!QDesktopServices.openUrl(url)) {
\r
804 logger.log(logger.LOW, "Error opening file :" +url);
\r
809 // Listener for when a link is clicked
\r
810 @SuppressWarnings("unused")
\r
811 private void linkClicked(QUrl url) {
\r
812 logger.log(logger.EXTREME, "URL Clicked: " +url.toString());
\r
813 if (url.toString().substring(0,8).equals("nnres://")) {
\r
814 logger.log(logger.EXTREME, "URL is NN resource");
\r
815 if (url.toString().endsWith("/vnd.evernote.ink")) {
\r
816 logger.log(logger.EXTREME, "Unable to open ink note");
\r
817 QMessageBox.information(this, tr("Unable Open"), tr("This is an ink note.\n"+
\r
818 "Ink notes are not supported since Evernote has not\n published any specifications on them\n" +
\r
819 "and I'm too lazy to figure them out by myself."));
\r
822 String fullName = url.toString().substring(8);
\r
823 int index = fullName.indexOf(".");
\r
827 type = fullName.substring(index+1);
\r
828 guid = fullName.substring(0,index);
\r
830 index = guid.indexOf(Global.attachmentNameDelimeter);
\r
832 guid = guid.substring(0,index);
\r
834 List<Resource> resList = currentNote.getResources();
\r
835 Resource res = null;
\r
836 for (int i=0; i<resList.size(); i++) {
\r
837 if (resList.get(i).getGuid().equals(guid)) {
\r
838 res = resList.get(i);
\r
843 String resGuid = Global.resourceMap.get(guid);
\r
844 if (resGuid != null)
\r
845 res = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, true);
\r
849 if (res.getAttributes() != null &&
\r
850 res.getAttributes().getFileName() != null &&
\r
851 !res.getAttributes().getFileName().trim().equals(""))
\r
852 fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();
\r
854 fileName = res.getGuid()+"."+type;
\r
855 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
856 QFile.OpenMode mode = new QFile.OpenMode();
\r
857 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
858 boolean openResult = file.open(mode);
\r
859 logger.log(logger.EXTREME, "File opened:" +openResult);
\r
860 QDataStream out = new QDataStream(file);
\r
861 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);
\r
862 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
864 logger.log(logger.EXTREME, "Writing resource");
\r
865 out.writeBytes(binData.toByteArray());
\r
868 String whichOS = System.getProperty("os.name");
\r
869 if (whichOS.contains("Windows"))
\r
870 url.setUrl("file:///"+file.fileName());
\r
872 url.setUrl("file://"+file.fileName());
\r
873 // fileWatcher.removePath(file.fileName());
\r
874 logger.log(logger.EXTREME, "Adding file watcher " +file.fileName());
\r
875 fileWatcher.addPath(file.fileName());
\r
877 // If we can't open it, then prompt the user to save it.
\r
878 if (!QDesktopServices.openUrl(url)) {
\r
879 logger.log(logger.EXTREME, "We can't handle this. Where do we put it?");
\r
880 QFileDialog dialog = new QFileDialog();
\r
882 if (dialog.exec()!=0) {
\r
883 List<String> fileNames = dialog.selectedFiles(); //gets all selected filenames
\r
884 if (fileNames.size() == 0)
\r
886 String sf = fileNames.get(0);
\r
887 QFile saveFile = new QFile(sf);
\r
888 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
889 saveFile.open(mode);
\r
890 QDataStream saveOut = new QDataStream(saveFile);
\r
891 saveOut.writeBytes(binData.toByteArray());
\r
899 logger.log(logger.EXTREME, "Launching URL");
\r
900 QDesktopServices.openUrl(url);
\r
903 // Listener for when BOLD is clicked
\r
904 @SuppressWarnings("unused")
\r
905 private void undoClicked() {
\r
906 browser.page().triggerAction(WebAction.Undo);
\r
907 browser.setFocus();
\r
910 // Listener for when BOLD is clicked
\r
911 @SuppressWarnings("unused")
\r
912 private void redoClicked() {
\r
913 browser.page().triggerAction(WebAction.Redo);
\r
914 browser.setFocus();
\r
917 // Listener for when BOLD is clicked
\r
918 @SuppressWarnings("unused")
\r
919 private void boldClicked() {
\r
920 browser.page().triggerAction(WebAction.ToggleBold);
\r
921 microFocusChanged();
\r
922 browser.setFocus();
\r
925 // Listener for when Italics is clicked
\r
926 @SuppressWarnings("unused")
\r
927 private void italicClicked() {
\r
928 browser.page().triggerAction(WebAction.ToggleItalic);
\r
929 microFocusChanged();
\r
930 browser.setFocus();
\r
933 // Listener for when UNDERLINE is clicked
\r
934 @SuppressWarnings("unused")
\r
935 private void underlineClicked() {
\r
936 browser.page().triggerAction(WebAction.ToggleUnderline);
\r
937 microFocusChanged();
\r
938 browser.setFocus();
\r
941 // Listener for when Strikethrough is clicked
\r
942 @SuppressWarnings("unused")
\r
943 private void strikethroughClicked() {
\r
944 browser.page().mainFrame().evaluateJavaScript(
\r
945 "document.execCommand('strikeThrough', false, '');");
\r
946 browser.setFocus();
\r
949 // Listener for when cut is clicked
\r
950 @SuppressWarnings("unused")
\r
951 private void cutClicked() {
\r
952 browser.page().triggerAction(WebAction.Cut);
\r
953 browser.setFocus();
\r
956 // Listener when COPY is clicked
\r
957 @SuppressWarnings("unused")
\r
958 private void copyClicked() {
\r
959 browser.page().triggerAction(WebAction.Copy);
\r
960 browser.setFocus();
\r
963 // Listener when PASTE is clicked
\r
964 public void pasteClicked() {
\r
965 logger.log(logger.EXTREME, "Paste Clicked");
\r
966 if (forceTextPaste) {
\r
967 pasteWithoutFormattingClicked();
\r
970 QClipboard clipboard = QApplication.clipboard();
\r
971 QMimeData mime = clipboard.mimeData();
\r
973 // String x = mime.html();
\r
975 if (mime.hasImage()) {
\r
976 logger.log(logger.EXTREME, "Image paste found");
\r
978 browser.setFocus();
\r
982 if (mime.hasUrls()) {
\r
983 logger.log(logger.EXTREME, "URL paste found");
\r
985 browser.setFocus();
\r
989 String text = mime.html();
\r
990 if (text.contains("en-tag") && mime.hasHtml()) {
\r
991 logger.log(logger.EXTREME, "Intra-note paste found");
\r
992 text = fixInternotePaste(text);
\r
993 mime.setHtml(text);
\r
994 clipboard.setMimeData(mime);
\r
997 logger.log(logger.EXTREME, "Final paste choice encountered");
\r
998 browser.page().triggerAction(WebAction.Paste);
\r
999 browser.setFocus();
\r
1003 // Paste text without formatting
\r
1004 private void pasteWithoutFormattingClicked() {
\r
1005 logger.log(logger.EXTREME, "Paste without format clipped");
\r
1006 QClipboard clipboard = QApplication.clipboard();
\r
1007 QMimeData mime = clipboard.mimeData();
\r
1008 if (!mime.hasText())
\r
1010 String text = mime.text();
\r
1011 clipboard.setText(text);
\r
1012 browser.page().triggerAction(WebAction.Paste);
\r
1013 QApplication.clipboard().setMimeData(mime);
\r
1014 browser.setFocus();
\r
1018 // insert date/time
\r
1019 @SuppressWarnings("unused")
\r
1020 private void insertDateTime() {
\r
1021 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
\r
1022 String dateTimeFormat = new String(fmt);
\r
1023 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
\r
1024 Calendar cal = Calendar.getInstance();
\r
1026 browser.page().mainFrame().evaluateJavaScript(
\r
1027 "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");
\r
1029 browser.setFocus();
\r
1033 // Listener when Left is clicked
\r
1034 @SuppressWarnings("unused")
\r
1035 private void justifyLeftClicked() {
\r
1036 browser.page().mainFrame().evaluateJavaScript(
\r
1037 "document.execCommand('JustifyLeft', false, '');");
\r
1038 browser.setFocus();
\r
1041 // Listener when Center is clicked
\r
1042 @SuppressWarnings("unused")
\r
1043 private void justifyCenterClicked() {
\r
1044 browser.page().mainFrame().evaluateJavaScript(
\r
1045 "document.execCommand('JustifyCenter', false, '');");
\r
1046 browser.setFocus();
\r
1049 // Listener when Left is clicked
\r
1050 @SuppressWarnings("unused")
\r
1051 private void justifyRightClicked() {
\r
1052 browser.page().mainFrame().evaluateJavaScript(
\r
1053 "document.execCommand('JustifyRight', false, '');");
\r
1054 browser.setFocus();
\r
1057 // Listener when HLINE is clicked
\r
1058 @SuppressWarnings("unused")
\r
1059 private void hlineClicked() {
\r
1060 browser.page().mainFrame().evaluateJavaScript(
\r
1061 "document.execCommand('insertHorizontalRule', false, '');");
\r
1062 browser.setFocus();
\r
1065 // Listener when outdent is clicked
\r
1066 private void outdentClicked() {
\r
1067 browser.page().mainFrame().evaluateJavaScript(
\r
1068 "document.execCommand('outdent', false, '');");
\r
1069 browser.setFocus();
\r
1072 // Listener when a bullet list is clicked
\r
1073 @SuppressWarnings("unused")
\r
1074 private void bulletListClicked() {
\r
1075 browser.page().mainFrame().evaluateJavaScript(
\r
1076 "document.execCommand('InsertUnorderedList', false, '');");
\r
1077 browser.setFocus();
\r
1080 // Listener when a bullet list is clicked
\r
1081 @SuppressWarnings("unused")
\r
1082 private void numberListClicked() {
\r
1083 browser.page().mainFrame().evaluateJavaScript(
\r
1084 "document.execCommand('InsertOrderedList', false, '');");
\r
1085 browser.setFocus();
\r
1088 // Listener when indent is clicked
\r
1089 private void indentClicked() {
\r
1090 browser.page().mainFrame().evaluateJavaScript(
\r
1091 "document.execCommand('indent', false, '');");
\r
1092 browser.setFocus();
\r
1095 // Listener when the font name is changed
\r
1096 @SuppressWarnings("unused")
\r
1097 private void fontChanged(String font) {
\r
1098 browser.page().mainFrame().evaluateJavaScript(
\r
1099 "document.execCommand('fontName',false,'" + font + "');");
\r
1100 browser.setFocus();
\r
1103 // Listener when a font size is changed
\r
1104 @SuppressWarnings("unused")
\r
1105 private void fontSizeChanged(String font) {
\r
1106 String text = browser.selectedText();
\r
1107 if (text.trim().equalsIgnoreCase(""))
\r
1110 String selectedText = browser.selectedText();
\r
1111 String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";
\r
1112 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1113 browser.page().mainFrame().evaluateJavaScript(script);
\r
1114 /* browser.page().mainFrame().evaluateJavaScript(
\r
1115 "document.execCommand('fontSize',false,'"
\r
1118 browser.setFocus();
\r
1121 // Load the font combo box based upon the font selected
\r
1122 private void loadFontSize(String name) {
\r
1123 QFontDatabase db = new QFontDatabase();
\r
1125 List<Integer> points = db.pointSizes(name);
\r
1126 for (int i=0; i<points.size(); i++) {
\r
1127 fontSize.addItem(points.get(i).toString());
\r
1130 fontSize.addItem("x-small");
\r
1131 fontSize.addItem("small");
\r
1132 fontSize.addItem("medium");
\r
1133 fontSize.addItem("large");
\r
1134 fontSize.addItem("x-large");
\r
1135 fontSize.addItem("xx-large");
\r
1136 fontSize.addItem("xxx-large");
\r
1140 // Listener when a font size is changed
\r
1141 @SuppressWarnings("unused")
\r
1142 private void fontColorClicked() {
\r
1143 // QColorDialog dialog = new QColorDialog();
\r
1144 // QColor color = QColorDialog.getColor();
\r
1145 QColor color = fontColorMenu.getColor();
\r
1146 if (color.isValid())
\r
1147 browser.page().mainFrame().evaluateJavaScript(
\r
1148 "document.execCommand('foreColor',false,'" + color.name()
\r
1150 browser.setFocus();
\r
1153 // Listener for when a background color change is requested
\r
1154 @SuppressWarnings("unused")
\r
1155 private void fontHilightClicked() {
\r
1156 // QColorDialog dialog = new QColorDialog();
\r
1157 // QColor color = QColorDialog.getColor();
\r
1158 QColor color = fontHilightColorMenu.getColor();
\r
1159 if (color.isValid())
\r
1160 browser.page().mainFrame().evaluateJavaScript(
\r
1161 "document.execCommand('backColor',false,'" + color.name()
\r
1163 browser.setFocus();
\r
1166 // Listener for when a background color change is requested
\r
1167 @SuppressWarnings("unused")
\r
1168 private void superscriptClicked() {
\r
1169 browser.page().mainFrame().evaluateJavaScript(
\r
1170 "document.execCommand('superscript');");
\r
1171 browser.setFocus();
\r
1174 // Listener for when a background color change is requested
\r
1175 @SuppressWarnings("unused")
\r
1176 private void subscriptClicked() {
\r
1177 browser.page().mainFrame().evaluateJavaScript(
\r
1178 "document.execCommand('subscript');");
\r
1179 browser.setFocus();
\r
1181 // Insert a to-do checkbox
\r
1182 @SuppressWarnings("unused")
\r
1183 private void todoClicked() {
\r
1184 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1185 String script_start = new String(
\r
1186 "document.execCommand('insertHtml', false, '");
\r
1187 String script_end = new String("');");
\r
1188 String todo = new String(
\r
1189 "<input TYPE=\"CHECKBOX\" value=\"false\" onClick=\"value=checked; window.jambi.contentChanged(); \" />");
\r
1190 browser.page().mainFrame().evaluateJavaScript(
\r
1191 script_start + todo + script_end);
\r
1192 browser.setFocus();
\r
1195 // Encrypt the selected text
\r
1196 @SuppressWarnings("unused")
\r
1197 private void encryptText() {
\r
1198 String text = browser.selectedText();
\r
1199 if (text.trim().equalsIgnoreCase(""))
\r
1202 EnCryptDialog dialog = new EnCryptDialog();
\r
1204 if (!dialog.okPressed()) {
\r
1208 EnCrypt crypt = new EnCrypt();
\r
1209 String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);
\r
1211 if (encrypted.trim().equals("")) {
\r
1212 QMessageBox.information(this, tr("Error"), tr("Error Encrypting String"));
\r
1215 StringBuffer buffer = new StringBuffer(encrypted.length() + 100);
\r
1216 buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""
\r
1217 + dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");
\r
1218 buffer.append("contentEditable=\"false\" alt=\"");
\r
1219 buffer.append(encrypted);
\r
1220 // NFC FIXME: should this be a file URL like in handleLocalAttachment and importAttachment?
\r
1221 buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png") +"\""));
\r
1222 Global.cryptCounter++;
\r
1223 buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");
\r
1224 buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");
\r
1225 buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString()
\r
1226 +"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&apos;")+"\\');\"");
\r
1227 buffer.append("style=\"display:block\" />");
\r
1229 String script_start = new String(
\r
1230 "document.execCommand('insertHtml', false, '");
\r
1231 String script_end = new String("');");
\r
1232 browser.page().mainFrame().evaluateJavaScript(
\r
1233 script_start + buffer.toString() + script_end);
\r
1237 // Insert a hyperlink
\r
1238 public void insertLink() {
\r
1239 logger.log(logger.EXTREME, "Inserting link");
\r
1240 String text = browser.selectedText();
\r
1241 if (text.trim().equalsIgnoreCase(""))
\r
1244 InsertLinkDialog dialog = new InsertLinkDialog();
\r
1245 if (currentHyperlink != null && currentHyperlink != "") {
\r
1246 dialog.setUrl(currentHyperlink);
\r
1249 if (!dialog.okPressed()) {
\r
1250 logger.log(logger.EXTREME, "Insert link canceled");
\r
1253 if (browser.insertLinkAction.text().equalsIgnoreCase("Insert Hyperlink")) {
\r
1254 String selectedText = browser.selectedText();
\r
1255 logger.log(logger.EXTREME, "Inserting link on text "+selectedText);
\r
1256 logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim());
\r
1257 String url = "<a href=\"" +dialog.getUrl().trim()
\r
1258 +"\" title=" +dialog.getUrl().trim()
\r
1259 +" >"+selectedText +"</a>";
\r
1260 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1261 browser.page().mainFrame().evaluateJavaScript(script);
\r
1264 String js = new String( "function getCursorPos() {"
\r
1266 +"if (window.getSelection) {"
\r
1267 +" var selObj = window.getSelection();"
\r
1268 +" var selRange = selObj.getRangeAt(0);"
\r
1269 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1270 +" while(workingNode != null) { "
\r
1271 +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');"
\r
1272 +" workingNode = workingNode.parentNode;"
\r
1275 +"} getCursorPos();");
\r
1276 browser.page().mainFrame().evaluateJavaScript(js);
\r
1283 public void insertTable() {
\r
1284 TableDialog dialog = new TableDialog();
\r
1286 if (!dialog.okPressed()) {
\r
1290 int cols = dialog.getCols();
\r
1291 int rows = dialog.getRows();
\r
1292 int width = dialog.getWidth();
\r
1293 boolean percent = dialog.isPercent();
\r
1295 String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();
\r
1297 newHTML = newHTML +"%";
\r
1298 newHTML = newHTML + "\"><tbody>";
\r
1300 for (int i=0; i<rows; i++) {
\r
1301 newHTML = newHTML +"<tr>";
\r
1302 for (int j=0; j<cols; j++) {
\r
1303 newHTML = newHTML +"<td> </td>";
\r
1305 newHTML = newHTML +"</tr>";
\r
1307 newHTML = newHTML+"</tbody></table>";
\r
1309 String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";
\r
1310 browser.page().mainFrame().evaluateJavaScript(script);
\r
1314 // Text content changed
\r
1315 @SuppressWarnings("unused")
\r
1316 private void selectionChanged() {
\r
1317 browser.encryptAction.setEnabled(true);
\r
1318 browser.insertLinkAction.setEnabled(true);
\r
1319 String scriptStart = "var selection_text = (window.getSelection()).toString();"
\r
1320 + "var range = (window.getSelection()).getRangeAt(0);"
\r
1321 + "var parent_html = range.commonAncestorContainer.innerHTML;"
\r
1322 + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"
\r
1323 + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"
\r
1324 + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"
\r
1325 + "var start = parent_html.indexOf(first_text);"
\r
1326 + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"
\r
1327 + "var value = parent_html.substring(start,end);"
\r
1328 + "window.jambi.saveSelectedText(value);" ;
\r
1329 browser.page().mainFrame().evaluateJavaScript(scriptStart);
\r
1333 public void saveSelectedText(String text) {
\r
1334 boolean enabled = true;
\r
1335 if (text.trim().length() == 0)
\r
1337 if (text.indexOf("en-tag=\"en-crypt\"") >= 0)
\r
1339 if (text.indexOf("<img en-tag=\"en-media\"") >= 0)
\r
1341 if (text.indexOf("<a en-tag=\"en-media\"") >= 0)
\r
1343 if (text.indexOf("<input ") >= 0)
\r
1346 browser.encryptAction.setEnabled(enabled);
\r
1347 browser.insertLinkAction.setEnabled(enabled);
\r
1348 // selectedText = text;
\r
1351 // Decrypt clicked text
\r
1352 public void decryptText(String id, String text, String hint) {
\r
1353 EnCrypt crypt = new EnCrypt();
\r
1354 String plainText = null;
\r
1355 Calendar currentTime = new GregorianCalendar();
\r
1356 Long l = new Long(currentTime.getTimeInMillis());
\r
1357 String slot = new String(Long.toString(l));
\r
1359 // First, try to decrypt with any keys we already have
\r
1360 for (int i=0; i<Global.passwordRemember.size(); i++) {
\r
1361 plainText = crypt.decrypt(text, Global.passwordRemember.get(i), 64);
\r
1362 if (plainText != null) {
\r
1363 slot = new String(Long.toString(l));
\r
1364 Global.passwordSafe.put(slot, Global.passwordRemember.get(i));
\r
1365 removeEncryption(id, plainText, false, slot);
\r
1371 EnDecryptDialog dialog = new EnDecryptDialog();
\r
1372 dialog.setHint(hint);
\r
1373 while (plainText == null || !dialog.okPressed()) {
\r
1375 if (!dialog.okPressed()) {
\r
1378 plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);
\r
1379 if (plainText == null) {
\r
1380 QMessageBox.warning(this, "Incorrect Password", "The password entered is not correct");
\r
1383 Global.passwordSafe.put(slot, dialog.getPassword());
\r
1384 removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);
\r
1385 if (dialog.rememberPassword())
\r
1386 Global.passwordRemember.add(dialog.getPassword());
\r
1390 // Get the editor tag line
\r
1391 public TagLineEdit getTagLine() {
\r
1395 // Modify a note's tags
\r
1396 @SuppressWarnings("unused")
\r
1397 private void modifyTags() {
\r
1398 TagAssign tagWindow = new TagAssign(allTags, currentTags);
\r
1400 if (tagWindow.okClicked()) {
\r
1401 currentTags.clear();
\r
1402 StringBuffer tagDisplay = new StringBuffer();
\r
1404 List<QListWidgetItem> newTags = tagWindow.getTagList()
\r
1406 for (int i = 0; i < newTags.size(); i++) {
\r
1407 currentTags.add(newTags.get(i).text());
\r
1408 tagDisplay.append(newTags.get(i).text());
\r
1409 if (i < newTags.size() - 1) {
\r
1410 tagDisplay.append(Global.tagDelimeter + " ");
\r
1413 tagEdit.setText(tagDisplay.toString());
\r
1414 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1418 // Tag line has been modified by typing text
\r
1419 @SuppressWarnings("unused")
\r
1420 private void modifyTagsTyping() {
\r
1421 String completionText = "";
\r
1422 if (tagEdit.currentCompleterSelection != null && !tagEdit.currentCompleterSelection.equals("")) {
\r
1423 completionText = tagEdit.currentCompleterSelection;
\r
1424 tagEdit.currentCompleterSelection = "";
\r
1427 if (tagEdit.text().equalsIgnoreCase(saveTagList))
\r
1430 // We know something has changed...
\r
1431 String oldTagArray[] = saveTagList.split(Global.tagDelimeter);
\r
1432 String newTagArray[] = tagEdit.text().split(Global.tagDelimeter);
\r
1434 if (!completionText.equals("") && newTagArray.length > 0) {
\r
1435 newTagArray[newTagArray.length-1] = completionText;
\r
1437 // Remove any potential duplicates from the new list
\r
1438 for (int i=0; i<newTagArray.length; i++) {
\r
1439 boolean foundOnce = false;
\r
1440 for (int j=0; j<newTagArray.length; j++) {
\r
1441 if (newTagArray[j].equalsIgnoreCase(newTagArray[i])) {
\r
1445 newTagArray[j] = "";
\r
1450 List<String> newTagList = new ArrayList<String>();
\r
1451 List<String> oldTagList = new ArrayList<String>();
\r
1453 for (int i = 0; i < oldTagArray.length; i++)
\r
1454 if (!oldTagArray[i].trim().equals(""))
\r
1455 oldTagList.add(oldTagArray[i]);
\r
1456 for (int i = 0; i < newTagArray.length; i++)
\r
1457 if (!newTagArray[i].trim().equals(""))
\r
1458 newTagList.add(newTagArray[i]);
\r
1460 // Let's cleanup the appearance of the tag list
\r
1461 Collections.sort(newTagList);
\r
1462 String newDisplay = "";
\r
1463 for (int i=0; i<newTagList.size(); i++) {
\r
1464 newDisplay = newDisplay+newTagList.get(i);
\r
1465 if (i<newTagList.size()-1)
\r
1466 newDisplay = newDisplay+", ";
\r
1468 tagEdit.blockSignals(true);
\r
1469 tagEdit.setText(newDisplay);
\r
1470 tagEdit.blockSignals(false);
\r
1472 // We now have lists of the new & old. Remove duplicates. If all
\r
1473 // are removed from both then nothing has really changed
\r
1474 for (int i = newTagList.size() - 1; i >= 0; i--) {
\r
1475 String nTag = newTagList.get(i);
\r
1476 for (int j = oldTagList.size() - 1; j >= 0; j--) {
\r
1477 String oTag = oldTagList.get(j);
\r
1478 if (oTag.equalsIgnoreCase(nTag)) {
\r
1479 oldTagList.remove(j);
\r
1480 newTagList.remove(i);
\r
1486 if (oldTagList.size() != 0 || newTagList.size() != 0) {
\r
1487 currentTags.clear();
\r
1488 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1489 for (int i = 0; i < newTagArray.length; i++)
\r
1490 if (!newTagArray[i].trim().equals(""))
\r
1491 currentTags.add(newTagArray[i].trim());
\r
1493 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1498 // Tab button was pressed
\r
1499 public void tabPressed() {
\r
1500 if (!insideList) {
\r
1501 String script_start = new String(
\r
1502 "document.execCommand('insertHtml', false, ' ');");
\r
1503 browser.page().mainFrame().evaluateJavaScript(script_start);
\r
1508 public void backtabPressed() {
\r
1513 public void setInsideList() {
\r
1514 insideList = true;
\r
1517 // The title has been edited
\r
1518 @SuppressWarnings("unused")
\r
1519 private void titleEdited() {
\r
1520 // If we don't have a good note, or if the current title
\r
1521 // matches the old title then we don't need to do anything
\r
1522 if (currentNote == null)
\r
1524 if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))
\r
1527 // If we have a real change, we need to save it.
\r
1528 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text());
\r
1529 currentNote.setTitle(titleLabel.text());
\r
1530 saveNoteTitle = titleLabel.text();
\r
1534 // Set the list of note tags
\r
1535 public void setAllTags(List<Tag> l) {
\r
1537 tagEdit.setTagList(l);
\r
1540 // Setter for the current tags
\r
1541 public void setCurrentTags(List<String> s) {
\r
1545 // Save the list of notebooks
\r
1546 public void setNotebookList(List<Notebook> n) {
\r
1548 loadNotebookList();
\r
1551 // Load the notebook list and select the current notebook
\r
1552 private void loadNotebookList() {
\r
1553 if (notebookBox.count() != 0)
\r
1554 notebookBox.clear();
\r
1555 if (notebookList == null)
\r
1558 for (int i = 0; i < notebookList.size(); i++) {
\r
1559 notebookBox.addItem(notebookList.get(i).getName());
\r
1560 if (currentNote != null) {
\r
1561 if (currentNote.getNotebookGuid().equals(
\r
1562 notebookList.get(i).getGuid())) {
\r
1563 notebookBox.setCurrentIndex(i);
\r
1569 // Get the contents of the editor
\r
1570 public String getContent() {
\r
1571 return browser.page().currentFrame().toHtml();
\r
1574 // The note contents have changed
\r
1575 public void contentChanged() {
\r
1576 String content = getContent();
\r
1578 noteSignal.noteChanged.emit(currentNote.getGuid(), content);
\r
1581 // The notebook selection has changed
\r
1582 @SuppressWarnings("unused")
\r
1583 private void notebookChanged() {
\r
1584 boolean changed = false;
\r
1585 String n = notebookBox.currentText();
\r
1586 for (int i = 0; i < notebookList.size(); i++) {
\r
1587 if (n.equals(notebookList.get(i).getName())) {
\r
1588 if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {
\r
1589 currentNote.setNotebookGuid(notebookList.get(i).getGuid());
\r
1592 i = notebookList.size();
\r
1596 // If the notebook changed, signal the update
\r
1598 noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote
\r
1599 .getNotebookGuid());
\r
1602 // Check the note title
\r
1603 private void checkNoteTitle() {
\r
1604 String text = browser.page().currentFrame().toPlainText();
\r
1605 if (saveNoteTitle.trim().equals("")) {
\r
1606 int newLine = text.indexOf("\n");
\r
1607 if (newLine > 0) {
\r
1608 text = text.substring(0, newLine);
\r
1609 if (text.trim().equals(""))
\r
1610 text = tr("Untitled Note");
\r
1611 titleLabel.setText(text);
\r
1613 if (text.length() > 20)
\r
1614 titleLabel.setText(text.substring(0, 20));
\r
1616 if (text.trim().equals(""))
\r
1617 titleLabel.setText(tr("Untitled Note"));
\r
1619 titleLabel.setText(text);
\r
1622 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel
\r
1627 // Return the note contents so we can email them
\r
1628 public String getContentsToEmail() {
\r
1629 return browser.page().currentFrame().toPlainText().trim();
\r
1631 * int body = browser.page().currentFrame().toHtml().indexOf("<body>");
\r
1632 * String temp = browser.page().currentFrame().toHtml(); if (body == -1)
\r
1633 * temp = "<html><body><b>Test</b></body></html>"; else temp =
\r
1634 * "<html>"+temp.substring(body); return temp; // return
\r
1635 * urlEncode(browser.page().currentFrame().toHtml());
\r
1639 // Insert an image into the editor
\r
1640 private void insertImage(QMimeData mime) {
\r
1641 logger.log(logger.EXTREME, "Entering insertImage");
\r
1642 QImage img = (QImage) mime.imageData();
\r
1643 String script_start = new String(
\r
1644 "document.execCommand('insertHTML', false, '");
\r
1645 String script_end = new String("');");
\r
1647 long now = new Date().getTime();
\r
1648 String path = Global.getFileManager().getResDirPath(
\r
1649 (new Long(now).toString()) + ".jpg");
\r
1651 // This block is just a hack to make sure we wait at least 1ms so we
\r
1653 // have collisions on image names
\r
1654 long i = new Date().getTime();
\r
1656 i = new Date().getTime();
\r
1658 // Open the file & write the data
\r
1659 QFile tfile = new QFile(path);
\r
1660 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1664 Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);
\r
1665 if (newRes == null)
\r
1667 currentNote.getResources().add(newRes);
\r
1669 // do the actual insert into the note
\r
1670 StringBuffer buffer = new StringBuffer(100);
\r
1671 buffer.append("<img src=\"");
\r
1672 buffer.append(tfile.fileName());
\r
1673 buffer.append("\" en-tag=en-media type=\"image/jpeg\""
\r
1674 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1675 +" guid=\"" +newRes.getGuid() +"\""
\r
1676 // +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1677 +" onContextMenu=\"window.jambi.imageContextMenu(&." +tfile.fileName() +"&.);\""
\r
1680 browser.page().mainFrame().evaluateJavaScript(
\r
1681 script_start + buffer + script_end);
\r
1686 // Handle URLs that are trying to be pasted
\r
1687 public void handleUrls(QMimeData mime) {
\r
1688 logger.log(logger.EXTREME, "Starting handleUrls");
\r
1689 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1691 List<QUrl> urlList = mime.urls();
\r
1692 String url = new String();
\r
1693 String script_start = new String(
\r
1694 "document.execCommand('createLink', false, '");
\r
1695 String script_end = new String("');");
\r
1697 for (int i = 0; i < urlList.size(); i++) {
\r
1698 url = urlList.get(i).toString();
\r
1699 // Find out what type of file we have
\r
1700 String mimeType = fileNameMap.getContentTypeFor(url);
\r
1702 // If null returned, we need to guess at the file type
\r
1703 if (mimeType == null)
\r
1704 mimeType = "application/"
\r
1705 + url.substring(url.lastIndexOf(".") + 1);
\r
1707 // Check if we have an image or some other type of file
\r
1708 if (url.substring(0, 5).equalsIgnoreCase("file:")
\r
1709 && mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1710 handleLocalImageURLPaste(mime, mimeType);
\r
1713 String[] type = mimeType.split("/");
\r
1714 boolean valid = validAttachment(type[1]);
\r
1715 boolean smallEnough = checkFileAttachmentSize(url);
\r
1716 if (smallEnough && valid
\r
1717 && url.substring(0, 5).equalsIgnoreCase("file:")
\r
1718 && !mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1719 handleLocalAttachment(mime, mimeType);
\r
1722 browser.page().mainFrame().evaluateJavaScript(
\r
1723 script_start + url + script_end);
\r
1728 // If a URL being pasted is an image URL, then attach the image
\r
1729 private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {
\r
1730 List<QUrl> urlList = mime.urls();
\r
1731 String url = new String();
\r
1732 String script_start_image = new String(
\r
1733 "document.execCommand('insertHtml', false, '");
\r
1734 String script_end = new String("');");
\r
1735 StringBuffer buffer;
\r
1737 // Copy the image over into the resource directory and create a new resource
\r
1738 // record for each url pasted
\r
1739 for (int i = 0; i < urlList.size(); i++) {
\r
1740 url = urlList.get(i).toString();
\r
1742 Resource newRes = createResource(url, i, mimeType, false);
\r
1743 if (newRes == null)
\r
1745 currentNote.getResources().add(newRes);
\r
1746 buffer = new StringBuffer(100);
\r
1748 // Open the file & write the data
\r
1749 String fileName = Global.getFileManager().getResDirPath(newRes.getGuid());
\r
1750 QFile tfile = new QFile(fileName);
\r
1751 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1752 tfile.write(newRes.getData().getBody());
\r
1754 buffer.append(script_start_image);
\r
1755 buffer.append("<img src=\"" + FileUtils.toForwardSlashedPath(fileName));
\r
1756 // if (mimeType.equalsIgnoreCase("image/jpg"))
\r
1757 // mimeType = "image/jpeg";
\r
1758 buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""
\r
1759 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1760 +" guid=\"" +newRes.getGuid() +"\""
\r
1761 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1763 buffer.append(script_end);
\r
1764 browser.page().mainFrame().evaluateJavaScript(buffer.toString());
\r
1770 // If a URL being pasted is a local file URL, then attach the file
\r
1771 private void handleLocalAttachment(QMimeData mime, String mimeType) {
\r
1772 logger.log(logger.EXTREME, "Attaching local file");
\r
1773 List<QUrl> urlList = mime.urls();
\r
1774 String script_start = new String(
\r
1775 "document.execCommand('insertHtml', false, '");
\r
1776 String script_end = new String("');");
\r
1777 StringBuffer buffer;
\r
1779 String[] type = mimeType.split("/");
\r
1780 String icon = findIcon(type[1]);
\r
1781 if (icon.equals("attachment.png"))
\r
1782 icon = findIcon(type[0]);
\r
1783 buffer = new StringBuffer(100);
\r
1785 for (int i = 0; i < urlList.size(); i++) {
\r
1786 String url = urlList.get(i).toString();
\r
1788 // Start building the HTML
\r
1789 if (icon.equals("attachment.png"))
\r
1790 icon = findIcon(url.substring(url.lastIndexOf(".")+1));
\r
1791 String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));
\r
1793 logger.log(logger.EXTREME, "Creating resource ");
\r
1794 Resource newRes = createResource(url, i, mimeType, true);
\r
1795 if (newRes == null)
\r
1797 logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());
\r
1798 currentNote.getResources().add(newRes);
\r
1800 String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();
\r
1801 // If we have a PDF, we need to setup the preview.
\r
1802 if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {
\r
1803 logger.log(logger.EXTREME, "Setting up PDF preview");
\r
1804 if (newRes.getAttributes() != null &&
\r
1805 newRes.getAttributes().getFileName() != null &&
\r
1806 !newRes.getAttributes().getFileName().trim().equals(""))
\r
1807 fileName = newRes.getGuid()+Global.attachmentNameDelimeter+
\r
1808 newRes.getAttributes().getFileName();
\r
1810 fileName = newRes.getGuid()+".pdf";
\r
1811 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
1812 QFile.OpenMode mode = new QFile.OpenMode();
\r
1813 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
1815 QDataStream out = new QDataStream(file);
\r
1816 // Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);
\r
1817 QByteArray binData = new QByteArray(newRes.getData().getBody());
\r
1818 // resBinary = null;
\r
1819 out.writeBytes(binData.toByteArray());
\r
1822 PDFPreview pdfPreview = new PDFPreview();
\r
1823 if (pdfPreview.setupPreview(Global.getFileManager().getResDirPath(fileName), "pdf",0)) {
\r
1824 // NFC TODO: should this be a 'file://' url like the ones above?
\r
1825 imageURL = file.fileName() + ".png";
\r
1829 logger.log(logger.EXTREME, "Generating link tags");
\r
1830 buffer.delete(0, buffer.length());
\r
1831 buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");
\r
1832 buffer.append(" onContextMenu=\"window.jambi.imageContextMenu('")
\r
1833 .append(Global.getFileManager().getResDirPath(fileName))
\r
1834 .append("');\" "); buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");
\r
1835 buffer.append("<img src=\"" + imageURL + "\" title=\"" +newRes.getAttributes().getFileName());
\r
1836 buffer.append("\"></img>");
\r
1837 buffer.append("</a>");
\r
1838 browser.page().mainFrame().evaluateJavaScript(
\r
1839 script_start + buffer.toString() + script_end);
\r
1844 private Resource createResource(String url, int sequence, String mime, boolean attachment) {
\r
1845 logger.log(logger.EXTREME, "Inside create resource");
\r
1846 QFile resourceFile;
\r
1847 String urlTest = new QUrl(url).toLocalFile();
\r
1848 if (!urlTest.equals(""))
\r
1850 url = url.replace("/", File.separator);
\r
1851 resourceFile = new QFile(url);
\r
1852 resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));
\r
1853 byte[] fileData = resourceFile.readAll().toByteArray();
\r
1854 resourceFile.close();
\r
1855 if (fileData.length == 0)
\r
1859 md = MessageDigest.getInstance("MD5");
\r
1860 md.update(fileData);
\r
1861 byte[] hash = md.digest();
\r
1863 Resource r = new Resource();
\r
1864 Calendar time = new GregorianCalendar();
\r
1865 long prevTime = time.getTimeInMillis();
\r
1866 while (prevTime == time.getTimeInMillis()) {
\r
1867 time = new GregorianCalendar();
\r
1869 r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());
\r
1870 r.setNoteGuid(currentNote.getGuid());
\r
1872 r.setActive(true);
\r
1873 r.setUpdateSequenceNum(0);
\r
1874 r.setWidth((short) 0);
\r
1875 r.setHeight((short) 0);
\r
1876 r.setDuration((short) 0);
\r
1878 Data d = new Data();
\r
1879 d.setBody(fileData);
\r
1880 d.setBodyIsSet(true);
\r
1881 d.setBodyHash(hash);
\r
1882 d.setBodyHashIsSet(true);
\r
1884 d.setSize(fileData.length);
\r
1886 int fileNamePos = url.lastIndexOf(File.separator);
\r
1887 if (fileNamePos == -1)
\r
1888 fileNamePos = url.lastIndexOf("/");
\r
1889 String fileName = url.substring(fileNamePos+1);
\r
1890 ResourceAttributes a = new ResourceAttributes();
\r
1892 a.setAltitudeIsSet(false);
\r
1893 a.setLongitude(0);
\r
1894 a.setLongitudeIsSet(false);
\r
1896 a.setLatitudeIsSet(false);
\r
1897 a.setCameraMake("");
\r
1898 a.setCameraMakeIsSet(false);
\r
1899 a.setCameraModel("");
\r
1900 a.setCameraModelIsSet(false);
\r
1901 a.setAttachment(attachment);
\r
1902 a.setAttachmentIsSet(true);
\r
1903 a.setClientWillIndex(false);
\r
1904 a.setClientWillIndexIsSet(true);
\r
1905 a.setRecoType("");
\r
1906 a.setRecoTypeIsSet(false);
\r
1907 a.setSourceURL(url);
\r
1908 a.setSourceURLIsSet(true);
\r
1909 a.setTimestamp(0);
\r
1910 a.setTimestampIsSet(false);
\r
1911 a.setFileName(fileName);
\r
1912 a.setFileNameIsSet(true);
\r
1913 r.setAttributes(a);
\r
1915 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
1917 } catch (NoSuchAlgorithmException e1) {
\r
1918 e1.printStackTrace();
\r
1924 // find the appropriate icon for an attachment
\r
1925 private String findIcon(String appl) {
\r
1926 appl = appl.toLowerCase();
\r
1927 File f = Global.getFileManager().getImageDirFile(appl + ".png");
\r
1929 return appl+".png";
\r
1930 return "attachment.png";
\r
1933 // Check if the account supports this type of attachment
\r
1934 private boolean validAttachment(String type) {
\r
1935 if (Global.isPremium())
\r
1937 if (type.equalsIgnoreCase("JPG"))
\r
1939 if (type.equalsIgnoreCase("PNG"))
\r
1941 if (type.equalsIgnoreCase("GIF"))
\r
1943 if (type.equalsIgnoreCase("MP3"))
\r
1945 if (type.equalsIgnoreCase("WAV"))
\r
1947 if (type.equalsIgnoreCase("AMR"))
\r
1949 if (type.equalsIgnoreCase("PDF"))
\r
1951 String error = tr("Non-premium accounts can only attach JPG, PNG, GIF, MP3, WAV, AMR, or PDF files.");
\r
1952 QMessageBox.information(this, tr("Non-Premium Account"), error);
\r
1957 // Check the file attachment to be sure it isn't over 25 mb
\r
1958 private boolean checkFileAttachmentSize(String url) {
\r
1959 String fileName = url.substring(8);
\r
1960 QFile resourceFile = new QFile(fileName);
\r
1961 resourceFile.open(new QIODevice.OpenMode(
\r
1962 QIODevice.OpenModeFlag.ReadOnly));
\r
1963 long size = resourceFile.size();
\r
1964 resourceFile.close();
\r
1965 size = size / 1024 / 1024;
\r
1966 if (size < 50 && Global.isPremium())
\r
1971 String error = tr("A file attachment may not exceed 25MB.");
\r
1972 QMessageBox.information(this, tr("Attachment Size"), error);
\r
1977 @SuppressWarnings("unused")
\r
1978 private void createdChanged() {
\r
1979 QDateTime dt = new QDateTime();
\r
1980 dt.setDate(createdDate.date());
\r
1981 dt.setTime(createdTime.time());
\r
1982 noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);
\r
1986 @SuppressWarnings("unused")
\r
1987 private void alteredChanged() {
\r
1988 QDateTime dt = new QDateTime();
\r
1989 dt.setDate(alteredDate.date());
\r
1990 dt.setTime(alteredTime.time());
\r
1991 noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);
\r
1994 @SuppressWarnings("unused")
\r
1995 private void subjectDateTimeChanged() {
\r
1996 QDateTime dt = new QDateTime();
\r
1997 dt.setDate(subjectDate.date());
\r
1998 dt.setTime(subjectTime.time());
\r
1999 noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);
\r
2003 @SuppressWarnings("unused")
\r
2004 private void sourceUrlChanged() {
\r
2005 noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());
\r
2008 @SuppressWarnings("unused")
\r
2009 private void authorChanged() {
\r
2010 noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());
\r
2013 @SuppressWarnings("unused")
\r
2014 private void geoBoxChanged() {
\r
2015 int index = geoBox.currentIndex();
\r
2016 geoBox.setCurrentIndex(0);
\r
2018 GeoDialog box = new GeoDialog();
\r
2019 box.setLongitude(currentNote.getAttributes().getLongitude());
\r
2020 box.setLatitude(currentNote.getAttributes().getLatitude());
\r
2021 box.setAltitude(currentNote.getAttributes().getAltitude());
\r
2023 if (!box.okPressed())
\r
2025 double alt = box.getAltitude();
\r
2026 double lat = box.getLatitude();
\r
2027 double lon = box.getLongitude();
\r
2028 if (alt != currentNote.getAttributes().getAltitude() ||
\r
2029 lon != currentNote.getAttributes().getLongitude() ||
\r
2030 lat != currentNote.getAttributes().getLatitude()) {
\r
2031 noteSignal.geoChanged.emit(currentNote.getGuid(), lon, lat, alt);
\r
2032 currentNote.getAttributes().setAltitude(alt);
\r
2033 currentNote.getAttributes().setLongitude(lon);
\r
2034 currentNote.getAttributes().setLatitude(lat);
\r
2039 noteSignal.geoChanged.emit(currentNote.getGuid(), 0.0, 0.0, 0.0);
\r
2040 currentNote.getAttributes().setAltitude(0.0);
\r
2041 currentNote.getAttributes().setLongitude(0.0);
\r
2042 currentNote.getAttributes().setLatitude(0.0);
\r
2045 if (index == 3 || index == 0) {
\r
2046 QDesktopServices.openUrl(new QUrl("http://maps.google.com/maps?z=6&q="+currentNote.getAttributes().getLatitude() +"," +currentNote.getAttributes().getLongitude()));
\r
2050 // ************************************************************
\r
2051 // * User chose to save an attachment. Pares out the request *
\r
2052 // * into a guid & file. Save the result. *
\r
2053 // ************************************************************
\r
2054 public void downloadAttachment(QNetworkRequest request) {
\r
2056 QFileDialog fd = new QFileDialog(this);
\r
2057 fd.setFileMode(FileMode.AnyFile);
\r
2058 fd.setConfirmOverwrite(true);
\r
2059 fd.setWindowTitle(tr("Save File"));
\r
2060 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2061 fd.setDirectory(System.getProperty("user.home"));
\r
2062 String name = request.url().toString();
\r
2064 int pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2066 guid = name.substring(0, pos).replace("nnres://", "");
\r
2067 name = name.substring(pos +Global.attachmentNameDelimeter.length());
\r
2068 fd.selectFile(name);
\r
2069 pos = name.lastIndexOf('.');
\r
2071 String mimeType = "(*." + name.substring(pos + 1)
\r
2072 + ");; All Files (*)";
\r
2073 fd.setFilter(tr(mimeType));
\r
2079 // Strip URL prefix and base dir
\r
2080 guid = guid.replace("nnres://", "")
\r
2081 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2083 pos = guid.lastIndexOf('.');
\r
2085 guid = guid.substring(0,pos);
\r
2086 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2087 name = name.replace('\\', '/');
\r
2088 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2089 QFile saveFile = new QFile(fd.selectedFiles().get(0));
\r
2090 QFile.OpenMode mode = new QFile.OpenMode();
\r
2091 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2092 saveFile.open(mode);
\r
2093 QDataStream saveOut = new QDataStream(saveFile);
\r
2094 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2095 saveOut.writeBytes(binData.toByteArray());
\r
2102 // ************************************************************
\r
2103 // * User chose to save an attachment. Pares out the request *
\r
2104 // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!
\r
2105 // ************************************************************
\r
2106 // NFC TODO: unused? remove
\r
2107 public void downloadImage(QNetworkRequest request) {
\r
2108 QFileDialog fd = new QFileDialog(this);
\r
2109 fd.setFileMode(FileMode.AnyFile);
\r
2110 fd.setConfirmOverwrite(true);
\r
2111 fd.setWindowTitle(tr("Save File"));
\r
2112 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2113 fd.setDirectory(System.getProperty("user.home"));
\r
2114 String name = request.url().toString();
\r
2115 name = name.replace("nnres://", "");
\r
2116 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
\r
2117 name = name.replace(dPath, "");
\r
2118 int pos = name.lastIndexOf('.');
\r
2119 String guid = name;
\r
2121 String mimeType = "(*." + name.substring(pos + 1)
\r
2122 + ");; All Files (*)";
\r
2123 fd.setFilter(tr(mimeType));
\r
2124 guid = guid.substring(0,pos);
\r
2126 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2128 guid = name.substring(0, pos);
\r
2129 fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));
\r
2131 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2132 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2133 String fileName = fd.selectedFiles().get(0);
\r
2134 QFile saveFile = new QFile(fileName);
\r
2135 QFile.OpenMode mode = new QFile.OpenMode();
\r
2136 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2137 saveFile.open(mode);
\r
2138 QDataStream saveOut = new QDataStream(saveFile);
\r
2139 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2140 saveOut.writeBytes(binData.toByteArray());
\r
2146 // *************************************************************
\r
2147 // * decrypt any hidden text. We could do an XML parse, but
\r
2148 // * it is quicker here just to scan for an <img tag & do the fix
\r
2149 // * the manual way
\r
2150 // *************************************************************
\r
2151 private void removeEncryption(String id, String plainText, boolean permanent, String slot) {
\r
2153 plainText = " <en-crypt-temp slot=\""+slot +"\">" +plainText+"</en-crypt-temp> ";
\r
2156 String html = browser.page().mainFrame().toHtml();
\r
2157 String text = html;
\r
2158 int imagePos = html.indexOf("<img");
\r
2160 for ( ;imagePos>0; ) {
\r
2161 // Find the end tag
\r
2162 endPos = text.indexOf(">", imagePos);
\r
2163 String tag = text.substring(imagePos-1,endPos);
\r
2164 if (tag.indexOf("id=\""+id+"\"") > -1) {
\r
2165 text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);
\r
2167 browser.setContent(new QByteArray(text));
\r
2170 imagePos = text.indexOf("<img", imagePos+1);
\r
2175 //****************************************************************
\r
2176 //* Focus shortcuts
\r
2177 //****************************************************************
\r
2178 @SuppressWarnings("unused")
\r
2179 private void focusTitle() {
\r
2180 titleLabel.setFocus();
\r
2182 @SuppressWarnings("unused")
\r
2183 private void focusTag() {
\r
2184 tagEdit.setFocus();
\r
2186 @SuppressWarnings("unused")
\r
2187 private void focusNote() {
\r
2188 browser.setFocus();
\r
2190 @SuppressWarnings("unused")
\r
2191 private void focusAuthor() {
\r
2192 authorLabel.setFocus();
\r
2194 @SuppressWarnings("unused")
\r
2195 private void focusUrl() {
\r
2196 urlLabel.setFocus();
\r
2200 //*****************************************************************
\r
2201 //* Set the document background color
\r
2202 //*****************************************************************
\r
2203 public void setBackgroundColor(String color) {
\r
2204 String js = "function changeBackground(color) {"
\r
2205 +"document.body.style.background = color;"
\r
2207 +"changeBackground('" +color+"');";
\r
2208 browser.page().mainFrame().evaluateJavaScript(js);
\r
2213 //****************************************************************
\r
2214 //* MicroFocus changed
\r
2215 //****************************************************************
\r
2216 private void microFocusChanged() {
\r
2217 boldButton.setDown(false);
\r
2218 italicButton.setDown(false);
\r
2219 underlineButton.setDown(false);
\r
2220 browser.openAction.setEnabled(false);
\r
2221 browser.downloadAttachment.setEnabled(false);
\r
2222 browser.downloadImage.setEnabled(false);
\r
2223 browser.rotateImageLeft.setEnabled(false);
\r
2224 browser.rotateImageRight.setEnabled(false);
\r
2225 browser.insertTableAction.setEnabled(true);
\r
2226 browser.insertTableRowAction.setEnabled(false);
\r
2227 browser.deleteTableRowAction.setEnabled(false);
\r
2228 browser.insertLinkAction.setText(tr("Insert Hyperlink"));
\r
2229 currentHyperlink ="";
\r
2230 insideList = false;
\r
2231 forceTextPaste = false;
\r
2233 String js = new String( "function getCursorPos() {"
\r
2235 +"if (window.getSelection) {"
\r
2236 +" var selObj = window.getSelection();"
\r
2237 +" var selRange = selObj.getRangeAt(0);"
\r
2238 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2239 +" while(workingNode != null) { "
\r
2240 // +" window.jambi.printNode(workingNode.nodeName);"
\r
2241 +" if (workingNode.nodeName=='EN-CRYPT-TEMP') window.jambi.forceTextPaste();"
\r
2242 +" if (workingNode.nodeName=='B') window.jambi.boldActive();"
\r
2243 +" if (workingNode.nodeName=='I') window.jambi.italicActive();"
\r
2244 +" if (workingNode.nodeName=='U') window.jambi.underlineActive();"
\r
2245 +" if (workingNode.nodeName=='UL') window.jambi.setInsideList();"
\r
2246 +" if (workingNode.nodeName=='OL') window.jambi.setInsideList();"
\r
2247 +" if (workingNode.nodeName=='LI') window.jambi.setInsideList();"
\r
2248 +" if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"
\r
2249 +" 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
2250 +" if (workingNode.nodeName=='SPAN') {"
\r
2251 +" if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"
\r
2253 +" workingNode = workingNode.parentNode;"
\r
2256 +"} getCursorPos();");
\r
2257 browser.page().mainFrame().evaluateJavaScript(js);
\r
2260 public void printNode(String n) {
\r
2261 System.out.println("Node Vaule: " +n);
\r
2265 //****************************************************************
\r
2266 //* Insert a table row
\r
2267 //****************************************************************
\r
2268 public void insertTableRow() {
\r
2270 String js = new String( "function insertTableRow() {"
\r
2271 +" var selObj = window.getSelection();"
\r
2272 +" var selRange = selObj.getRangeAt(0);"
\r
2273 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2274 +" var cellCount = 0;"
\r
2275 +" while(workingNode != null) { "
\r
2276 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2277 +" row = document.createElement('TR');"
\r
2278 +" var nodes = workingNode.getElementsByTagName('td');"
\r
2279 +" for (j=0; j<nodes.length; j=j+1) {"
\r
2280 +" cell = document.createElement('TD');"
\r
2281 +" cell.innerHTML=' ';"
\r
2282 +" row.appendChild(cell);"
\r
2284 +" workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"
\r
2287 +" workingNode = workingNode.parentNode;"
\r
2289 +"} insertTableRow();");
\r
2290 browser.page().mainFrame().evaluateJavaScript(js);
\r
2293 //****************************************************************
\r
2294 //* Insert a table row
\r
2295 //****************************************************************
\r
2296 public void deleteTableRow() {
\r
2298 String js = new String( "function deleteTableRow() {"
\r
2299 +" var selObj = window.getSelection();"
\r
2300 +" var selRange = selObj.getRangeAt(0);"
\r
2301 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2302 +" var cellCount = 0;"
\r
2303 +" while(workingNode != null) { "
\r
2304 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2305 +" workingNode.parentNode.removeChild(workingNode);"
\r
2308 +" workingNode = workingNode.parentNode;"
\r
2310 +"} deleteTableRow();");
\r
2311 browser.page().mainFrame().evaluateJavaScript(js);
\r
2314 public void setInsideTable() {
\r
2315 browser.insertTableRowAction.setEnabled(true);
\r
2316 browser.deleteTableRowAction.setEnabled(true);
\r
2317 browser.insertTableAction.setEnabled(false);
\r
2318 browser.encryptAction.setEnabled(false);
\r
2321 public void setInsideLink(String link) {
\r
2322 browser.insertLinkAction.setText(tr("Edit Hyperlink"));
\r
2323 currentHyperlink = link;
\r
2326 public void italicActive() {
\r
2327 italicButton.setDown(true);
\r
2329 public void boldActive() {
\r
2330 boldButton.setDown(true);
\r
2332 public void underlineActive() {
\r
2333 underlineButton.setDown(true);
\r
2335 public void forceTextPaste() {
\r
2336 forceTextPaste = true;
\r
2338 public void imageContextMenu(String f) {
\r
2339 browser.downloadImage.setEnabled(true);
\r
2340 browser.rotateImageRight.setEnabled(true);
\r
2341 browser.rotateImageLeft.setEnabled(true);
\r
2342 browser.openAction.setEnabled(true);
\r
2345 public void rotateImageRight() {
\r
2346 QWebSettings.setMaximumPagesInCache(0);
\r
2347 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2348 QImage image = new QImage(selectedFile);
\r
2349 QMatrix matrix = new QMatrix();
\r
2350 matrix.rotate( 90.0 );
\r
2351 image = image.transformed(matrix);
\r
2352 image.save(selectedFile);
\r
2353 QWebSettings.setMaximumPagesInCache(0);
\r
2354 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2355 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2358 // resourceSignal.contentChanged.emit(selectedFile);
\r
2361 public void rotateImageLeft() {
\r
2362 QImage image = new QImage(selectedFile);
\r
2363 QMatrix matrix = new QMatrix();
\r
2364 matrix.rotate( -90.0 );
\r
2365 image = image.transformed(matrix);
\r
2366 image.save(selectedFile);
\r
2367 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2370 // resourceSignal.contentChanged.emit(selectedFile);
\r
2372 public void resourceContextMenu(String f) {
\r
2373 browser.downloadAttachment.setEnabled(true);
\r
2374 browser.openAction.setEnabled(true);
\r
2379 //****************************************************************
\r
2380 //* Apply CSS style to specified word
\r
2381 //****************************************************************
\r
2382 /* public void applyStyleToWords(String word, String style) {
\r
2383 QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");
\r
2384 script.open(OpenModeFlag.ReadOnly);
\r
2385 String s = script.readAll().toString();
\r
2386 String js = new String(s +" findit('"+word+"', '"+style+"');");
\r
2387 browser.page().mainFrame().evaluateJavaScript(js);
\r
2388 System.out.println(getContent());
\r
2391 //****************************************************************
\r
2392 //* Someone tried to paste a resource between notes, so we need *
\r
2393 //* to do some special handling. *
\r
2394 //****************************************************************
\r
2395 private String fixInternotePaste(String text) {
\r
2396 logger.log(logger.EXTREME, "Fixing internote paste");
\r
2397 String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");
\r
2398 return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");
\r
2400 private String fixInternotePasteSearch(String text, String type, String locTag) {
\r
2402 // First, let's fix the images.
\r
2403 int startPos = text.indexOf(type);
\r
2405 for (; startPos>=0;) {
\r
2406 endPos = text.indexOf(">", startPos+1);
\r
2407 String segment = text.substring(startPos, endPos);
\r
2408 if (segment.indexOf("en-tag") > -1) {
\r
2409 String newSegment = segment;
\r
2411 int guidStartPos = segment.indexOf("guid=\"");
\r
2412 int guidEndPos = segment.indexOf("\"", guidStartPos+7);
\r
2413 String guid = segment.substring(guidStartPos+6,guidEndPos);
\r
2415 int mimeStartPos = segment.indexOf("type");
\r
2416 int mimeEndPos = segment.indexOf("\"", mimeStartPos+7);
\r
2417 String mime = segment.substring(mimeStartPos+6,mimeEndPos);
\r
2419 int srcStartPos = segment.indexOf("src");
\r
2420 int srcEndPos = segment.indexOf("\"", srcStartPos+6);
\r
2421 String src = segment.substring(srcStartPos+5,srcEndPos);
\r
2423 Calendar currentTime = new GregorianCalendar();
\r
2424 Long l = new Long(currentTime.getTimeInMillis());
\r
2425 long prevTime = l;
\r
2426 while (l==prevTime) {
\r
2427 currentTime = new GregorianCalendar();
\r
2428 l= new Long(currentTime.getTimeInMillis());
\r
2431 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2432 // if r==null, then the image doesn't exist (it was probably cut out of another note, so
\r
2433 // we need to recereate it
\r
2435 r = createResource(src, 1, mime, false);
\r
2439 String randint = new String(Long.toString(l));
\r
2440 String extension = null;
\r
2441 if (r.getMime()!= null) {
\r
2442 extension = r.getMime().toLowerCase();
\r
2443 if (extension.indexOf("/")>-1)
\r
2444 extension = extension.substring(extension.indexOf("/")+1);
\r
2446 String newFile = randint;
\r
2447 if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")
\r
2448 if (!locTag.startsWith("src"))
\r
2449 newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();
\r
2450 r.setNoteGuid(currentNote.getGuid());
\r
2452 r.setGuid(randint);
\r
2453 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
2454 QFile f = new QFile(Global.getFileManager().getResDirPath(newFile));
\r
2455 QByteArray bin = new QByteArray(r.getData().getBody());
\r
2456 f.open(QFile.OpenModeFlag.WriteOnly);
\r
2459 newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);
\r
2460 currentNote.getResources().add(r);
\r
2462 int startSrcPos = newSegment.indexOf(locTag);
\r
2463 int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);
\r
2465 if (locTag.startsWith("src")) {
\r
2466 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2467 newSegment = newSegment.replace(source,
\r
2468 FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath(newFile)));
\r
2470 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2471 newSegment = newSegment.replace(source, newFile);
\r
2474 text = text.substring(0,startPos) + newSegment + text.substring(endPos);
\r
2476 startPos = text.indexOf(type, startPos+1);
\r
2482 public void nextPage(String file) {
\r
2483 logger.log(logger.EXTREME, "Starting nextPage()");
\r
2485 Integer pageNumber;
\r
2486 if (previewPageList.containsKey(file))
\r
2487 pageNumber = previewPageList.get(file)+1;
\r
2490 previewPageList.remove(file);
\r
2491 previewPageList.put(file, pageNumber);
\r
2492 PDFPreview pdfPreview = new PDFPreview();
\r
2493 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2494 if (goodPreview) {
\r
2496 // String html = getContent();
\r
2497 QWebSettings.setMaximumPagesInCache(0);
\r
2498 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2499 // browser.setContent(new QByteArray());
\r
2500 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2502 // browser.setContent(new QByteArray(html));
\r
2503 // browser.triggerPageAction(WebAction.Reload);
\r
2504 // pdfMouseOver(selectedFile);
\r
2508 public void previousPage(String file) {
\r
2509 logger.log(logger.EXTREME, "Starting previousPage()");
\r
2511 Integer pageNumber;
\r
2512 if (previewPageList.containsKey(file))
\r
2513 pageNumber = previewPageList.get(file)-1;
\r
2516 previewPageList.remove(file);
\r
2517 previewPageList.put(file, pageNumber);
\r
2518 PDFPreview pdfPreview = new PDFPreview();
\r
2519 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2520 if (goodPreview) {
\r
2522 // String html = getContent();
\r
2523 QWebSettings.setMaximumPagesInCache(0);
\r
2524 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2525 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2527 // browser.setContent(new QByteArray(html));
\r
2528 // browser.triggerPageAction(WebAction.Reload);
\r
2532 /* public void pdfMouseOver(String name) {
\r
2534 if (previewPageList.containsKey(selectedFile))
\r
2535 pageNumber = previewPageList.get(selectedFile)+1;
\r
2539 if (pageNumber <= 1)
\r
2540 browser.previousPageAction.setEnabled(false);
\r
2542 browser.previousPageAction.setEnabled(true);
\r
2544 PDFPreview pdf = new PDFPreview();
\r
2545 int totalPages = pdf.getPageCount(name);
\r
2546 if (previewPageList.containsKey(selectedFile))
\r
2547 pageNumber = previewPageList.get(selectedFile)+1;
\r
2550 if (totalPages > pageNumber)
\r
2551 browser.nextPageAction.setEnabled(true);
\r
2553 browser.nextPageAction.setEnabled(false);
\r
2557 public void pdfMouseOut() {
\r
2558 // browser.nextPageAction.setVisible(false);
\r
2559 // browser.previousPageAction.setVisible(false);
\r
2563 private void toggleUndoVisible(Boolean toggle) {
\r
2564 undoAction.setVisible(toggle);
\r
2565 Global.saveEditorButtonsVisible("undo", toggle);
\r
2567 private void toggleRedoVisible(Boolean toggle) {
\r
2568 redoAction.setVisible(toggle);
\r
2569 Global.saveEditorButtonsVisible("redo", toggle);
\r
2571 private void toggleCutVisible(Boolean toggle) {
\r
2572 cutAction.setVisible(toggle);
\r
2573 Global.saveEditorButtonsVisible("cut", toggle);
\r
2575 private void toggleCopyVisible(Boolean toggle) {
\r
2576 copyAction.setVisible(toggle);
\r
2577 Global.saveEditorButtonsVisible("copy", toggle);
\r
2579 private void togglePasteVisible(Boolean toggle) {
\r
2580 pasteAction.setVisible(toggle);
\r
2581 Global.saveEditorButtonsVisible("paste", toggle);
\r
2583 private void toggleBoldVisible(Boolean toggle) {
\r
2584 boldAction.setVisible(toggle);
\r
2585 Global.saveEditorButtonsVisible("bold", toggle);
\r
2587 private void toggleItalicVisible(Boolean toggle) {
\r
2588 italicAction.setVisible(toggle);
\r
2589 Global.saveEditorButtonsVisible("italic", toggle);
\r
2591 private void toggleUnderlineVisible(Boolean toggle) {
\r
2592 underlineAction.setVisible(toggle);
\r
2593 Global.saveEditorButtonsVisible("underline", toggle);
\r
2595 private void toggleStrikethroughVisible(Boolean toggle) {
\r
2596 strikethroughAction.setVisible(toggle);
\r
2597 Global.saveEditorButtonsVisible("strikethrough", toggle);
\r
2599 private void toggleLeftAlignVisible(Boolean toggle) {
\r
2600 leftAlignAction.setVisible(toggle);
\r
2601 Global.saveEditorButtonsVisible("alignLeft", toggle);
\r
2603 private void toggleRightAlignVisible(Boolean toggle) {
\r
2604 rightAlignAction.setVisible(toggle);
\r
2605 Global.saveEditorButtonsVisible("alignRight", toggle);
\r
2607 private void toggleCenterAlignVisible(Boolean toggle) {
\r
2608 centerAlignAction.setVisible(toggle);
\r
2609 Global.saveEditorButtonsVisible("alignCenter", toggle);
\r
2611 private void toggleHLineVisible(Boolean toggle) {
\r
2612 hlineAction.setVisible(toggle);
\r
2613 Global.saveEditorButtonsVisible("hline", toggle);
\r
2615 private void toggleIndentVisible(Boolean toggle) {
\r
2616 indentAction.setVisible(toggle);
\r
2617 Global.saveEditorButtonsVisible("indent", toggle);
\r
2619 private void toggleOutdentVisible(Boolean toggle) {
\r
2620 outdentAction.setVisible(toggle);
\r
2621 Global.saveEditorButtonsVisible("outdent", toggle);
\r
2623 private void toggleBulletListVisible(Boolean toggle) {
\r
2624 bulletListAction.setVisible(toggle);
\r
2625 Global.saveEditorButtonsVisible("bulletList", toggle);
\r
2627 private void toggleNumberListVisible(Boolean toggle) {
\r
2628 numberListAction.setVisible(toggle);
\r
2629 Global.saveEditorButtonsVisible("numberList", toggle);
\r
2631 private void toggleFontListVisible(Boolean toggle) {
\r
2632 fontListAction.setVisible(toggle);
\r
2633 Global.saveEditorButtonsVisible("font", toggle);
\r
2635 private void toggleFontColorVisible(Boolean toggle) {
\r
2636 fontColorAction.setVisible(toggle);
\r
2637 Global.saveEditorButtonsVisible("fontColor", toggle);
\r
2639 private void toggleFontSizeVisible(Boolean toggle) {
\r
2640 fontSizeAction.setVisible(toggle);
\r
2641 Global.saveEditorButtonsVisible("fontSize", toggle);
\r
2643 private void toggleFontHilightVisible(Boolean toggle) {
\r
2644 fontHilightAction.setVisible(toggle);
\r
2645 Global.saveEditorButtonsVisible("fontHilight", toggle);
\r
2650 // Invoke spell checker dialog
\r
2651 private void doSpellCheck() {
\r
2653 File wordList = new File(Global.getFileManager().getSpellDirPath()+Locale.getDefault()+".dic");
\r
2654 SpellDictionary dictionary;
\r
2656 dictionary = new SpellDictionaryHashMap(wordList);
\r
2657 SpellChecker spellChecker = new SpellChecker(dictionary);
\r
2658 SuggestionListener spellListener = new SuggestionListener(this);
\r
2659 spellChecker.addSpellCheckListener(spellListener);
\r
2661 String content = getBrowser().page().mainFrame().toPlainText();
\r
2662 StringWordTokenizer tokenizer = new StringWordTokenizer(content);
\r
2663 if (!tokenizer.hasMoreWords())
\r
2665 String word = tokenizer.nextWord();
\r
2666 getBrowser().page().action(WebAction.MoveToStartOfDocument);
\r
2667 QWebPage.FindFlags flags = new QWebPage.FindFlags();
\r
2668 flags.set(QWebPage.FindFlag.FindBackward);
\r
2670 getBrowser().setFocus();
\r
2671 boolean found = getBrowser().page().findText(word);
\r
2673 QMessageBox.critical(this, tr("Spell Check Error"),
\r
2674 tr("An error has occurred while launching the spell check. The most probable" +
\r
2675 " cause is that the cursor was not at the beginning of the document.\n\n" +
\r
2676 "Please place the cursor at the beginning & try again"));
\r
2680 found = getBrowser().page().findText(word);
\r
2683 spellChecker.checkSpelling(new StringWordTokenizer(word));
\r
2684 getBrowser().setFocus();
\r
2686 flags = new QWebPage.FindFlags();
\r
2687 tokenizer = new StringWordTokenizer(content);
\r
2689 while(tokenizer.hasMoreWords()) {
\r
2690 word = tokenizer.nextWord();
\r
2691 found = getBrowser().page().findText(word);
\r
2692 if (found && !spellListener.abortSpellCheck) {
\r
2693 spellChecker.checkSpelling(new StringWordTokenizer(word));
\r
2694 getBrowser().setFocus();
\r
2697 spellChecker.removeSpellCheckListener(spellListener);
\r
2698 if (!spellListener.errorsFound)
\r
2699 QMessageBox.information(this, tr("Spell Check Complete"),
\r
2700 tr("No spelling errors found"));
\r
2701 } catch (FileNotFoundException e) {
\r
2702 QMessageBox.critical(this, tr("Spell Check Error"),
\r
2703 tr("Dictionary "+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
2704 ".dic was not found."));
\r
2705 } catch (IOException e) {
\r
2706 QMessageBox.critical(this, tr("Spell Check Error"),
\r
2707 tr("Dictionary "+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
2708 ".dic is invalid."));
\r
2714 >>>>>>> 14a0afe3faba057afbddf62aa8ed25139750d68b