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
203 public final QToolButton fontColor;
\r
204 public final QAction fontColorAction;
\r
205 private final ColorMenu fontColorMenu;
\r
206 public final QToolButton fontHilight;
\r
207 public final QAction fontHilightAction;
\r
208 private final ColorMenu fontHilightColorMenu;
\r
209 public final QFileSystemWatcher fileWatcher;
\r
210 public int cursorPosition;
\r
211 private boolean forceTextPaste = false;
\r
212 private String selectedFile;
\r
213 private String currentHyperlink;
\r
214 public boolean keepPDFNavigationHidden;
\r
215 private final ApplicationLogger logger;
\r
217 private final HashMap<String,Integer> previewPageList;
\r
220 public static class SuggestionListener implements SpellCheckListener {
\r
221 public boolean abortSpellCheck = false;
\r
222 public boolean errorsFound = false;
\r
224 private final BrowserWindow parent;
\r
225 public SuggestionListener(BrowserWindow parent) {
\r
226 this.parent = parent;
\r
228 public void spellingError(SpellCheckEvent event) {
\r
229 errorsFound = true;
\r
230 SpellCheck dialog = new SpellCheck();
\r
231 dialog.setWord(event.getInvalidWord());
\r
233 List<Word> suggestions = event.getSuggestions();
\r
234 if (suggestions.isEmpty()) {
\r
235 dialog.setNoSuggestions(true);
\r
237 dialog.setCurrentSuggestion(suggestions.get(0).getWord());
\r
238 for (int i=0; i<suggestions.size(); i++) {
\r
239 dialog.addSuggestion(suggestions.get(i).getWord());
\r
241 dialog.setSelectedSuggestion(0);
\r
244 if (dialog.cancelPressed()) {
\r
245 abortSpellCheck = true;
\r
248 if (dialog.replacePressed()) {
\r
249 QClipboard clipboard = QApplication.clipboard();
\r
250 clipboard.setText(dialog.getReplacementWord());
\r
251 parent.pasteClicked();
\r
258 public BrowserWindow(DatabaseConnection c) {
\r
259 logger = new ApplicationLogger("browser.log");
\r
260 logger.log(logger.HIGH, "Setting up browser");
\r
262 fileWatcher = new QFileSystemWatcher();
\r
263 // fileWatcher.fileChanged.connect(this, "fileChanged(String)");
\r
264 noteSignal = new NoteSignal();
\r
265 titleLabel = new QLineEdit();
\r
266 titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX);
\r
267 urlText = new QLineEdit();
\r
268 authorText = new QLineEdit();
\r
269 geoBox = new QComboBox();
\r
270 urlLabel = new QPushButton();
\r
271 urlLabel.clicked.connect(this, "sourceUrlClicked()");
\r
272 authorLabel = new QLabel();
\r
275 focusLost = new Signal0();
\r
277 tagEdit = new TagLineEdit(allTags);
\r
278 tagLabel = new QLabel("Tags:");
\r
279 tagEdit.focusLost.connect(this, "modifyTagsTyping()");
\r
281 createdCalendarWidget = new QCalendarWidget();
\r
282 createdDate = new QDateEdit();
\r
283 createdDate.setDisplayFormat(Global.getDateFormat());
\r
284 createdDate.setCalendarPopup(true);
\r
285 createdDate.setCalendarWidget(createdCalendarWidget);
\r
286 createdTime = new QTimeEdit();
\r
287 createdDate.dateChanged.connect(this, "createdChanged()");
\r
288 createdTime.timeChanged.connect(this, "createdChanged()");
\r
290 alteredCalendarWidget = new QCalendarWidget();
\r
291 alteredDate = new QDateEdit();
\r
292 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
293 alteredDate.setCalendarPopup(true);
\r
294 alteredDate.setCalendarWidget(alteredCalendarWidget);
\r
295 alteredTime = new QTimeEdit();
\r
296 alteredLabel = new QLabel("Altered:");
\r
297 alteredDate.dateChanged.connect(this, "alteredChanged()");
\r
298 alteredTime.timeChanged.connect(this, "alteredChanged()");
\r
300 subjectCalendarWidget = new QCalendarWidget();
\r
301 subjectDate = new QDateEdit();
\r
302 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
303 subjectDate.setCalendarPopup(true);
\r
304 subjectDate.setCalendarWidget(subjectCalendarWidget);
\r
305 subjectTime = new QTimeEdit();
\r
306 subjectLabel = new QLabel(tr("Subject Date:"));
\r
307 subjectDate.dateChanged.connect(this, "subjectDateTimeChanged()");
\r
308 subjectTime.timeChanged.connect(this, "subjectDateTimeChanged()");
\r
309 authorText.textChanged.connect(this, "authorChanged()");
\r
310 urlText.textChanged.connect(this, "sourceUrlChanged()");
\r
312 notebookBox = new QComboBox();
\r
313 notebookLabel = new QLabel(tr("Notebook"));
\r
314 createdLabel = new QLabel(tr("Created:"));
\r
315 // selectedText = new String();
\r
317 urlLabel.setVisible(false);
\r
318 urlText.setVisible(false);
\r
319 authorLabel.setVisible(false);
\r
321 geoBox.setVisible(false);
\r
322 geoBox.addItem(new QIcon(iconPath+"globe.png"), "");
\r
323 geoBox.addItem(new String(tr("Set")));
\r
324 geoBox.addItem(new String(tr("Clear")));
\r
325 geoBox.addItem(new String(tr("View On Map")));
\r
326 geoBox.activated.connect(this, "geoBoxChanged()");
\r
328 authorText.setVisible(false);
\r
329 createdDate.setVisible(false);
\r
330 alteredLabel.setVisible(false);
\r
331 //notebookBox.setVisible(false);
\r
332 notebookLabel.setVisible(false);
\r
333 createdLabel.setVisible(false);
\r
334 createdTime.setVisible(false);
\r
335 alteredDate.setVisible(false);
\r
336 alteredTime.setVisible(false);
\r
337 subjectLabel.setVisible(false);
\r
338 subjectDate.setVisible(false);
\r
339 subjectTime.setVisible(false);
\r
340 extendedOn = false;
\r
341 buttonsVisible = true;
\r
342 setAcceptDrops(true);
\r
344 browser = new ContentView(this);
\r
345 browser.page().setLinkDelegationPolicy(
\r
346 QWebPage.LinkDelegationPolicy.DelegateAllLinks);
\r
347 browser.linkClicked.connect(this, "linkClicked(QUrl)");
\r
348 currentHyperlink = "";
\r
350 QVBoxLayout v = new QVBoxLayout();
\r
351 QFormLayout notebookLayout = new QFormLayout();
\r
352 QGridLayout dateLayout = new QGridLayout();
\r
353 titleLabel.setReadOnly(false);
\r
354 titleLabel.editingFinished.connect(this, "titleEdited()");
\r
355 browser.page().contentsChanged.connect(this, "contentChanged()");
\r
356 browser.page().selectionChanged.connect(this, "selectionChanged()");
\r
357 browser.page().mainFrame().javaScriptWindowObjectCleared.connect(this,
\r
358 "exposeToJavascript()");
\r
360 notebookBox.activated.connect(this, "notebookChanged()");
\r
361 resourceSignal = new NoteResourceSignal();
\r
363 QHBoxLayout tagLayout = new QHBoxLayout();
\r
364 v.addWidget(titleLabel, 0);
\r
365 notebookLayout.addRow(notebookLabel, notebookBox);
\r
366 tagLayout.addLayout(notebookLayout, 0);
\r
367 tagLayout.stretch(4);
\r
368 tagLayout.addWidget(tagLabel, 0);
\r
369 tagLayout.addWidget(tagEdit, 1);
\r
370 v.addLayout(tagLayout);
\r
372 QHBoxLayout urlLayout = new QHBoxLayout();
\r
373 urlLayout.addWidget(urlLabel, 0);
\r
374 urlLayout.addWidget(urlText, 0);
\r
375 v.addLayout(urlLayout);
\r
377 QHBoxLayout authorLayout = new QHBoxLayout();
\r
378 authorLayout.addWidget(authorLabel, 0);
\r
379 authorLayout.addWidget(authorText, 0);
\r
380 authorLayout.addWidget(geoBox);
\r
381 v.addLayout(authorLayout);
\r
383 dateLayout.addWidget(createdLabel, 0, 0);
\r
384 dateLayout.addWidget(createdDate, 0, 1);
\r
385 dateLayout.addWidget(createdTime, 0, 2);
\r
386 dateLayout.setColumnStretch(9, 100);
\r
387 dateLayout.addWidget(alteredLabel, 0, 3);
\r
388 dateLayout.addWidget(alteredDate, 0, 4);
\r
389 dateLayout.addWidget(alteredTime, 0, 5);
\r
390 dateLayout.addWidget(subjectLabel, 0, 6);
\r
391 dateLayout.addWidget(subjectDate, 0, 7);
\r
392 dateLayout.addWidget(subjectTime, 0, 8);
\r
393 v.addLayout(dateLayout, 0);
\r
395 undoButton = newEditorButton("undo", tr("Undo Change"));
\r
396 redoButton = newEditorButton("redo", tr("Redo Change"));
\r
397 cutButton = newEditorButton("cut", tr("Cut"));
\r
398 copyButton = newEditorButton("copy", tr("Copy"));
\r
399 pasteButton = newEditorButton("paste", tr("Paste"));
\r
400 boldButton = newEditorButton("bold", tr("Bold"));
\r
401 underlineButton = newEditorButton("underline", tr("Underline"));
\r
402 italicButton = newEditorButton("italic", tr("Italic"));
\r
404 rightAlignButton = newEditorButton("justifyRight", tr("Right Align"));
\r
405 leftAlignButton = newEditorButton("justifyLeft", tr("Left Align"));
\r
406 centerAlignButton = newEditorButton("justifyCenter", tr("Center Align"));
\r
408 strikethroughButton = newEditorButton("strikethrough", tr("Strikethrough"));
\r
409 hlineButton = newEditorButton("hline", tr("Insert Horizontal Line"));
\r
410 indentButton = newEditorButton("indent", tr("Shift Right"));
\r
411 outdentButton = newEditorButton("outdent", tr("Shift Left"));
\r
412 bulletListButton = newEditorButton("bulletList", tr("Bullet List"));
\r
413 numberListButton = newEditorButton("numberList", tr("Number List"));
\r
416 buttonLayout = new EditorButtonBar();
\r
417 // buttonLayout.setSpacing(0);
\r
418 v.addWidget(buttonLayout);
\r
420 undoAction = buttonLayout.addWidget(undoButton);
\r
421 buttonLayout.toggleUndoVisible.triggered.connect(this, "toggleUndoVisible(Boolean)");
\r
422 redoAction = buttonLayout.addWidget(redoButton);
\r
423 buttonLayout.toggleRedoVisible.triggered.connect(this, "toggleRedoVisible(Boolean)");
\r
425 buttonLayout.addWidget(newSeparator());
\r
426 cutAction = buttonLayout.addWidget(cutButton);
\r
427 buttonLayout.toggleCutVisible.triggered.connect(this, "toggleCutVisible(Boolean)");
\r
428 copyAction = buttonLayout.addWidget(copyButton);
\r
429 buttonLayout.toggleCopyVisible.triggered.connect(this, "toggleCopyVisible(Boolean)");
\r
430 pasteAction = buttonLayout.addWidget(pasteButton);
\r
431 buttonLayout.togglePasteVisible.triggered.connect(this, "togglePasteVisible(Boolean)");
\r
433 buttonLayout.addWidget(newSeparator());
\r
434 boldAction = buttonLayout.addWidget(boldButton);
\r
435 buttonLayout.toggleBoldVisible.triggered.connect(this, "toggleBoldVisible(Boolean)");
\r
436 italicAction = buttonLayout.addWidget(italicButton);
\r
437 buttonLayout.toggleItalicVisible.triggered.connect(this, "toggleItalicVisible(Boolean)");
\r
438 underlineAction = buttonLayout.addWidget(underlineButton);
\r
439 buttonLayout.toggleUnderlineVisible.triggered.connect(this, "toggleUnderlineVisible(Boolean)");
\r
440 strikethroughAction = buttonLayout.addWidget(strikethroughButton);
\r
441 buttonLayout.toggleStrikethroughVisible.triggered.connect(this, "toggleStrikethroughVisible(Boolean)");
\r
444 buttonLayout.addWidget(newSeparator());
\r
445 leftAlignAction = buttonLayout.addWidget(leftAlignButton);
\r
446 buttonLayout.toggleLeftAlignVisible.triggered.connect(this, "toggleLeftAlignVisible(Boolean)");
\r
447 centerAlignAction = buttonLayout.addWidget(centerAlignButton);
\r
448 buttonLayout.toggleCenterAlignVisible.triggered.connect(this, "toggleCenterAlignVisible(Boolean)");
\r
449 rightAlignAction = buttonLayout.addWidget(rightAlignButton);
\r
450 buttonLayout.toggleRightAlignVisible.triggered.connect(this, "toggleRightAlignVisible(Boolean)");
\r
452 buttonLayout.addWidget(newSeparator());
\r
453 hlineAction = buttonLayout.addWidget(hlineButton);
\r
454 buttonLayout.toggleHLineVisible.triggered.connect(this, "toggleHLineVisible(Boolean)");
\r
456 indentAction = buttonLayout.addWidget(indentButton);
\r
457 buttonLayout.toggleIndentVisible.triggered.connect(this, "toggleIndentVisible(Boolean)");
\r
458 outdentAction = buttonLayout.addWidget(outdentButton);
\r
459 buttonLayout.toggleOutdentVisible.triggered.connect(this, "toggleOutdentVisible(Boolean)");
\r
460 bulletListAction = buttonLayout.addWidget(bulletListButton);
\r
461 buttonLayout.toggleBulletListVisible.triggered.connect(this, "toggleBulletListVisible(Boolean)");
\r
462 numberListAction = buttonLayout.addWidget(numberListButton);
\r
463 buttonLayout.toggleNumberListVisible.triggered.connect(this, "toggleNumberListVisible(Boolean)");
\r
465 // Setup the font & font size combo boxes
\r
466 buttonLayout.addWidget(newSeparator());
\r
467 fontList = new QComboBox();
\r
468 fontSize = new QComboBox();
\r
469 fontList.setToolTip("Font");
\r
470 fontSize.setToolTip("Font Size");
\r
471 fontList.activated.connect(this, "fontChanged(String)");
\r
472 fontSize.activated.connect(this, "fontSizeChanged(String)");
\r
473 fontListAction = buttonLayout.addWidget(fontList);
\r
474 buttonLayout.toggleFontVisible.triggered.connect(this, "toggleFontListVisible(Boolean)");
\r
475 fontSizeAction = buttonLayout.addWidget(fontSize);
\r
476 buttonLayout.toggleFontSizeVisible.triggered.connect(this, "toggleFontSizeVisible(Boolean)");
\r
477 QFontDatabase fonts = new QFontDatabase();
\r
478 List<String> fontFamilies = fonts.families();
\r
479 for (int i = 0; i < fontFamilies.size(); i++) {
\r
480 fontList.addItem(fontFamilies.get(i));
\r
482 loadFontSize(fontFamilies.get(i));
\r
486 // buttonLayout.addWidget(newSeparator(), 0);
\r
487 fontColor = newToolButton("fontColor", tr("Font Color"));
\r
488 fontColorMenu = new ColorMenu(this);
\r
489 fontColor.setMenu(fontColorMenu.getMenu());
\r
490 fontColor.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
491 fontColor.setAutoRaise(false);
\r
492 fontColorMenu.getMenu().triggered.connect(this, "fontColorClicked()");
\r
493 fontColorAction = buttonLayout.addWidget(fontColor);
\r
494 buttonLayout.toggleFontColorVisible.triggered.connect(this, "toggleFontColorVisible(Boolean)");
\r
495 fontHilight = newToolButton("fontHilight", tr("Font Hilight Color"));
\r
496 fontHilight.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
497 fontHilight.setAutoRaise(false);
\r
498 fontHilightColorMenu = new ColorMenu(this);
\r
499 fontHilightColorMenu.setDefault(QColor.yellow);
\r
500 fontHilight.setMenu(fontHilightColorMenu.getMenu());
\r
501 fontHilightColorMenu.getMenu().triggered.connect(this, "fontHilightClicked()");
\r
502 fontHilightAction = buttonLayout.addWidget(fontHilight);
\r
503 fontHilightColorMenu.setDefault(QColor.yellow);
\r
504 buttonLayout.toggleFontHilight.triggered.connect(this, "toggleFontHilightVisible(Boolean)");
\r
506 // buttonLayout.addWidget(new QLabel(), 1);
\r
507 v.addWidget(browser, 1);
\r
510 browser.downloadAttachmentRequested.connect(this,
\r
511 "downloadAttachment(QNetworkRequest)");
\r
512 browser.downloadImageRequested.connect(this,
\r
513 "downloadImage(QNetworkRequest)");
\r
514 setTabOrder(notebookBox, tagEdit);
\r
515 setTabOrder(tagEdit, browser);
\r
517 focusNoteShortcut = new QShortcut(this);
\r
518 setupShortcut(focusNoteShortcut, "Focus_Note");
\r
519 focusNoteShortcut.activated.connect(this, "focusNote()");
\r
520 focusTitleShortcut = new QShortcut(this);
\r
521 setupShortcut(focusTitleShortcut, "Focus_Title");
\r
522 focusTitleShortcut.activated.connect(this, "focusTitle()");
\r
523 focusTagShortcut = new QShortcut(this);
\r
524 setupShortcut(focusTagShortcut, "Focus_Tag");
\r
525 focusTagShortcut.activated.connect(this, "focusTag()");
\r
526 focusAuthorShortcut = new QShortcut(this);
\r
527 setupShortcut(focusAuthorShortcut, "Focus_Author");
\r
528 focusAuthorShortcut.activated.connect(this, "focusAuthor()");
\r
529 focusUrlShortcut = new QShortcut(this);
\r
530 setupShortcut(focusUrlShortcut, "Focus_Url");
\r
531 focusUrlShortcut.activated.connect(this, "focusUrl()");
\r
533 browser.page().mainFrame().setTextSizeMultiplier(Global.getTextSizeMultiplier());
\r
534 browser.page().mainFrame().setZoomFactor(Global.getZoomFactor());
\r
536 previewPageList = new HashMap<String,Integer>();
\r
538 browser.page().microFocusChanged.connect(this, "microFocusChanged()");
\r
539 logger.log(logger.HIGH, "Browser setup complete");
\r
544 private void setupShortcut(QShortcut action, String text) {
\r
545 if (!Global.shortcutKeys.containsAction(text))
\r
547 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
\r
553 // Getter for the QWebView
\r
554 public QWebView getBrowser() {
\r
558 // Block signals while loading data or things are flagged as dirty by
\r
560 public void loadingData(boolean val) {
\r
561 logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val);
\r
562 notebookBox.blockSignals(val);
\r
563 browser.page().blockSignals(val);
\r
564 browser.page().mainFrame().blockSignals(val);
\r
565 titleLabel.blockSignals(val);
\r
566 alteredDate.blockSignals(val);
\r
567 alteredTime.blockSignals(val);
\r
568 createdTime.blockSignals(val);
\r
569 createdDate.blockSignals(val);
\r
570 subjectDate.blockSignals(val);
\r
571 subjectTime.blockSignals(val);
\r
572 urlText.blockSignals(val);
\r
573 authorText.blockSignals(val);
\r
575 exposeToJavascript();
\r
576 logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val);
\r
580 public void setReadOnly(boolean v) {
\r
582 titleLabel.setEnabled(!v);
\r
583 notebookBox.setEnabled(!v);
\r
584 tagEdit.setEnabled(!v);
\r
585 authorLabel.setEnabled(!v);
\r
586 geoBox.setEnabled(!v);
\r
587 urlText.setEnabled(!v);
\r
588 createdDate.setEnabled(!v);
\r
589 subjectDate.setEnabled(!v);
\r
590 alteredDate.setEnabled(!v);
\r
591 getBrowser().setEnabled(true);
\r
594 // expose this class to Javascript on the web page
\r
595 private void exposeToJavascript() {
\r
596 browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this);
\r
599 // Custom event queue
\r
601 public boolean event(QEvent e) {
\r
602 if (e.type().equals(QEvent.Type.FocusOut)) {
\r
603 logger.log(logger.EXTREME, "Focus lost");
\r
606 return super.event(e);
\r
609 // clear out browser
\r
610 public void clear() {
\r
611 logger.log(logger.EXTREME, "Entering BrowserWindow.clear()");
\r
613 browser.setContent(new QByteArray());
\r
614 tagEdit.setText("");
\r
615 tagEdit.tagCompleter.reset();
\r
616 urlLabel.setText(tr("Source URL:"));
\r
617 titleLabel.setText("");
\r
618 logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()");
\r
621 // get/set current note
\r
622 public void setNote(Note n) {
\r
626 saveNoteTitle = n.getTitle();
\r
630 public Note getNote() {
\r
631 return currentNote;
\r
634 // New Editor Button
\r
635 private QPushButton newEditorButton(String name, String toolTip) {
\r
636 QPushButton button = new QPushButton();
\r
637 QIcon icon = new QIcon(iconPath + name + ".gif");
\r
638 button.setIcon(icon);
\r
639 button.setToolTip(toolTip);
\r
640 button.clicked.connect(this, name + "Clicked()");
\r
643 // New Editor Button
\r
644 private QToolButton newToolButton(String name, String toolTip) {
\r
645 QToolButton button = new QToolButton();
\r
646 QIcon icon = new QIcon(iconPath + name + ".gif");
\r
647 button.setIcon(icon);
\r
648 button.setToolTip(toolTip);
\r
649 button.clicked.connect(this, name + "Clicked()");
\r
654 private QLabel newSeparator() {
\r
655 return new QLabel(" ");
\r
658 // Set the title in the window
\r
659 public void setTitle(String t) {
\r
660 titleLabel.setText(t);
\r
665 // Return the current text title
\r
666 public String getTitle() {
\r
667 return titleLabel.text();
\r
670 // Set the tag name string
\r
671 public void setTag(String t) {
\r
673 tagEdit.setText(t);
\r
674 tagEdit.tagCompleter.reset();
\r
677 // Set the source URL
\r
678 public void setUrl(String t) {
\r
679 urlLabel.setText(tr("Source URL:\t"));
\r
680 urlText.setText(t);
\r
683 // The user want's to launch a web browser on the source of the URL
\r
684 public void sourceUrlClicked() {
\r
685 // Make sure we have a valid URL
\r
686 if (urlText.text().trim().equals(""))
\r
689 String url = urlText.text();
\r
690 if (!url.toLowerCase().startsWith(tr("http://")))
\r
691 url = tr("http://") +url;
\r
693 if (!QDesktopServices.openUrl(new QUrl(url))) {
\r
694 logger.log(logger.LOW, "Error opening file :" +url);
\r
698 public void setAuthor(String t) {
\r
699 authorLabel.setText(tr("Author:\t"));
\r
700 authorText.setText(t);
\r
703 // Set the creation date
\r
704 public void setCreation(long date) {
\r
705 QDateTime dt = new QDateTime();
\r
706 dt.setTime_t((int) (date / 1000));
\r
707 createdDate.setDateTime(dt);
\r
708 createdTime.setDateTime(dt);
\r
709 createdDate.setDisplayFormat(Global.getDateFormat());
\r
710 createdTime.setDisplayFormat(Global.getTimeFormat());
\r
713 // Set the creation date
\r
714 public void setAltered(long date) {
\r
715 QDateTime dt = new QDateTime();
\r
716 dt.setTime_t((int) (date / 1000));
\r
717 alteredDate.setDateTime(dt);
\r
718 alteredTime.setDateTime(dt);
\r
719 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
720 alteredTime.setDisplayFormat(Global.getTimeFormat());
\r
723 // Set the subject date
\r
724 public void setSubjectDate(long date) {
\r
725 QDateTime dt = new QDateTime();
\r
726 dt.setTime_t((int) (date / 1000));
\r
727 subjectDate.setDateTime(dt);
\r
728 subjectTime.setDateTime(dt);
\r
729 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
730 subjectTime.setDisplayFormat(Global.getTimeFormat());
\r
733 // Toggle the extended attribute information
\r
734 public void toggleInformation() {
\r
736 extendedOn = false;
\r
740 urlLabel.setVisible(extendedOn);
\r
741 urlText.setVisible(extendedOn);
\r
742 authorText.setVisible(extendedOn);
\r
743 geoBox.setVisible(extendedOn);
\r
744 authorLabel.setVisible(extendedOn);
\r
745 createdDate.setVisible(extendedOn);
\r
746 createdTime.setVisible(extendedOn);
\r
747 createdLabel.setVisible(extendedOn);
\r
748 alteredLabel.setVisible(extendedOn);
\r
749 alteredDate.setVisible(extendedOn);
\r
750 alteredTime.setVisible(extendedOn);
\r
751 //notebookBox.setVisible(extendedOn);
\r
752 notebookLabel.setVisible(extendedOn);
\r
753 subjectLabel.setVisible(extendedOn);
\r
754 subjectDate.setVisible(extendedOn);
\r
755 subjectTime.setVisible(extendedOn);
\r
758 public void hideButtons() {
\r
760 undoButton.parentWidget().setVisible(false);
\r
761 buttonsVisible = false;
\r
765 // Is the extended view on?
\r
766 public boolean isExtended() {
\r
770 // Listener for when a link is clicked
\r
771 @SuppressWarnings("unused")
\r
772 private void openFile() {
\r
773 logger.log(logger.EXTREME, "Starting openFile()");
\r
774 File fileHandle = new File(selectedFile);
\r
775 URI fileURL = fileHandle.toURI();
\r
776 String localURL = fileURL.toString();
\r
777 QUrl url = new QUrl(localURL);
\r
778 QFile file = new QFile(selectedFile);
\r
780 logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName());
\r
781 fileWatcher.addPath(file.fileName());
\r
783 if (!QDesktopServices.openUrl(url)) {
\r
784 logger.log(logger.LOW, "Error opening file :" +url);
\r
789 // Listener for when a link is clicked
\r
790 @SuppressWarnings("unused")
\r
791 private void linkClicked(QUrl url) {
\r
792 logger.log(logger.EXTREME, "URL Clicked: " +url.toString());
\r
793 if (url.toString().substring(0,8).equals("nnres://")) {
\r
794 logger.log(logger.EXTREME, "URL is NN resource");
\r
795 if (url.toString().endsWith("/vnd.evernote.ink")) {
\r
796 logger.log(logger.EXTREME, "Unable to open ink note");
\r
797 QMessageBox.information(this, tr("Unable Open"), tr("This is an ink note.\n"+
\r
798 "Ink notes are not supported since Evernote has not\n published any specifications on them\n" +
\r
799 "and I'm too lazy to figure them out by myself."));
\r
802 String fullName = url.toString().substring(8);
\r
803 int index = fullName.indexOf(".");
\r
807 type = fullName.substring(index+1);
\r
808 guid = fullName.substring(0,index);
\r
810 index = guid.indexOf(Global.attachmentNameDelimeter);
\r
812 guid = guid.substring(0,index);
\r
814 List<Resource> resList = currentNote.getResources();
\r
815 Resource res = null;
\r
816 for (int i=0; i<resList.size(); i++) {
\r
817 if (resList.get(i).getGuid().equals(guid)) {
\r
818 res = resList.get(i);
\r
823 String resGuid = Global.resourceMap.get(guid);
\r
824 if (resGuid != null)
\r
825 res = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, true);
\r
829 if (res.getAttributes() != null &&
\r
830 res.getAttributes().getFileName() != null &&
\r
831 !res.getAttributes().getFileName().trim().equals(""))
\r
832 fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();
\r
834 fileName = res.getGuid()+"."+type;
\r
835 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
836 QFile.OpenMode mode = new QFile.OpenMode();
\r
837 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
838 boolean openResult = file.open(mode);
\r
839 logger.log(logger.EXTREME, "File opened:" +openResult);
\r
840 QDataStream out = new QDataStream(file);
\r
841 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);
\r
842 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
844 logger.log(logger.EXTREME, "Writing resource");
\r
845 out.writeBytes(binData.toByteArray());
\r
848 String whichOS = System.getProperty("os.name");
\r
849 if (whichOS.contains("Windows"))
\r
850 url.setUrl("file:///"+file.fileName());
\r
852 url.setUrl("file://"+file.fileName());
\r
853 // fileWatcher.removePath(file.fileName());
\r
854 logger.log(logger.EXTREME, "Adding file watcher " +file.fileName());
\r
855 fileWatcher.addPath(file.fileName());
\r
857 // If we can't open it, then prompt the user to save it.
\r
858 if (!QDesktopServices.openUrl(url)) {
\r
859 logger.log(logger.EXTREME, "We can't handle this. Where do we put it?");
\r
860 QFileDialog dialog = new QFileDialog();
\r
862 if (dialog.exec()!=0) {
\r
863 List<String> fileNames = dialog.selectedFiles(); //gets all selected filenames
\r
864 if (fileNames.size() == 0)
\r
866 String sf = fileNames.get(0);
\r
867 QFile saveFile = new QFile(sf);
\r
868 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
869 saveFile.open(mode);
\r
870 QDataStream saveOut = new QDataStream(saveFile);
\r
871 saveOut.writeBytes(binData.toByteArray());
\r
879 logger.log(logger.EXTREME, "Launching URL");
\r
880 QDesktopServices.openUrl(url);
\r
883 // Listener for when BOLD is clicked
\r
884 @SuppressWarnings("unused")
\r
885 private void undoClicked() {
\r
886 browser.page().triggerAction(WebAction.Undo);
\r
887 browser.setFocus();
\r
890 // Listener for when BOLD is clicked
\r
891 @SuppressWarnings("unused")
\r
892 private void redoClicked() {
\r
893 browser.page().triggerAction(WebAction.Redo);
\r
894 browser.setFocus();
\r
897 // Listener for when BOLD is clicked
\r
898 @SuppressWarnings("unused")
\r
899 private void boldClicked() {
\r
900 browser.page().triggerAction(WebAction.ToggleBold);
\r
901 microFocusChanged();
\r
902 browser.setFocus();
\r
905 // Listener for when Italics is clicked
\r
906 @SuppressWarnings("unused")
\r
907 private void italicClicked() {
\r
908 browser.page().triggerAction(WebAction.ToggleItalic);
\r
909 microFocusChanged();
\r
910 browser.setFocus();
\r
913 // Listener for when UNDERLINE is clicked
\r
914 @SuppressWarnings("unused")
\r
915 private void underlineClicked() {
\r
916 browser.page().triggerAction(WebAction.ToggleUnderline);
\r
917 microFocusChanged();
\r
918 browser.setFocus();
\r
921 // Listener for when Strikethrough is clicked
\r
922 @SuppressWarnings("unused")
\r
923 private void strikethroughClicked() {
\r
924 browser.page().mainFrame().evaluateJavaScript(
\r
925 "document.execCommand('strikeThrough', false, '');");
\r
926 browser.setFocus();
\r
929 // Listener for when cut is clicked
\r
930 @SuppressWarnings("unused")
\r
931 private void cutClicked() {
\r
932 browser.page().triggerAction(WebAction.Cut);
\r
933 browser.setFocus();
\r
936 // Listener when COPY is clicked
\r
937 @SuppressWarnings("unused")
\r
938 private void copyClicked() {
\r
939 browser.page().triggerAction(WebAction.Copy);
\r
940 browser.setFocus();
\r
943 // Listener when PASTE is clicked
\r
944 public void pasteClicked() {
\r
945 logger.log(logger.EXTREME, "Paste Clicked");
\r
946 if (forceTextPaste) {
\r
947 pasteWithoutFormattingClicked();
\r
950 QClipboard clipboard = QApplication.clipboard();
\r
951 QMimeData mime = clipboard.mimeData();
\r
953 // String x = mime.html();
\r
955 if (mime.hasImage()) {
\r
956 logger.log(logger.EXTREME, "Image paste found");
\r
958 browser.setFocus();
\r
962 if (mime.hasUrls()) {
\r
963 logger.log(logger.EXTREME, "URL paste found");
\r
965 browser.setFocus();
\r
969 String text = mime.html();
\r
970 if (text.contains("en-tag") && mime.hasHtml()) {
\r
971 logger.log(logger.EXTREME, "Intra-note paste found");
\r
972 text = fixInternotePaste(text);
\r
973 mime.setHtml(text);
\r
974 clipboard.setMimeData(mime);
\r
977 logger.log(logger.EXTREME, "Final paste choice encountered");
\r
978 browser.page().triggerAction(WebAction.Paste);
\r
979 browser.setFocus();
\r
983 // Paste text without formatting
\r
984 private void pasteWithoutFormattingClicked() {
\r
985 logger.log(logger.EXTREME, "Paste without format clipped");
\r
986 QClipboard clipboard = QApplication.clipboard();
\r
987 QMimeData mime = clipboard.mimeData();
\r
988 if (!mime.hasText())
\r
990 String text = mime.text();
\r
991 clipboard.setText(text);
\r
992 browser.page().triggerAction(WebAction.Paste);
\r
993 QApplication.clipboard().setMimeData(mime);
\r
994 browser.setFocus();
\r
998 // insert date/time
\r
999 @SuppressWarnings("unused")
\r
1000 private void insertDateTime() {
\r
1001 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
\r
1002 String dateTimeFormat = new String(fmt);
\r
1003 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
\r
1004 Calendar cal = Calendar.getInstance();
\r
1006 browser.page().mainFrame().evaluateJavaScript(
\r
1007 "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");
\r
1009 browser.setFocus();
\r
1013 // Listener when Left is clicked
\r
1014 @SuppressWarnings("unused")
\r
1015 private void justifyLeftClicked() {
\r
1016 browser.page().mainFrame().evaluateJavaScript(
\r
1017 "document.execCommand('JustifyLeft', false, '');");
\r
1018 browser.setFocus();
\r
1021 // Listener when Center is clicked
\r
1022 @SuppressWarnings("unused")
\r
1023 private void justifyCenterClicked() {
\r
1024 browser.page().mainFrame().evaluateJavaScript(
\r
1025 "document.execCommand('JustifyCenter', false, '');");
\r
1026 browser.setFocus();
\r
1029 // Listener when Left is clicked
\r
1030 @SuppressWarnings("unused")
\r
1031 private void justifyRightClicked() {
\r
1032 browser.page().mainFrame().evaluateJavaScript(
\r
1033 "document.execCommand('JustifyRight', false, '');");
\r
1034 browser.setFocus();
\r
1037 // Listener when HLINE is clicked
\r
1038 @SuppressWarnings("unused")
\r
1039 private void hlineClicked() {
\r
1040 browser.page().mainFrame().evaluateJavaScript(
\r
1041 "document.execCommand('insertHorizontalRule', false, '');");
\r
1042 browser.setFocus();
\r
1045 // Listener when outdent is clicked
\r
1046 private void outdentClicked() {
\r
1047 browser.page().mainFrame().evaluateJavaScript(
\r
1048 "document.execCommand('outdent', false, '');");
\r
1049 browser.setFocus();
\r
1052 // Listener when a bullet list is clicked
\r
1053 @SuppressWarnings("unused")
\r
1054 private void bulletListClicked() {
\r
1055 browser.page().mainFrame().evaluateJavaScript(
\r
1056 "document.execCommand('InsertUnorderedList', false, '');");
\r
1057 browser.setFocus();
\r
1060 // Listener when a bullet list is clicked
\r
1061 @SuppressWarnings("unused")
\r
1062 private void numberListClicked() {
\r
1063 browser.page().mainFrame().evaluateJavaScript(
\r
1064 "document.execCommand('InsertOrderedList', false, '');");
\r
1065 browser.setFocus();
\r
1068 // Listener when indent is clicked
\r
1069 private void indentClicked() {
\r
1070 browser.page().mainFrame().evaluateJavaScript(
\r
1071 "document.execCommand('indent', false, '');");
\r
1072 browser.setFocus();
\r
1075 // Listener when the font name is changed
\r
1076 @SuppressWarnings("unused")
\r
1077 private void fontChanged(String font) {
\r
1078 browser.page().mainFrame().evaluateJavaScript(
\r
1079 "document.execCommand('fontName',false,'" + font + "');");
\r
1080 browser.setFocus();
\r
1083 // Listener when a font size is changed
\r
1084 @SuppressWarnings("unused")
\r
1085 private void fontSizeChanged(String font) {
\r
1086 String text = browser.selectedText();
\r
1087 if (text.trim().equalsIgnoreCase(""))
\r
1090 String selectedText = browser.selectedText();
\r
1091 String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";
\r
1092 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1093 browser.page().mainFrame().evaluateJavaScript(script);
\r
1094 /* browser.page().mainFrame().evaluateJavaScript(
\r
1095 "document.execCommand('fontSize',false,'"
\r
1098 browser.setFocus();
\r
1101 // Load the font combo box based upon the font selected
\r
1102 private void loadFontSize(String name) {
\r
1103 QFontDatabase db = new QFontDatabase();
\r
1105 List<Integer> points = db.pointSizes(name);
\r
1106 for (int i=0; i<points.size(); i++) {
\r
1107 fontSize.addItem(points.get(i).toString());
\r
1110 fontSize.addItem("x-small");
\r
1111 fontSize.addItem("small");
\r
1112 fontSize.addItem("medium");
\r
1113 fontSize.addItem("large");
\r
1114 fontSize.addItem("x-large");
\r
1115 fontSize.addItem("xx-large");
\r
1116 fontSize.addItem("xxx-large");
\r
1120 // Listener when a font size is changed
\r
1121 @SuppressWarnings("unused")
\r
1122 private void fontColorClicked() {
\r
1123 // QColorDialog dialog = new QColorDialog();
\r
1124 // QColor color = QColorDialog.getColor();
\r
1125 QColor color = fontColorMenu.getColor();
\r
1126 if (color.isValid())
\r
1127 browser.page().mainFrame().evaluateJavaScript(
\r
1128 "document.execCommand('foreColor',false,'" + color.name()
\r
1130 browser.setFocus();
\r
1133 // Listener for when a background color change is requested
\r
1134 @SuppressWarnings("unused")
\r
1135 private void fontHilightClicked() {
\r
1136 // QColorDialog dialog = new QColorDialog();
\r
1137 // QColor color = QColorDialog.getColor();
\r
1138 QColor color = fontHilightColorMenu.getColor();
\r
1139 if (color.isValid())
\r
1140 browser.page().mainFrame().evaluateJavaScript(
\r
1141 "document.execCommand('backColor',false,'" + color.name()
\r
1143 browser.setFocus();
\r
1146 // Listener for when a background color change is requested
\r
1147 @SuppressWarnings("unused")
\r
1148 private void superscriptClicked() {
\r
1149 browser.page().mainFrame().evaluateJavaScript(
\r
1150 "document.execCommand('superscript');");
\r
1151 browser.setFocus();
\r
1154 // Listener for when a background color change is requested
\r
1155 @SuppressWarnings("unused")
\r
1156 private void subscriptClicked() {
\r
1157 browser.page().mainFrame().evaluateJavaScript(
\r
1158 "document.execCommand('subscript');");
\r
1159 browser.setFocus();
\r
1161 // Insert a to-do checkbox
\r
1162 @SuppressWarnings("unused")
\r
1163 private void todoClicked() {
\r
1164 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1165 String script_start = new String(
\r
1166 "document.execCommand('insertHtml', false, '");
\r
1167 String script_end = new String("');");
\r
1168 String todo = new String(
\r
1169 "<input TYPE=\"CHECKBOX\" value=\"false\" onClick=\"value=checked; window.jambi.contentChanged(); \" />");
\r
1170 browser.page().mainFrame().evaluateJavaScript(
\r
1171 script_start + todo + script_end);
\r
1172 browser.setFocus();
\r
1175 // Encrypt the selected text
\r
1176 @SuppressWarnings("unused")
\r
1177 private void encryptText() {
\r
1178 String text = browser.selectedText();
\r
1179 if (text.trim().equalsIgnoreCase(""))
\r
1182 EnCryptDialog dialog = new EnCryptDialog();
\r
1184 if (!dialog.okPressed()) {
\r
1188 EnCrypt crypt = new EnCrypt();
\r
1189 String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);
\r
1191 if (encrypted.trim().equals("")) {
\r
1192 QMessageBox.information(this, tr("Error"), tr("Error Encrypting String"));
\r
1195 StringBuffer buffer = new StringBuffer(encrypted.length() + 100);
\r
1196 buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""
\r
1197 + dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");
\r
1198 buffer.append("contentEditable=\"false\" alt=\"");
\r
1199 buffer.append(encrypted);
\r
1200 // NFC FIXME: should this be a file URL like in handleLocalAttachment and importAttachment?
\r
1201 buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png") +"\""));
\r
1202 Global.cryptCounter++;
\r
1203 buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");
\r
1204 buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");
\r
1205 buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString()
\r
1206 +"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&apos;")+"\\');\"");
\r
1207 buffer.append("style=\"display:block\" />");
\r
1209 String script_start = new String(
\r
1210 "document.execCommand('insertHtml', false, '");
\r
1211 String script_end = new String("');");
\r
1212 browser.page().mainFrame().evaluateJavaScript(
\r
1213 script_start + buffer.toString() + script_end);
\r
1217 // Insert a hyperlink
\r
1218 public void insertLink() {
\r
1219 logger.log(logger.EXTREME, "Inserting link");
\r
1220 String text = browser.selectedText();
\r
1221 if (text.trim().equalsIgnoreCase(""))
\r
1224 InsertLinkDialog dialog = new InsertLinkDialog();
\r
1225 if (currentHyperlink != null && currentHyperlink != "") {
\r
1226 dialog.setUrl(currentHyperlink);
\r
1229 if (!dialog.okPressed()) {
\r
1230 logger.log(logger.EXTREME, "Insert link canceled");
\r
1233 if (browser.insertLinkAction.text().equalsIgnoreCase("Insert Hyperlink")) {
\r
1234 String selectedText = browser.selectedText();
\r
1235 logger.log(logger.EXTREME, "Inserting link on text "+selectedText);
\r
1236 logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim());
\r
1237 String url = "<a href=\"" +dialog.getUrl().trim()
\r
1238 +"\" title=" +dialog.getUrl().trim()
\r
1239 +" >"+selectedText +"</a>";
\r
1240 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1241 browser.page().mainFrame().evaluateJavaScript(script);
\r
1244 String js = new String( "function getCursorPos() {"
\r
1246 +"if (window.getSelection) {"
\r
1247 +" var selObj = window.getSelection();"
\r
1248 +" var selRange = selObj.getRangeAt(0);"
\r
1249 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1250 +" while(workingNode != null) { "
\r
1251 +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');"
\r
1252 +" workingNode = workingNode.parentNode;"
\r
1255 +"} getCursorPos();");
\r
1256 browser.page().mainFrame().evaluateJavaScript(js);
\r
1263 public void insertTable() {
\r
1264 TableDialog dialog = new TableDialog();
\r
1266 if (!dialog.okPressed()) {
\r
1270 int cols = dialog.getCols();
\r
1271 int rows = dialog.getRows();
\r
1272 int width = dialog.getWidth();
\r
1273 boolean percent = dialog.isPercent();
\r
1275 String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();
\r
1277 newHTML = newHTML +"%";
\r
1278 newHTML = newHTML + "\"><tbody>";
\r
1280 for (int i=0; i<rows; i++) {
\r
1281 newHTML = newHTML +"<tr>";
\r
1282 for (int j=0; j<cols; j++) {
\r
1283 newHTML = newHTML +"<td> </td>";
\r
1285 newHTML = newHTML +"</tr>";
\r
1287 newHTML = newHTML+"</tbody></table>";
\r
1289 String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";
\r
1290 browser.page().mainFrame().evaluateJavaScript(script);
\r
1294 // Text content changed
\r
1295 @SuppressWarnings("unused")
\r
1296 private void selectionChanged() {
\r
1297 browser.encryptAction.setEnabled(true);
\r
1298 browser.insertLinkAction.setEnabled(true);
\r
1299 String scriptStart = "var selection_text = (window.getSelection()).toString();"
\r
1300 + "var range = (window.getSelection()).getRangeAt(0);"
\r
1301 + "var parent_html = range.commonAncestorContainer.innerHTML;"
\r
1302 + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"
\r
1303 + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"
\r
1304 + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"
\r
1305 + "var start = parent_html.indexOf(first_text);"
\r
1306 + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"
\r
1307 + "var value = parent_html.substring(start,end);"
\r
1308 + "window.jambi.saveSelectedText(value);" ;
\r
1309 browser.page().mainFrame().evaluateJavaScript(scriptStart);
\r
1313 public void saveSelectedText(String text) {
\r
1314 boolean enabled = true;
\r
1315 if (text.trim().length() == 0)
\r
1317 if (text.indexOf("en-tag=\"en-crypt\"") >= 0)
\r
1319 if (text.indexOf("<img en-tag=\"en-media\"") >= 0)
\r
1321 if (text.indexOf("<a en-tag=\"en-media\"") >= 0)
\r
1323 if (text.indexOf("<input ") >= 0)
\r
1326 browser.encryptAction.setEnabled(enabled);
\r
1327 browser.insertLinkAction.setEnabled(enabled);
\r
1328 // selectedText = text;
\r
1331 // Decrypt clicked text
\r
1332 public void decryptText(String id, String text, String hint) {
\r
1333 EnCrypt crypt = new EnCrypt();
\r
1334 String plainText = null;
\r
1335 Calendar currentTime = new GregorianCalendar();
\r
1336 Long l = new Long(currentTime.getTimeInMillis());
\r
1337 String slot = new String(Long.toString(l));
\r
1339 // First, try to decrypt with any keys we already have
\r
1340 for (int i=0; i<Global.passwordRemember.size(); i++) {
\r
1341 plainText = crypt.decrypt(text, Global.passwordRemember.get(i), 64);
\r
1342 if (plainText != null) {
\r
1343 slot = new String(Long.toString(l));
\r
1344 Global.passwordSafe.put(slot, Global.passwordRemember.get(i));
\r
1345 removeEncryption(id, plainText, false, slot);
\r
1351 EnDecryptDialog dialog = new EnDecryptDialog();
\r
1352 dialog.setHint(hint);
\r
1353 while (plainText == null || !dialog.okPressed()) {
\r
1355 if (!dialog.okPressed()) {
\r
1358 plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);
\r
1359 if (plainText == null) {
\r
1360 QMessageBox.warning(this, "Incorrect Password", "The password entered is not correct");
\r
1363 Global.passwordSafe.put(slot, dialog.getPassword());
\r
1364 removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);
\r
1365 if (dialog.rememberPassword())
\r
1366 Global.passwordRemember.add(dialog.getPassword());
\r
1370 // Get the editor tag line
\r
1371 public TagLineEdit getTagLine() {
\r
1375 // Modify a note's tags
\r
1376 @SuppressWarnings("unused")
\r
1377 private void modifyTags() {
\r
1378 TagAssign tagWindow = new TagAssign(allTags, currentTags);
\r
1380 if (tagWindow.okClicked()) {
\r
1381 currentTags.clear();
\r
1382 StringBuffer tagDisplay = new StringBuffer();
\r
1384 List<QListWidgetItem> newTags = tagWindow.getTagList()
\r
1386 for (int i = 0; i < newTags.size(); i++) {
\r
1387 currentTags.add(newTags.get(i).text());
\r
1388 tagDisplay.append(newTags.get(i).text());
\r
1389 if (i < newTags.size() - 1) {
\r
1390 tagDisplay.append(Global.tagDelimeter + " ");
\r
1393 tagEdit.setText(tagDisplay.toString());
\r
1394 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1398 // Tag line has been modified by typing text
\r
1399 @SuppressWarnings("unused")
\r
1400 private void modifyTagsTyping() {
\r
1401 String completionText = "";
\r
1402 if (tagEdit.currentCompleterSelection != null && !tagEdit.currentCompleterSelection.equals("")) {
\r
1403 completionText = tagEdit.currentCompleterSelection;
\r
1404 tagEdit.currentCompleterSelection = "";
\r
1407 if (tagEdit.text().equalsIgnoreCase(saveTagList))
\r
1410 // We know something has changed...
\r
1411 String oldTagArray[] = saveTagList.split(Global.tagDelimeter);
\r
1412 String newTagArray[] = tagEdit.text().split(Global.tagDelimeter);
\r
1414 if (!completionText.equals("") && newTagArray.length > 0) {
\r
1415 newTagArray[newTagArray.length-1] = completionText;
\r
1417 // Remove any potential duplicates from the new list
\r
1418 for (int i=0; i<newTagArray.length; i++) {
\r
1419 boolean foundOnce = false;
\r
1420 for (int j=0; j<newTagArray.length; j++) {
\r
1421 if (newTagArray[j].equalsIgnoreCase(newTagArray[i])) {
\r
1425 newTagArray[j] = "";
\r
1430 List<String> newTagList = new ArrayList<String>();
\r
1431 List<String> oldTagList = new ArrayList<String>();
\r
1433 for (int i = 0; i < oldTagArray.length; i++)
\r
1434 if (!oldTagArray[i].trim().equals(""))
\r
1435 oldTagList.add(oldTagArray[i]);
\r
1436 for (int i = 0; i < newTagArray.length; i++)
\r
1437 if (!newTagArray[i].trim().equals(""))
\r
1438 newTagList.add(newTagArray[i]);
\r
1440 // Let's cleanup the appearance of the tag list
\r
1441 Collections.sort(newTagList);
\r
1442 String newDisplay = "";
\r
1443 for (int i=0; i<newTagList.size(); i++) {
\r
1444 newDisplay = newDisplay+newTagList.get(i);
\r
1445 if (i<newTagList.size()-1)
\r
1446 newDisplay = newDisplay+", ";
\r
1448 tagEdit.blockSignals(true);
\r
1449 tagEdit.setText(newDisplay);
\r
1450 tagEdit.blockSignals(false);
\r
1452 // We now have lists of the new & old. Remove duplicates. If all
\r
1453 // are removed from both then nothing has really changed
\r
1454 for (int i = newTagList.size() - 1; i >= 0; i--) {
\r
1455 String nTag = newTagList.get(i);
\r
1456 for (int j = oldTagList.size() - 1; j >= 0; j--) {
\r
1457 String oTag = oldTagList.get(j);
\r
1458 if (oTag.equalsIgnoreCase(nTag)) {
\r
1459 oldTagList.remove(j);
\r
1460 newTagList.remove(i);
\r
1466 if (oldTagList.size() != 0 || newTagList.size() != 0) {
\r
1467 currentTags.clear();
\r
1468 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1469 for (int i = 0; i < newTagArray.length; i++)
\r
1470 if (!newTagArray[i].trim().equals(""))
\r
1471 currentTags.add(newTagArray[i].trim());
\r
1473 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1478 // Tab button was pressed
\r
1479 public void tabPressed() {
\r
1480 if (!insideList) {
\r
1481 String script_start = new String(
\r
1482 "document.execCommand('insertHtml', false, ' ');");
\r
1483 browser.page().mainFrame().evaluateJavaScript(script_start);
\r
1488 public void backtabPressed() {
\r
1493 public void setInsideList() {
\r
1494 insideList = true;
\r
1497 // The title has been edited
\r
1498 @SuppressWarnings("unused")
\r
1499 private void titleEdited() {
\r
1500 // If we don't have a good note, or if the current title
\r
1501 // matches the old title then we don't need to do anything
\r
1502 if (currentNote == null)
\r
1504 if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))
\r
1507 // If we have a real change, we need to save it.
\r
1508 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text());
\r
1509 currentNote.setTitle(titleLabel.text());
\r
1510 saveNoteTitle = titleLabel.text();
\r
1514 // Set the list of note tags
\r
1515 public void setAllTags(List<Tag> l) {
\r
1517 tagEdit.setTagList(l);
\r
1520 // Setter for the current tags
\r
1521 public void setCurrentTags(List<String> s) {
\r
1525 // Save the list of notebooks
\r
1526 public void setNotebookList(List<Notebook> n) {
\r
1528 loadNotebookList();
\r
1531 // Load the notebook list and select the current notebook
\r
1532 private void loadNotebookList() {
\r
1533 if (notebookBox.count() != 0)
\r
1534 notebookBox.clear();
\r
1535 if (notebookList == null)
\r
1538 for (int i = 0; i < notebookList.size(); i++) {
\r
1539 notebookBox.addItem(notebookList.get(i).getName());
\r
1540 if (currentNote != null) {
\r
1541 if (currentNote.getNotebookGuid().equals(
\r
1542 notebookList.get(i).getGuid())) {
\r
1543 notebookBox.setCurrentIndex(i);
\r
1549 // Get the contents of the editor
\r
1550 public String getContent() {
\r
1551 return browser.page().currentFrame().toHtml();
\r
1554 // The note contents have changed
\r
1555 public void contentChanged() {
\r
1556 String content = getContent();
\r
1558 noteSignal.noteChanged.emit(currentNote.getGuid(), content);
\r
1561 // The notebook selection has changed
\r
1562 @SuppressWarnings("unused")
\r
1563 private void notebookChanged() {
\r
1564 boolean changed = false;
\r
1565 String n = notebookBox.currentText();
\r
1566 for (int i = 0; i < notebookList.size(); i++) {
\r
1567 if (n.equals(notebookList.get(i).getName())) {
\r
1568 if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {
\r
1569 currentNote.setNotebookGuid(notebookList.get(i).getGuid());
\r
1572 i = notebookList.size();
\r
1576 // If the notebook changed, signal the update
\r
1578 noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote
\r
1579 .getNotebookGuid());
\r
1582 // Check the note title
\r
1583 private void checkNoteTitle() {
\r
1584 String text = browser.page().currentFrame().toPlainText();
\r
1585 if (saveNoteTitle.trim().equals("")) {
\r
1586 int newLine = text.indexOf("\n");
\r
1587 if (newLine > 0) {
\r
1588 text = text.substring(0, newLine);
\r
1589 if (text.trim().equals(""))
\r
1590 text = tr("Untitled Note");
\r
1591 titleLabel.setText(text);
\r
1593 if (text.length() > 20)
\r
1594 titleLabel.setText(text.substring(0, 20));
\r
1596 if (text.trim().equals(""))
\r
1597 titleLabel.setText(tr("Untitled Note"));
\r
1599 titleLabel.setText(text);
\r
1602 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel
\r
1607 // Return the note contents so we can email them
\r
1608 public String getContentsToEmail() {
\r
1609 return browser.page().currentFrame().toPlainText().trim();
\r
1611 * int body = browser.page().currentFrame().toHtml().indexOf("<body>");
\r
1612 * String temp = browser.page().currentFrame().toHtml(); if (body == -1)
\r
1613 * temp = "<html><body><b>Test</b></body></html>"; else temp =
\r
1614 * "<html>"+temp.substring(body); return temp; // return
\r
1615 * urlEncode(browser.page().currentFrame().toHtml());
\r
1619 // Insert an image into the editor
\r
1620 private void insertImage(QMimeData mime) {
\r
1621 logger.log(logger.EXTREME, "Entering insertImage");
\r
1622 QImage img = (QImage) mime.imageData();
\r
1623 String script_start = new String(
\r
1624 "document.execCommand('insertHTML', false, '");
\r
1625 String script_end = new String("');");
\r
1627 long now = new Date().getTime();
\r
1628 String path = Global.getFileManager().getResDirPath(
\r
1629 (new Long(now).toString()) + ".jpg");
\r
1631 // This block is just a hack to make sure we wait at least 1ms so we
\r
1633 // have collisions on image names
\r
1634 long i = new Date().getTime();
\r
1636 i = new Date().getTime();
\r
1638 // Open the file & write the data
\r
1639 QFile tfile = new QFile(path);
\r
1640 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1644 Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);
\r
1645 if (newRes == null)
\r
1647 currentNote.getResources().add(newRes);
\r
1649 // do the actual insert into the note
\r
1650 StringBuffer buffer = new StringBuffer(100);
\r
1651 buffer.append("<img src=\"");
\r
1652 buffer.append(tfile.fileName());
\r
1653 buffer.append("\" en-tag=en-media type=\"image/jpeg\""
\r
1654 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1655 +" guid=\"" +newRes.getGuid() +"\""
\r
1656 // +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1657 +" onContextMenu=\"window.jambi.imageContextMenu(&." +tfile.fileName() +"&.);\""
\r
1660 browser.page().mainFrame().evaluateJavaScript(
\r
1661 script_start + buffer + script_end);
\r
1666 // Handle URLs that are trying to be pasted
\r
1667 public void handleUrls(QMimeData mime) {
\r
1668 logger.log(logger.EXTREME, "Starting handleUrls");
\r
1669 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1671 List<QUrl> urlList = mime.urls();
\r
1672 String url = new String();
\r
1673 String script_start = new String(
\r
1674 "document.execCommand('createLink', false, '");
\r
1675 String script_end = new String("');");
\r
1677 for (int i = 0; i < urlList.size(); i++) {
\r
1678 url = urlList.get(i).toString();
\r
1679 // Find out what type of file we have
\r
1680 String mimeType = fileNameMap.getContentTypeFor(url);
\r
1682 // If null returned, we need to guess at the file type
\r
1683 if (mimeType == null)
\r
1684 mimeType = "application/"
\r
1685 + url.substring(url.lastIndexOf(".") + 1);
\r
1687 // Check if we have an image or some other type of file
\r
1688 if (url.substring(0, 5).equalsIgnoreCase("file:")
\r
1689 && mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1690 handleLocalImageURLPaste(mime, mimeType);
\r
1693 String[] type = mimeType.split("/");
\r
1694 boolean valid = validAttachment(type[1]);
\r
1695 boolean smallEnough = checkFileAttachmentSize(url);
\r
1696 if (smallEnough && valid
\r
1697 && url.substring(0, 5).equalsIgnoreCase("file:")
\r
1698 && !mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1699 handleLocalAttachment(mime, mimeType);
\r
1702 browser.page().mainFrame().evaluateJavaScript(
\r
1703 script_start + url + script_end);
\r
1708 // If a URL being pasted is an image URL, then attach the image
\r
1709 private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {
\r
1710 List<QUrl> urlList = mime.urls();
\r
1711 String url = new String();
\r
1712 String script_start_image = new String(
\r
1713 "document.execCommand('insertHtml', false, '");
\r
1714 String script_end = new String("');");
\r
1715 StringBuffer buffer;
\r
1717 // Copy the image over into the resource directory and create a new resource
\r
1718 // record for each url pasted
\r
1719 for (int i = 0; i < urlList.size(); i++) {
\r
1720 url = urlList.get(i).toString();
\r
1722 Resource newRes = createResource(url, i, mimeType, false);
\r
1723 if (newRes == null)
\r
1725 currentNote.getResources().add(newRes);
\r
1726 buffer = new StringBuffer(100);
\r
1728 // Open the file & write the data
\r
1729 String fileName = Global.getFileManager().getResDirPath(newRes.getGuid());
\r
1730 QFile tfile = new QFile(fileName);
\r
1731 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1732 tfile.write(newRes.getData().getBody());
\r
1734 buffer.append(script_start_image);
\r
1735 buffer.append("<img src=\"" + FileUtils.toForwardSlashedPath(fileName));
\r
1736 // if (mimeType.equalsIgnoreCase("image/jpg"))
\r
1737 // mimeType = "image/jpeg";
\r
1738 buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""
\r
1739 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1740 +" guid=\"" +newRes.getGuid() +"\""
\r
1741 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1743 buffer.append(script_end);
\r
1744 browser.page().mainFrame().evaluateJavaScript(buffer.toString());
\r
1750 // If a URL being pasted is a local file URL, then attach the file
\r
1751 private void handleLocalAttachment(QMimeData mime, String mimeType) {
\r
1752 logger.log(logger.EXTREME, "Attaching local file");
\r
1753 List<QUrl> urlList = mime.urls();
\r
1754 String script_start = new String(
\r
1755 "document.execCommand('insertHtml', false, '");
\r
1756 String script_end = new String("');");
\r
1757 StringBuffer buffer;
\r
1759 String[] type = mimeType.split("/");
\r
1760 String icon = findIcon(type[1]);
\r
1761 if (icon.equals("attachment.png"))
\r
1762 icon = findIcon(type[0]);
\r
1763 buffer = new StringBuffer(100);
\r
1765 for (int i = 0; i < urlList.size(); i++) {
\r
1766 String url = urlList.get(i).toString();
\r
1768 // Start building the HTML
\r
1769 if (icon.equals("attachment.png"))
\r
1770 icon = findIcon(url.substring(url.lastIndexOf(".")+1));
\r
1771 String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));
\r
1773 logger.log(logger.EXTREME, "Creating resource ");
\r
1774 Resource newRes = createResource(url, i, mimeType, true);
\r
1775 if (newRes == null)
\r
1777 logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());
\r
1778 currentNote.getResources().add(newRes);
\r
1780 String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();
\r
1781 // If we have a PDF, we need to setup the preview.
\r
1782 if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {
\r
1783 logger.log(logger.EXTREME, "Setting up PDF preview");
\r
1784 if (newRes.getAttributes() != null &&
\r
1785 newRes.getAttributes().getFileName() != null &&
\r
1786 !newRes.getAttributes().getFileName().trim().equals(""))
\r
1787 fileName = newRes.getGuid()+Global.attachmentNameDelimeter+
\r
1788 newRes.getAttributes().getFileName();
\r
1790 fileName = newRes.getGuid()+".pdf";
\r
1791 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
1792 QFile.OpenMode mode = new QFile.OpenMode();
\r
1793 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
1795 QDataStream out = new QDataStream(file);
\r
1796 // Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);
\r
1797 QByteArray binData = new QByteArray(newRes.getData().getBody());
\r
1798 // resBinary = null;
\r
1799 out.writeBytes(binData.toByteArray());
\r
1802 PDFPreview pdfPreview = new PDFPreview();
\r
1803 if (pdfPreview.setupPreview(Global.getFileManager().getResDirPath(fileName), "pdf",0)) {
\r
1804 // NFC TODO: should this be a 'file://' url like the ones above?
\r
1805 imageURL = file.fileName() + ".png";
\r
1809 logger.log(logger.EXTREME, "Generating link tags");
\r
1810 buffer.delete(0, buffer.length());
\r
1811 buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");
\r
1812 buffer.append(" onContextMenu=\"window.jambi.imageContextMenu('")
\r
1813 .append(Global.getFileManager().getResDirPath(fileName))
\r
1814 .append("');\" "); buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");
\r
1815 buffer.append("<img src=\"" + imageURL + "\" title=\"" +newRes.getAttributes().getFileName());
\r
1816 buffer.append("\"></img>");
\r
1817 buffer.append("</a>");
\r
1818 browser.page().mainFrame().evaluateJavaScript(
\r
1819 script_start + buffer.toString() + script_end);
\r
1824 private Resource createResource(String url, int sequence, String mime, boolean attachment) {
\r
1825 logger.log(logger.EXTREME, "Inside create resource");
\r
1826 QFile resourceFile;
\r
1827 String urlTest = new QUrl(url).toLocalFile();
\r
1828 if (!urlTest.equals(""))
\r
1830 url = url.replace("/", File.separator);
\r
1831 resourceFile = new QFile(url);
\r
1832 resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));
\r
1833 byte[] fileData = resourceFile.readAll().toByteArray();
\r
1834 resourceFile.close();
\r
1835 if (fileData.length == 0)
\r
1839 md = MessageDigest.getInstance("MD5");
\r
1840 md.update(fileData);
\r
1841 byte[] hash = md.digest();
\r
1843 Resource r = new Resource();
\r
1844 Calendar time = new GregorianCalendar();
\r
1845 long prevTime = time.getTimeInMillis();
\r
1846 while (prevTime == time.getTimeInMillis()) {
\r
1847 time = new GregorianCalendar();
\r
1849 r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());
\r
1850 r.setNoteGuid(currentNote.getGuid());
\r
1852 r.setActive(true);
\r
1853 r.setUpdateSequenceNum(0);
\r
1854 r.setWidth((short) 0);
\r
1855 r.setHeight((short) 0);
\r
1856 r.setDuration((short) 0);
\r
1858 Data d = new Data();
\r
1859 d.setBody(fileData);
\r
1860 d.setBodyIsSet(true);
\r
1861 d.setBodyHash(hash);
\r
1862 d.setBodyHashIsSet(true);
\r
1864 d.setSize(fileData.length);
\r
1866 int fileNamePos = url.lastIndexOf(File.separator);
\r
1867 if (fileNamePos == -1)
\r
1868 fileNamePos = url.lastIndexOf("/");
\r
1869 String fileName = url.substring(fileNamePos+1);
\r
1870 ResourceAttributes a = new ResourceAttributes();
\r
1872 a.setAltitudeIsSet(false);
\r
1873 a.setLongitude(0);
\r
1874 a.setLongitudeIsSet(false);
\r
1876 a.setLatitudeIsSet(false);
\r
1877 a.setCameraMake("");
\r
1878 a.setCameraMakeIsSet(false);
\r
1879 a.setCameraModel("");
\r
1880 a.setCameraModelIsSet(false);
\r
1881 a.setAttachment(attachment);
\r
1882 a.setAttachmentIsSet(true);
\r
1883 a.setClientWillIndex(false);
\r
1884 a.setClientWillIndexIsSet(true);
\r
1885 a.setRecoType("");
\r
1886 a.setRecoTypeIsSet(false);
\r
1887 a.setSourceURL(url);
\r
1888 a.setSourceURLIsSet(true);
\r
1889 a.setTimestamp(0);
\r
1890 a.setTimestampIsSet(false);
\r
1891 a.setFileName(fileName);
\r
1892 a.setFileNameIsSet(true);
\r
1893 r.setAttributes(a);
\r
1895 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
1897 } catch (NoSuchAlgorithmException e1) {
\r
1898 e1.printStackTrace();
\r
1904 // find the appropriate icon for an attachment
\r
1905 private String findIcon(String appl) {
\r
1906 appl = appl.toLowerCase();
\r
1907 File f = Global.getFileManager().getImageDirFile(appl + ".png");
\r
1909 return appl+".png";
\r
1910 return "attachment.png";
\r
1913 // Check if the account supports this type of attachment
\r
1914 private boolean validAttachment(String type) {
\r
1915 if (Global.isPremium())
\r
1917 if (type.equalsIgnoreCase("JPG"))
\r
1919 if (type.equalsIgnoreCase("PNG"))
\r
1921 if (type.equalsIgnoreCase("GIF"))
\r
1923 if (type.equalsIgnoreCase("MP3"))
\r
1925 if (type.equalsIgnoreCase("WAV"))
\r
1927 if (type.equalsIgnoreCase("AMR"))
\r
1929 if (type.equalsIgnoreCase("PDF"))
\r
1931 String error = tr("Non-premium accounts can only attach JPG, PNG, GIF, MP3, WAV, AMR, or PDF files.");
\r
1932 QMessageBox.information(this, tr("Non-Premium Account"), error);
\r
1937 // Check the file attachment to be sure it isn't over 25 mb
\r
1938 private boolean checkFileAttachmentSize(String url) {
\r
1939 String fileName = url.substring(8);
\r
1940 QFile resourceFile = new QFile(fileName);
\r
1941 resourceFile.open(new QIODevice.OpenMode(
\r
1942 QIODevice.OpenModeFlag.ReadOnly));
\r
1943 long size = resourceFile.size();
\r
1944 resourceFile.close();
\r
1945 size = size / 1024 / 1024;
\r
1946 if (size < 50 && Global.isPremium())
\r
1951 String error = tr("A file attachment may not exceed 25MB.");
\r
1952 QMessageBox.information(this, tr("Attachment Size"), error);
\r
1957 @SuppressWarnings("unused")
\r
1958 private void createdChanged() {
\r
1959 QDateTime dt = new QDateTime();
\r
1960 dt.setDate(createdDate.date());
\r
1961 dt.setTime(createdTime.time());
\r
1962 noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);
\r
1966 @SuppressWarnings("unused")
\r
1967 private void alteredChanged() {
\r
1968 QDateTime dt = new QDateTime();
\r
1969 dt.setDate(alteredDate.date());
\r
1970 dt.setTime(alteredTime.time());
\r
1971 noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);
\r
1974 @SuppressWarnings("unused")
\r
1975 private void subjectDateTimeChanged() {
\r
1976 QDateTime dt = new QDateTime();
\r
1977 dt.setDate(subjectDate.date());
\r
1978 dt.setTime(subjectTime.time());
\r
1979 noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);
\r
1983 @SuppressWarnings("unused")
\r
1984 private void sourceUrlChanged() {
\r
1985 noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());
\r
1988 @SuppressWarnings("unused")
\r
1989 private void authorChanged() {
\r
1990 noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());
\r
1993 @SuppressWarnings("unused")
\r
1994 private void geoBoxChanged() {
\r
1995 int index = geoBox.currentIndex();
\r
1996 geoBox.setCurrentIndex(0);
\r
1998 GeoDialog box = new GeoDialog();
\r
1999 box.setLongitude(currentNote.getAttributes().getLongitude());
\r
2000 box.setLatitude(currentNote.getAttributes().getLatitude());
\r
2001 box.setAltitude(currentNote.getAttributes().getAltitude());
\r
2003 if (!box.okPressed())
\r
2005 double alt = box.getAltitude();
\r
2006 double lat = box.getLatitude();
\r
2007 double lon = box.getLongitude();
\r
2008 if (alt != currentNote.getAttributes().getAltitude() ||
\r
2009 lon != currentNote.getAttributes().getLongitude() ||
\r
2010 lat != currentNote.getAttributes().getLatitude()) {
\r
2011 noteSignal.geoChanged.emit(currentNote.getGuid(), lon, lat, alt);
\r
2012 currentNote.getAttributes().setAltitude(alt);
\r
2013 currentNote.getAttributes().setLongitude(lon);
\r
2014 currentNote.getAttributes().setLatitude(lat);
\r
2019 noteSignal.geoChanged.emit(currentNote.getGuid(), 0.0, 0.0, 0.0);
\r
2020 currentNote.getAttributes().setAltitude(0.0);
\r
2021 currentNote.getAttributes().setLongitude(0.0);
\r
2022 currentNote.getAttributes().setLatitude(0.0);
\r
2025 if (index == 3 || index == 0) {
\r
2026 QDesktopServices.openUrl(new QUrl("http://maps.google.com/maps?z=6&q="+currentNote.getAttributes().getLatitude() +"," +currentNote.getAttributes().getLongitude()));
\r
2030 // ************************************************************
\r
2031 // * User chose to save an attachment. Pares out the request *
\r
2032 // * into a guid & file. Save the result. *
\r
2033 // ************************************************************
\r
2034 public void downloadAttachment(QNetworkRequest request) {
\r
2036 QFileDialog fd = new QFileDialog(this);
\r
2037 fd.setFileMode(FileMode.AnyFile);
\r
2038 fd.setConfirmOverwrite(true);
\r
2039 fd.setWindowTitle(tr("Save File"));
\r
2040 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2041 fd.setDirectory(System.getProperty("user.home"));
\r
2042 String name = request.url().toString();
\r
2044 int pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2046 guid = name.substring(0, pos).replace("nnres://", "");
\r
2047 name = name.substring(pos +Global.attachmentNameDelimeter.length());
\r
2048 fd.selectFile(name);
\r
2049 pos = name.lastIndexOf('.');
\r
2051 String mimeType = "(*." + name.substring(pos + 1)
\r
2052 + ");; All Files (*)";
\r
2053 fd.setFilter(tr(mimeType));
\r
2059 // Strip URL prefix and base dir
\r
2060 guid = guid.replace("nnres://", "")
\r
2061 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2063 pos = guid.lastIndexOf('.');
\r
2065 guid = guid.substring(0,pos);
\r
2066 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2067 name = name.replace('\\', '/');
\r
2068 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2069 QFile saveFile = new QFile(fd.selectedFiles().get(0));
\r
2070 QFile.OpenMode mode = new QFile.OpenMode();
\r
2071 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2072 saveFile.open(mode);
\r
2073 QDataStream saveOut = new QDataStream(saveFile);
\r
2074 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2075 saveOut.writeBytes(binData.toByteArray());
\r
2082 // ************************************************************
\r
2083 // * User chose to save an attachment. Pares out the request *
\r
2084 // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!
\r
2085 // ************************************************************
\r
2086 // NFC TODO: unused? remove
\r
2087 public void downloadImage(QNetworkRequest request) {
\r
2088 QFileDialog fd = new QFileDialog(this);
\r
2089 fd.setFileMode(FileMode.AnyFile);
\r
2090 fd.setConfirmOverwrite(true);
\r
2091 fd.setWindowTitle(tr("Save File"));
\r
2092 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2093 fd.setDirectory(System.getProperty("user.home"));
\r
2094 String name = request.url().toString();
\r
2095 name = name.replace("nnres://", "");
\r
2096 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
\r
2097 name = name.replace(dPath, "");
\r
2098 int pos = name.lastIndexOf('.');
\r
2099 String guid = name;
\r
2101 String mimeType = "(*." + name.substring(pos + 1)
\r
2102 + ");; All Files (*)";
\r
2103 fd.setFilter(tr(mimeType));
\r
2104 guid = guid.substring(0,pos);
\r
2106 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2108 guid = name.substring(0, pos);
\r
2109 fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));
\r
2111 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2112 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2113 String fileName = fd.selectedFiles().get(0);
\r
2114 QFile saveFile = new QFile(fileName);
\r
2115 QFile.OpenMode mode = new QFile.OpenMode();
\r
2116 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2117 saveFile.open(mode);
\r
2118 QDataStream saveOut = new QDataStream(saveFile);
\r
2119 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2120 saveOut.writeBytes(binData.toByteArray());
\r
2126 // *************************************************************
\r
2127 // * decrypt any hidden text. We could do an XML parse, but
\r
2128 // * it is quicker here just to scan for an <img tag & do the fix
\r
2129 // * the manual way
\r
2130 // *************************************************************
\r
2131 private void removeEncryption(String id, String plainText, boolean permanent, String slot) {
\r
2133 plainText = " <en-crypt-temp slot=\""+slot +"\">" +plainText+"</en-crypt-temp> ";
\r
2136 String html = browser.page().mainFrame().toHtml();
\r
2137 String text = html;
\r
2138 int imagePos = html.indexOf("<img");
\r
2140 for ( ;imagePos>0; ) {
\r
2141 // Find the end tag
\r
2142 endPos = text.indexOf(">", imagePos);
\r
2143 String tag = text.substring(imagePos-1,endPos);
\r
2144 if (tag.indexOf("id=\""+id+"\"") > -1) {
\r
2145 text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);
\r
2147 browser.setContent(new QByteArray(text));
\r
2150 imagePos = text.indexOf("<img", imagePos+1);
\r
2155 //****************************************************************
\r
2156 //* Focus shortcuts
\r
2157 //****************************************************************
\r
2158 @SuppressWarnings("unused")
\r
2159 private void focusTitle() {
\r
2160 titleLabel.setFocus();
\r
2162 @SuppressWarnings("unused")
\r
2163 private void focusTag() {
\r
2164 tagEdit.setFocus();
\r
2166 @SuppressWarnings("unused")
\r
2167 private void focusNote() {
\r
2168 browser.setFocus();
\r
2170 @SuppressWarnings("unused")
\r
2171 private void focusAuthor() {
\r
2172 authorLabel.setFocus();
\r
2174 @SuppressWarnings("unused")
\r
2175 private void focusUrl() {
\r
2176 urlLabel.setFocus();
\r
2180 //*****************************************************************
\r
2181 //* Set the document background color
\r
2182 //*****************************************************************
\r
2183 public void setBackgroundColor(String color) {
\r
2184 String js = "function changeBackground(color) {"
\r
2185 +"document.body.style.background = color;"
\r
2187 +"changeBackground('" +color+"');";
\r
2188 browser.page().mainFrame().evaluateJavaScript(js);
\r
2193 //****************************************************************
\r
2194 //* MicroFocus changed
\r
2195 //****************************************************************
\r
2196 private void microFocusChanged() {
\r
2197 boldButton.setDown(false);
\r
2198 italicButton.setDown(false);
\r
2199 underlineButton.setDown(false);
\r
2200 browser.openAction.setEnabled(false);
\r
2201 browser.downloadAttachment.setEnabled(false);
\r
2202 browser.downloadImage.setEnabled(false);
\r
2203 browser.rotateImageLeft.setEnabled(false);
\r
2204 browser.rotateImageRight.setEnabled(false);
\r
2205 browser.insertTableAction.setEnabled(true);
\r
2206 browser.insertTableRowAction.setEnabled(false);
\r
2207 browser.deleteTableRowAction.setEnabled(false);
\r
2208 browser.insertLinkAction.setText(tr("Insert Hyperlink"));
\r
2209 currentHyperlink ="";
\r
2210 insideList = false;
\r
2211 forceTextPaste = false;
\r
2213 String js = new String( "function getCursorPos() {"
\r
2215 +"if (window.getSelection) {"
\r
2216 +" var selObj = window.getSelection();"
\r
2217 +" var selRange = selObj.getRangeAt(0);"
\r
2218 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2219 +" while(workingNode != null) { "
\r
2220 // +" window.jambi.printNode(workingNode.nodeName);"
\r
2221 +" if (workingNode.nodeName=='EN-CRYPT-TEMP') window.jambi.forceTextPaste();"
\r
2222 +" if (workingNode.nodeName=='B') window.jambi.boldActive();"
\r
2223 +" if (workingNode.nodeName=='I') window.jambi.italicActive();"
\r
2224 +" if (workingNode.nodeName=='U') window.jambi.underlineActive();"
\r
2225 +" if (workingNode.nodeName=='UL') window.jambi.setInsideList();"
\r
2226 +" if (workingNode.nodeName=='OL') window.jambi.setInsideList();"
\r
2227 +" if (workingNode.nodeName=='LI') window.jambi.setInsideList();"
\r
2228 +" if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"
\r
2229 +" 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
2230 +" if (workingNode.nodeName=='SPAN') {"
\r
2231 +" if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"
\r
2233 +" workingNode = workingNode.parentNode;"
\r
2236 +"} getCursorPos();");
\r
2237 browser.page().mainFrame().evaluateJavaScript(js);
\r
2240 public void printNode(String n) {
\r
2241 System.out.println("Node Vaule: " +n);
\r
2245 //****************************************************************
\r
2246 //* Insert a table row
\r
2247 //****************************************************************
\r
2248 public void insertTableRow() {
\r
2250 String js = new String( "function insertTableRow() {"
\r
2251 +" var selObj = window.getSelection();"
\r
2252 +" var selRange = selObj.getRangeAt(0);"
\r
2253 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2254 +" var cellCount = 0;"
\r
2255 +" while(workingNode != null) { "
\r
2256 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2257 +" row = document.createElement('TR');"
\r
2258 +" var nodes = workingNode.getElementsByTagName('td');"
\r
2259 +" for (j=0; j<nodes.length; j=j+1) {"
\r
2260 +" cell = document.createElement('TD');"
\r
2261 +" cell.innerHTML=' ';"
\r
2262 +" row.appendChild(cell);"
\r
2264 +" workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"
\r
2267 +" workingNode = workingNode.parentNode;"
\r
2269 +"} insertTableRow();");
\r
2270 browser.page().mainFrame().evaluateJavaScript(js);
\r
2273 //****************************************************************
\r
2274 //* Insert a table row
\r
2275 //****************************************************************
\r
2276 public void deleteTableRow() {
\r
2278 String js = new String( "function deleteTableRow() {"
\r
2279 +" var selObj = window.getSelection();"
\r
2280 +" var selRange = selObj.getRangeAt(0);"
\r
2281 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2282 +" var cellCount = 0;"
\r
2283 +" while(workingNode != null) { "
\r
2284 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2285 +" workingNode.parentNode.removeChild(workingNode);"
\r
2288 +" workingNode = workingNode.parentNode;"
\r
2290 +"} deleteTableRow();");
\r
2291 browser.page().mainFrame().evaluateJavaScript(js);
\r
2294 public void setInsideTable() {
\r
2295 browser.insertTableRowAction.setEnabled(true);
\r
2296 browser.deleteTableRowAction.setEnabled(true);
\r
2297 browser.insertTableAction.setEnabled(false);
\r
2298 browser.encryptAction.setEnabled(false);
\r
2301 public void setInsideLink(String link) {
\r
2302 browser.insertLinkAction.setText(tr("Edit Hyperlink"));
\r
2303 currentHyperlink = link;
\r
2306 public void italicActive() {
\r
2307 italicButton.setDown(true);
\r
2309 public void boldActive() {
\r
2310 boldButton.setDown(true);
\r
2312 public void underlineActive() {
\r
2313 underlineButton.setDown(true);
\r
2315 public void forceTextPaste() {
\r
2316 forceTextPaste = true;
\r
2318 public void imageContextMenu(String f) {
\r
2319 browser.downloadImage.setEnabled(true);
\r
2320 browser.rotateImageRight.setEnabled(true);
\r
2321 browser.rotateImageLeft.setEnabled(true);
\r
2322 browser.openAction.setEnabled(true);
\r
2325 public void rotateImageRight() {
\r
2326 QWebSettings.setMaximumPagesInCache(0);
\r
2327 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2328 QImage image = new QImage(selectedFile);
\r
2329 QMatrix matrix = new QMatrix();
\r
2330 matrix.rotate( 90.0 );
\r
2331 image = image.transformed(matrix);
\r
2332 image.save(selectedFile);
\r
2333 QWebSettings.setMaximumPagesInCache(0);
\r
2334 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2335 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2338 // resourceSignal.contentChanged.emit(selectedFile);
\r
2341 public void rotateImageLeft() {
\r
2342 QImage image = new QImage(selectedFile);
\r
2343 QMatrix matrix = new QMatrix();
\r
2344 matrix.rotate( -90.0 );
\r
2345 image = image.transformed(matrix);
\r
2346 image.save(selectedFile);
\r
2347 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2350 // resourceSignal.contentChanged.emit(selectedFile);
\r
2352 public void resourceContextMenu(String f) {
\r
2353 browser.downloadAttachment.setEnabled(true);
\r
2354 browser.openAction.setEnabled(true);
\r
2359 //****************************************************************
\r
2360 //* Apply CSS style to specified word
\r
2361 //****************************************************************
\r
2362 /* public void applyStyleToWords(String word, String style) {
\r
2363 QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");
\r
2364 script.open(OpenModeFlag.ReadOnly);
\r
2365 String s = script.readAll().toString();
\r
2366 String js = new String(s +" findit('"+word+"', '"+style+"');");
\r
2367 browser.page().mainFrame().evaluateJavaScript(js);
\r
2368 System.out.println(getContent());
\r
2371 //****************************************************************
\r
2372 //* Someone tried to paste a resource between notes, so we need *
\r
2373 //* to do some special handling. *
\r
2374 //****************************************************************
\r
2375 private String fixInternotePaste(String text) {
\r
2376 logger.log(logger.EXTREME, "Fixing internote paste");
\r
2377 String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");
\r
2378 return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");
\r
2380 private String fixInternotePasteSearch(String text, String type, String locTag) {
\r
2382 // First, let's fix the images.
\r
2383 int startPos = text.indexOf(type);
\r
2385 for (; startPos>=0;) {
\r
2386 endPos = text.indexOf(">", startPos+1);
\r
2387 String segment = text.substring(startPos, endPos);
\r
2388 if (segment.indexOf("en-tag") > -1) {
\r
2389 String newSegment = segment;
\r
2391 int guidStartPos = segment.indexOf("guid=\"");
\r
2392 int guidEndPos = segment.indexOf("\"", guidStartPos+7);
\r
2393 String guid = segment.substring(guidStartPos+6,guidEndPos);
\r
2395 int mimeStartPos = segment.indexOf("type");
\r
2396 int mimeEndPos = segment.indexOf("\"", mimeStartPos+7);
\r
2397 String mime = segment.substring(mimeStartPos+6,mimeEndPos);
\r
2399 int srcStartPos = segment.indexOf("src");
\r
2400 int srcEndPos = segment.indexOf("\"", srcStartPos+6);
\r
2401 String src = segment.substring(srcStartPos+5,srcEndPos);
\r
2403 Calendar currentTime = new GregorianCalendar();
\r
2404 Long l = new Long(currentTime.getTimeInMillis());
\r
2405 long prevTime = l;
\r
2406 while (l==prevTime) {
\r
2407 currentTime = new GregorianCalendar();
\r
2408 l= new Long(currentTime.getTimeInMillis());
\r
2411 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2412 // if r==null, then the image doesn't exist (it was probably cut out of another note, so
\r
2413 // we need to recereate it
\r
2415 r = createResource(src, 1, mime, false);
\r
2419 String randint = new String(Long.toString(l));
\r
2420 String extension = null;
\r
2421 if (r.getMime()!= null) {
\r
2422 extension = r.getMime().toLowerCase();
\r
2423 if (extension.indexOf("/")>-1)
\r
2424 extension = extension.substring(extension.indexOf("/")+1);
\r
2426 String newFile = randint;
\r
2427 if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")
\r
2428 if (!locTag.startsWith("src"))
\r
2429 newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();
\r
2430 r.setNoteGuid(currentNote.getGuid());
\r
2432 r.setGuid(randint);
\r
2433 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
2434 QFile f = new QFile(Global.getFileManager().getResDirPath(newFile));
\r
2435 QByteArray bin = new QByteArray(r.getData().getBody());
\r
2436 f.open(QFile.OpenModeFlag.WriteOnly);
\r
2439 newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);
\r
2440 currentNote.getResources().add(r);
\r
2442 int startSrcPos = newSegment.indexOf(locTag);
\r
2443 int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);
\r
2445 if (locTag.startsWith("src")) {
\r
2446 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2447 newSegment = newSegment.replace(source,
\r
2448 FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath(newFile)));
\r
2450 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2451 newSegment = newSegment.replace(source, newFile);
\r
2454 text = text.substring(0,startPos) + newSegment + text.substring(endPos);
\r
2456 startPos = text.indexOf(type, startPos+1);
\r
2462 public void nextPage(String file) {
\r
2463 logger.log(logger.EXTREME, "Starting nextPage()");
\r
2465 Integer pageNumber;
\r
2466 if (previewPageList.containsKey(file))
\r
2467 pageNumber = previewPageList.get(file)+1;
\r
2470 previewPageList.remove(file);
\r
2471 previewPageList.put(file, pageNumber);
\r
2472 PDFPreview pdfPreview = new PDFPreview();
\r
2473 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2474 if (goodPreview) {
\r
2476 // String html = getContent();
\r
2477 QWebSettings.setMaximumPagesInCache(0);
\r
2478 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2479 // browser.setContent(new QByteArray());
\r
2480 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2482 // browser.setContent(new QByteArray(html));
\r
2483 // browser.triggerPageAction(WebAction.Reload);
\r
2484 // pdfMouseOver(selectedFile);
\r
2488 public void previousPage(String file) {
\r
2489 logger.log(logger.EXTREME, "Starting previousPage()");
\r
2491 Integer pageNumber;
\r
2492 if (previewPageList.containsKey(file))
\r
2493 pageNumber = previewPageList.get(file)-1;
\r
2496 previewPageList.remove(file);
\r
2497 previewPageList.put(file, pageNumber);
\r
2498 PDFPreview pdfPreview = new PDFPreview();
\r
2499 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2500 if (goodPreview) {
\r
2502 // String html = getContent();
\r
2503 QWebSettings.setMaximumPagesInCache(0);
\r
2504 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2505 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2507 // browser.setContent(new QByteArray(html));
\r
2508 // browser.triggerPageAction(WebAction.Reload);
\r
2512 /* public void pdfMouseOver(String name) {
\r
2514 if (previewPageList.containsKey(selectedFile))
\r
2515 pageNumber = previewPageList.get(selectedFile)+1;
\r
2519 if (pageNumber <= 1)
\r
2520 browser.previousPageAction.setEnabled(false);
\r
2522 browser.previousPageAction.setEnabled(true);
\r
2524 PDFPreview pdf = new PDFPreview();
\r
2525 int totalPages = pdf.getPageCount(name);
\r
2526 if (previewPageList.containsKey(selectedFile))
\r
2527 pageNumber = previewPageList.get(selectedFile)+1;
\r
2530 if (totalPages > pageNumber)
\r
2531 browser.nextPageAction.setEnabled(true);
\r
2533 browser.nextPageAction.setEnabled(false);
\r
2537 public void pdfMouseOut() {
\r
2538 // browser.nextPageAction.setVisible(false);
\r
2539 // browser.previousPageAction.setVisible(false);
\r
2543 private void toggleUndoVisible(Boolean toggle) {
\r
2544 undoAction.setVisible(toggle);
\r
2545 Global.saveEditorButtonsVisible("undo", toggle);
\r
2547 private void toggleRedoVisible(Boolean toggle) {
\r
2548 redoAction.setVisible(toggle);
\r
2549 Global.saveEditorButtonsVisible("redo", toggle);
\r
2551 private void toggleCutVisible(Boolean toggle) {
\r
2552 cutAction.setVisible(toggle);
\r
2553 Global.saveEditorButtonsVisible("cut", toggle);
\r
2555 private void toggleCopyVisible(Boolean toggle) {
\r
2556 copyAction.setVisible(toggle);
\r
2557 Global.saveEditorButtonsVisible("copy", toggle);
\r
2559 private void togglePasteVisible(Boolean toggle) {
\r
2560 pasteAction.setVisible(toggle);
\r
2561 Global.saveEditorButtonsVisible("paste", toggle);
\r
2563 private void toggleBoldVisible(Boolean toggle) {
\r
2564 boldAction.setVisible(toggle);
\r
2565 Global.saveEditorButtonsVisible("bold", toggle);
\r
2567 private void toggleItalicVisible(Boolean toggle) {
\r
2568 italicAction.setVisible(toggle);
\r
2569 Global.saveEditorButtonsVisible("italic", toggle);
\r
2571 private void toggleUnderlineVisible(Boolean toggle) {
\r
2572 underlineAction.setVisible(toggle);
\r
2573 Global.saveEditorButtonsVisible("underline", toggle);
\r
2575 private void toggleStrikethroughVisible(Boolean toggle) {
\r
2576 strikethroughAction.setVisible(toggle);
\r
2577 Global.saveEditorButtonsVisible("strikethrough", toggle);
\r
2579 private void toggleLeftAlignVisible(Boolean toggle) {
\r
2580 leftAlignAction.setVisible(toggle);
\r
2581 Global.saveEditorButtonsVisible("alignLeft", toggle);
\r
2583 private void toggleRightAlignVisible(Boolean toggle) {
\r
2584 rightAlignAction.setVisible(toggle);
\r
2585 Global.saveEditorButtonsVisible("alignRight", toggle);
\r
2587 private void toggleCenterAlignVisible(Boolean toggle) {
\r
2588 centerAlignAction.setVisible(toggle);
\r
2589 Global.saveEditorButtonsVisible("alignCenter", toggle);
\r
2591 private void toggleHLineVisible(Boolean toggle) {
\r
2592 hlineAction.setVisible(toggle);
\r
2593 Global.saveEditorButtonsVisible("hline", toggle);
\r
2595 private void toggleIndentVisible(Boolean toggle) {
\r
2596 indentAction.setVisible(toggle);
\r
2597 Global.saveEditorButtonsVisible("indent", toggle);
\r
2599 private void toggleOutdentVisible(Boolean toggle) {
\r
2600 outdentAction.setVisible(toggle);
\r
2601 Global.saveEditorButtonsVisible("outdent", toggle);
\r
2603 private void toggleBulletListVisible(Boolean toggle) {
\r
2604 bulletListAction.setVisible(toggle);
\r
2605 Global.saveEditorButtonsVisible("bulletList", toggle);
\r
2607 private void toggleNumberListVisible(Boolean toggle) {
\r
2608 numberListAction.setVisible(toggle);
\r
2609 Global.saveEditorButtonsVisible("numberList", toggle);
\r
2611 private void toggleFontListVisible(Boolean toggle) {
\r
2612 fontListAction.setVisible(toggle);
\r
2613 Global.saveEditorButtonsVisible("font", toggle);
\r
2615 private void toggleFontColorVisible(Boolean toggle) {
\r
2616 fontColorAction.setVisible(toggle);
\r
2617 Global.saveEditorButtonsVisible("fontColor", toggle);
\r
2619 private void toggleFontSizeVisible(Boolean toggle) {
\r
2620 fontSizeAction.setVisible(toggle);
\r
2621 Global.saveEditorButtonsVisible("fontSize", toggle);
\r
2623 private void toggleFontHilightVisible(Boolean toggle) {
\r
2624 fontHilightAction.setVisible(toggle);
\r
2625 Global.saveEditorButtonsVisible("fontHilight", toggle);
\r
2629 // Invoke spell checker dialog
\r
2630 private void doSpellCheck() {
\r
2632 File wordList = new File(Global.getFileManager().getSpellDirPath()+Locale.getDefault()+".dic");
\r
2633 SpellDictionary dictionary;
\r
2635 dictionary = new SpellDictionaryHashMap(wordList);
\r
2636 SpellChecker spellChecker = new SpellChecker(dictionary);
\r
2637 SuggestionListener spellListener = new SuggestionListener(this);
\r
2638 spellChecker.addSpellCheckListener(spellListener);
\r
2640 String content = getBrowser().page().mainFrame().toPlainText();
\r
2641 StringWordTokenizer tokenizer = new StringWordTokenizer(content);
\r
2642 if (!tokenizer.hasMoreWords())
\r
2644 String word = tokenizer.nextWord();
\r
2645 getBrowser().page().action(WebAction.MoveToStartOfDocument);
\r
2646 QWebPage.FindFlags flags = new QWebPage.FindFlags();
\r
2647 flags.set(QWebPage.FindFlag.FindBackward);
\r
2649 getBrowser().setFocus();
\r
2650 boolean found = getBrowser().page().findText(word);
\r
2652 QMessageBox.critical(this, tr("Spell Check Error"),
\r
2653 tr("An error has occurred while launching the spell check. The most probable" +
\r
2654 " cause is that the cursor was not at the beginning of the document.\n\n" +
\r
2655 "Please place the cursor at the beginning & try again"));
\r
2659 found = getBrowser().page().findText(word);
\r
2662 spellChecker.checkSpelling(new StringWordTokenizer(word));
\r
2663 getBrowser().setFocus();
\r
2665 flags = new QWebPage.FindFlags();
\r
2666 tokenizer = new StringWordTokenizer(content);
\r
2668 while(tokenizer.hasMoreWords()) {
\r
2669 word = tokenizer.nextWord();
\r
2670 found = getBrowser().page().findText(word);
\r
2671 if (found && !spellListener.abortSpellCheck) {
\r
2672 spellChecker.checkSpelling(new StringWordTokenizer(word));
\r
2673 getBrowser().setFocus();
\r
2676 spellChecker.removeSpellCheckListener(spellListener);
\r
2677 if (!spellListener.errorsFound)
\r
2678 QMessageBox.information(this, tr("Spell Check Complete"),
\r
2679 tr("No spelling errors found"));
\r
2680 } catch (FileNotFoundException e) {
\r
2681 QMessageBox.critical(this, tr("Spell Check Error"),
\r
2682 tr("Dictionary "+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
2683 ".dic was not found."));
\r
2684 } catch (IOException e) {
\r
2685 QMessageBox.critical(this, tr("Spell Check Error"),
\r
2686 tr("Dictionary "+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
2687 ".dic is invalid."));
\r