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
540 logger.log(logger.HIGH, "Browser setup complete");
\r
545 private void setupShortcut(QShortcut action, String text) {
\r
546 if (!Global.shortcutKeys.containsAction(text))
\r
548 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
\r
554 // Getter for the QWebView
\r
555 public QWebView getBrowser() {
\r
559 // Block signals while loading data or things are flagged as dirty by
\r
561 public void loadingData(boolean val) {
\r
562 logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val);
\r
563 notebookBox.blockSignals(val);
\r
564 browser.page().blockSignals(val);
\r
565 browser.page().mainFrame().blockSignals(val);
\r
566 titleLabel.blockSignals(val);
\r
567 alteredDate.blockSignals(val);
\r
568 alteredTime.blockSignals(val);
\r
569 createdTime.blockSignals(val);
\r
570 createdDate.blockSignals(val);
\r
571 subjectDate.blockSignals(val);
\r
572 subjectTime.blockSignals(val);
\r
573 urlText.blockSignals(val);
\r
574 authorText.blockSignals(val);
\r
576 exposeToJavascript();
\r
577 logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val);
\r
581 public void setReadOnly(boolean v) {
\r
583 titleLabel.setEnabled(!v);
\r
584 notebookBox.setEnabled(!v);
\r
585 tagEdit.setEnabled(!v);
\r
586 authorLabel.setEnabled(!v);
\r
587 geoBox.setEnabled(!v);
\r
588 urlText.setEnabled(!v);
\r
589 createdDate.setEnabled(!v);
\r
590 subjectDate.setEnabled(!v);
\r
591 alteredDate.setEnabled(!v);
\r
592 getBrowser().setEnabled(true);
\r
595 // expose this class to Javascript on the web page
\r
596 private void exposeToJavascript() {
\r
597 browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this);
\r
600 // Custom event queue
\r
602 public boolean event(QEvent e) {
\r
603 if (e.type().equals(QEvent.Type.FocusOut)) {
\r
604 logger.log(logger.EXTREME, "Focus lost");
\r
607 return super.event(e);
\r
610 // clear out browser
\r
611 public void clear() {
\r
612 logger.log(logger.EXTREME, "Entering BrowserWindow.clear()");
\r
614 browser.setContent(new QByteArray());
\r
615 tagEdit.setText("");
\r
616 tagEdit.tagCompleter.reset();
\r
617 urlLabel.setText(tr("Source URL:"));
\r
618 titleLabel.setText("");
\r
619 logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()");
\r
622 // get/set current note
\r
623 public void setNote(Note n) {
\r
627 saveNoteTitle = n.getTitle();
\r
631 public Note getNote() {
\r
632 return currentNote;
\r
635 // New Editor Button
\r
636 private QPushButton newEditorButton(String name, String toolTip) {
\r
637 QPushButton button = new QPushButton();
\r
638 QIcon icon = new QIcon(iconPath + name + ".gif");
\r
639 button.setIcon(icon);
\r
640 button.setToolTip(toolTip);
\r
641 button.clicked.connect(this, name + "Clicked()");
\r
644 // New Editor Button
\r
645 private QToolButton newToolButton(String name, String toolTip) {
\r
646 QToolButton button = new QToolButton();
\r
647 QIcon icon = new QIcon(iconPath + name + ".gif");
\r
648 button.setIcon(icon);
\r
649 button.setToolTip(toolTip);
\r
650 button.clicked.connect(this, name + "Clicked()");
\r
655 private QLabel newSeparator() {
\r
656 return new QLabel(" ");
\r
659 // Set the title in the window
\r
660 public void setTitle(String t) {
\r
661 titleLabel.setText(t);
\r
666 // Return the current text title
\r
667 public String getTitle() {
\r
668 return titleLabel.text();
\r
671 // Set the tag name string
\r
672 public void setTag(String t) {
\r
674 tagEdit.setText(t);
\r
675 tagEdit.tagCompleter.reset();
\r
678 // Set the source URL
\r
679 public void setUrl(String t) {
\r
680 urlLabel.setText(tr("Source URL:\t"));
\r
681 urlText.setText(t);
\r
684 // The user want's to launch a web browser on the source of the URL
\r
685 public void sourceUrlClicked() {
\r
686 // Make sure we have a valid URL
\r
687 if (urlText.text().trim().equals(""))
\r
690 String url = urlText.text();
\r
691 if (!url.toLowerCase().startsWith(tr("http://")))
\r
692 url = tr("http://") +url;
\r
694 if (!QDesktopServices.openUrl(new QUrl(url))) {
\r
695 logger.log(logger.LOW, "Error opening file :" +url);
\r
699 public void setAuthor(String t) {
\r
700 authorLabel.setText(tr("Author:\t"));
\r
701 authorText.setText(t);
\r
704 // Set the creation date
\r
705 public void setCreation(long date) {
\r
706 QDateTime dt = new QDateTime();
\r
707 dt.setTime_t((int) (date / 1000));
\r
708 createdDate.setDateTime(dt);
\r
709 createdTime.setDateTime(dt);
\r
710 createdDate.setDisplayFormat(Global.getDateFormat());
\r
711 createdTime.setDisplayFormat(Global.getTimeFormat());
\r
714 // Set the creation date
\r
715 public void setAltered(long date) {
\r
716 QDateTime dt = new QDateTime();
\r
717 dt.setTime_t((int) (date / 1000));
\r
718 alteredDate.setDateTime(dt);
\r
719 alteredTime.setDateTime(dt);
\r
720 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
721 alteredTime.setDisplayFormat(Global.getTimeFormat());
\r
724 // Set the subject date
\r
725 public void setSubjectDate(long date) {
\r
726 QDateTime dt = new QDateTime();
\r
727 dt.setTime_t((int) (date / 1000));
\r
728 subjectDate.setDateTime(dt);
\r
729 subjectTime.setDateTime(dt);
\r
730 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
731 subjectTime.setDisplayFormat(Global.getTimeFormat());
\r
734 // Toggle the extended attribute information
\r
735 public void toggleInformation() {
\r
737 extendedOn = false;
\r
741 urlLabel.setVisible(extendedOn);
\r
742 urlText.setVisible(extendedOn);
\r
743 authorText.setVisible(extendedOn);
\r
744 geoBox.setVisible(extendedOn);
\r
745 authorLabel.setVisible(extendedOn);
\r
746 createdDate.setVisible(extendedOn);
\r
747 createdTime.setVisible(extendedOn);
\r
748 createdLabel.setVisible(extendedOn);
\r
749 alteredLabel.setVisible(extendedOn);
\r
750 alteredDate.setVisible(extendedOn);
\r
751 alteredTime.setVisible(extendedOn);
\r
752 //notebookBox.setVisible(extendedOn);
\r
753 notebookLabel.setVisible(extendedOn);
\r
754 subjectLabel.setVisible(extendedOn);
\r
755 subjectDate.setVisible(extendedOn);
\r
756 subjectTime.setVisible(extendedOn);
\r
759 public void hideButtons() {
\r
761 undoButton.parentWidget().setVisible(false);
\r
762 buttonsVisible = false;
\r
766 // Is the extended view on?
\r
767 public boolean isExtended() {
\r
771 // Listener for when a link is clicked
\r
772 @SuppressWarnings("unused")
\r
773 private void openFile() {
\r
774 logger.log(logger.EXTREME, "Starting openFile()");
\r
775 File fileHandle = new File(selectedFile);
\r
776 URI fileURL = fileHandle.toURI();
\r
777 String localURL = fileURL.toString();
\r
778 QUrl url = new QUrl(localURL);
\r
779 QFile file = new QFile(selectedFile);
\r
781 logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName());
\r
782 fileWatcher.addPath(file.fileName());
\r
784 if (!QDesktopServices.openUrl(url)) {
\r
785 logger.log(logger.LOW, "Error opening file :" +url);
\r
790 // Listener for when a link is clicked
\r
791 @SuppressWarnings("unused")
\r
792 private void linkClicked(QUrl url) {
\r
793 logger.log(logger.EXTREME, "URL Clicked: " +url.toString());
\r
794 if (url.toString().substring(0,8).equals("nnres://")) {
\r
795 logger.log(logger.EXTREME, "URL is NN resource");
\r
796 if (url.toString().endsWith("/vnd.evernote.ink")) {
\r
797 logger.log(logger.EXTREME, "Unable to open ink note");
\r
798 QMessageBox.information(this, tr("Unable Open"), tr("This is an ink note.\n"+
\r
799 "Ink notes are not supported since Evernote has not\n published any specifications on them\n" +
\r
800 "and I'm too lazy to figure them out by myself."));
\r
803 String fullName = url.toString().substring(8);
\r
804 int index = fullName.indexOf(".");
\r
808 type = fullName.substring(index+1);
\r
809 guid = fullName.substring(0,index);
\r
811 index = guid.indexOf(Global.attachmentNameDelimeter);
\r
813 guid = guid.substring(0,index);
\r
815 List<Resource> resList = currentNote.getResources();
\r
816 Resource res = null;
\r
817 for (int i=0; i<resList.size(); i++) {
\r
818 if (resList.get(i).getGuid().equals(guid)) {
\r
819 res = resList.get(i);
\r
824 String resGuid = Global.resourceMap.get(guid);
\r
825 if (resGuid != null)
\r
826 res = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, true);
\r
830 if (res.getAttributes() != null &&
\r
831 res.getAttributes().getFileName() != null &&
\r
832 !res.getAttributes().getFileName().trim().equals(""))
\r
833 fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();
\r
835 fileName = res.getGuid()+"."+type;
\r
836 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
837 QFile.OpenMode mode = new QFile.OpenMode();
\r
838 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
839 boolean openResult = file.open(mode);
\r
840 logger.log(logger.EXTREME, "File opened:" +openResult);
\r
841 QDataStream out = new QDataStream(file);
\r
842 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);
\r
843 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
845 logger.log(logger.EXTREME, "Writing resource");
\r
846 out.writeBytes(binData.toByteArray());
\r
849 String whichOS = System.getProperty("os.name");
\r
850 if (whichOS.contains("Windows"))
\r
851 url.setUrl("file:///"+file.fileName());
\r
853 url.setUrl("file://"+file.fileName());
\r
854 // fileWatcher.removePath(file.fileName());
\r
855 logger.log(logger.EXTREME, "Adding file watcher " +file.fileName());
\r
856 fileWatcher.addPath(file.fileName());
\r
858 // If we can't open it, then prompt the user to save it.
\r
859 if (!QDesktopServices.openUrl(url)) {
\r
860 logger.log(logger.EXTREME, "We can't handle this. Where do we put it?");
\r
861 QFileDialog dialog = new QFileDialog();
\r
863 if (dialog.exec()!=0) {
\r
864 List<String> fileNames = dialog.selectedFiles(); //gets all selected filenames
\r
865 if (fileNames.size() == 0)
\r
867 String sf = fileNames.get(0);
\r
868 QFile saveFile = new QFile(sf);
\r
869 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
870 saveFile.open(mode);
\r
871 QDataStream saveOut = new QDataStream(saveFile);
\r
872 saveOut.writeBytes(binData.toByteArray());
\r
880 logger.log(logger.EXTREME, "Launching URL");
\r
881 QDesktopServices.openUrl(url);
\r
884 // Listener for when BOLD is clicked
\r
885 @SuppressWarnings("unused")
\r
886 private void undoClicked() {
\r
887 browser.page().triggerAction(WebAction.Undo);
\r
888 browser.setFocus();
\r
891 // Listener for when BOLD is clicked
\r
892 @SuppressWarnings("unused")
\r
893 private void redoClicked() {
\r
894 browser.page().triggerAction(WebAction.Redo);
\r
895 browser.setFocus();
\r
898 // Listener for when BOLD is clicked
\r
899 @SuppressWarnings("unused")
\r
900 private void boldClicked() {
\r
901 browser.page().triggerAction(WebAction.ToggleBold);
\r
902 microFocusChanged();
\r
903 browser.setFocus();
\r
906 // Listener for when Italics is clicked
\r
907 @SuppressWarnings("unused")
\r
908 private void italicClicked() {
\r
909 browser.page().triggerAction(WebAction.ToggleItalic);
\r
910 microFocusChanged();
\r
911 browser.setFocus();
\r
914 // Listener for when UNDERLINE is clicked
\r
915 @SuppressWarnings("unused")
\r
916 private void underlineClicked() {
\r
917 browser.page().triggerAction(WebAction.ToggleUnderline);
\r
918 microFocusChanged();
\r
919 browser.setFocus();
\r
922 // Listener for when Strikethrough is clicked
\r
923 @SuppressWarnings("unused")
\r
924 private void strikethroughClicked() {
\r
925 browser.page().mainFrame().evaluateJavaScript(
\r
926 "document.execCommand('strikeThrough', false, '');");
\r
927 browser.setFocus();
\r
930 // Listener for when cut is clicked
\r
931 @SuppressWarnings("unused")
\r
932 private void cutClicked() {
\r
933 browser.page().triggerAction(WebAction.Cut);
\r
934 browser.setFocus();
\r
937 // Listener when COPY is clicked
\r
938 @SuppressWarnings("unused")
\r
939 private void copyClicked() {
\r
940 browser.page().triggerAction(WebAction.Copy);
\r
941 browser.setFocus();
\r
944 // Listener when PASTE is clicked
\r
945 public void pasteClicked() {
\r
946 logger.log(logger.EXTREME, "Paste Clicked");
\r
947 if (forceTextPaste) {
\r
948 pasteWithoutFormattingClicked();
\r
951 QClipboard clipboard = QApplication.clipboard();
\r
952 QMimeData mime = clipboard.mimeData();
\r
954 // String x = mime.html();
\r
956 if (mime.hasImage()) {
\r
957 logger.log(logger.EXTREME, "Image paste found");
\r
959 browser.setFocus();
\r
963 if (mime.hasUrls()) {
\r
964 logger.log(logger.EXTREME, "URL paste found");
\r
966 browser.setFocus();
\r
970 String text = mime.html();
\r
971 if (text.contains("en-tag") && mime.hasHtml()) {
\r
972 logger.log(logger.EXTREME, "Intra-note paste found");
\r
973 text = fixInternotePaste(text);
\r
974 mime.setHtml(text);
\r
975 clipboard.setMimeData(mime);
\r
978 logger.log(logger.EXTREME, "Final paste choice encountered");
\r
979 browser.page().triggerAction(WebAction.Paste);
\r
980 browser.setFocus();
\r
984 // Paste text without formatting
\r
985 private void pasteWithoutFormattingClicked() {
\r
986 logger.log(logger.EXTREME, "Paste without format clipped");
\r
987 QClipboard clipboard = QApplication.clipboard();
\r
988 QMimeData mime = clipboard.mimeData();
\r
989 if (!mime.hasText())
\r
991 String text = mime.text();
\r
992 clipboard.setText(text);
\r
993 browser.page().triggerAction(WebAction.Paste);
\r
994 QApplication.clipboard().setMimeData(mime);
\r
995 browser.setFocus();
\r
999 // insert date/time
\r
1000 @SuppressWarnings("unused")
\r
1001 private void insertDateTime() {
\r
1002 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
\r
1003 String dateTimeFormat = new String(fmt);
\r
1004 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
\r
1005 Calendar cal = Calendar.getInstance();
\r
1007 browser.page().mainFrame().evaluateJavaScript(
\r
1008 "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");
\r
1010 browser.setFocus();
\r
1014 // Listener when Left is clicked
\r
1015 @SuppressWarnings("unused")
\r
1016 private void justifyLeftClicked() {
\r
1017 browser.page().mainFrame().evaluateJavaScript(
\r
1018 "document.execCommand('JustifyLeft', false, '');");
\r
1019 browser.setFocus();
\r
1022 // Listener when Center is clicked
\r
1023 @SuppressWarnings("unused")
\r
1024 private void justifyCenterClicked() {
\r
1025 browser.page().mainFrame().evaluateJavaScript(
\r
1026 "document.execCommand('JustifyCenter', false, '');");
\r
1027 browser.setFocus();
\r
1030 // Listener when Left is clicked
\r
1031 @SuppressWarnings("unused")
\r
1032 private void justifyRightClicked() {
\r
1033 browser.page().mainFrame().evaluateJavaScript(
\r
1034 "document.execCommand('JustifyRight', false, '');");
\r
1035 browser.setFocus();
\r
1038 // Listener when HLINE is clicked
\r
1039 @SuppressWarnings("unused")
\r
1040 private void hlineClicked() {
\r
1041 browser.page().mainFrame().evaluateJavaScript(
\r
1042 "document.execCommand('insertHorizontalRule', false, '');");
\r
1043 browser.setFocus();
\r
1046 // Listener when outdent is clicked
\r
1047 private void outdentClicked() {
\r
1048 browser.page().mainFrame().evaluateJavaScript(
\r
1049 "document.execCommand('outdent', false, '');");
\r
1050 browser.setFocus();
\r
1053 // Listener when a bullet list is clicked
\r
1054 @SuppressWarnings("unused")
\r
1055 private void bulletListClicked() {
\r
1056 browser.page().mainFrame().evaluateJavaScript(
\r
1057 "document.execCommand('InsertUnorderedList', false, '');");
\r
1058 browser.setFocus();
\r
1061 // Listener when a bullet list is clicked
\r
1062 @SuppressWarnings("unused")
\r
1063 private void numberListClicked() {
\r
1064 browser.page().mainFrame().evaluateJavaScript(
\r
1065 "document.execCommand('InsertOrderedList', false, '');");
\r
1066 browser.setFocus();
\r
1069 // Listener when indent is clicked
\r
1070 private void indentClicked() {
\r
1071 browser.page().mainFrame().evaluateJavaScript(
\r
1072 "document.execCommand('indent', false, '');");
\r
1073 browser.setFocus();
\r
1076 // Listener when the font name is changed
\r
1077 @SuppressWarnings("unused")
\r
1078 private void fontChanged(String font) {
\r
1079 browser.page().mainFrame().evaluateJavaScript(
\r
1080 "document.execCommand('fontName',false,'" + font + "');");
\r
1081 browser.setFocus();
\r
1084 // Listener when a font size is changed
\r
1085 @SuppressWarnings("unused")
\r
1086 private void fontSizeChanged(String font) {
\r
1087 String text = browser.selectedText();
\r
1088 if (text.trim().equalsIgnoreCase(""))
\r
1091 String selectedText = browser.selectedText();
\r
1092 String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";
\r
1093 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1094 browser.page().mainFrame().evaluateJavaScript(script);
\r
1095 /* browser.page().mainFrame().evaluateJavaScript(
\r
1096 "document.execCommand('fontSize',false,'"
\r
1099 browser.setFocus();
\r
1102 // Load the font combo box based upon the font selected
\r
1103 private void loadFontSize(String name) {
\r
1104 QFontDatabase db = new QFontDatabase();
\r
1106 List<Integer> points = db.pointSizes(name);
\r
1107 for (int i=0; i<points.size(); i++) {
\r
1108 fontSize.addItem(points.get(i).toString());
\r
1111 fontSize.addItem("x-small");
\r
1112 fontSize.addItem("small");
\r
1113 fontSize.addItem("medium");
\r
1114 fontSize.addItem("large");
\r
1115 fontSize.addItem("x-large");
\r
1116 fontSize.addItem("xx-large");
\r
1117 fontSize.addItem("xxx-large");
\r
1121 // Listener when a font size is changed
\r
1122 @SuppressWarnings("unused")
\r
1123 private void fontColorClicked() {
\r
1124 // QColorDialog dialog = new QColorDialog();
\r
1125 // QColor color = QColorDialog.getColor();
\r
1126 QColor color = fontColorMenu.getColor();
\r
1127 if (color.isValid())
\r
1128 browser.page().mainFrame().evaluateJavaScript(
\r
1129 "document.execCommand('foreColor',false,'" + color.name()
\r
1131 browser.setFocus();
\r
1134 // Listener for when a background color change is requested
\r
1135 @SuppressWarnings("unused")
\r
1136 private void fontHilightClicked() {
\r
1137 // QColorDialog dialog = new QColorDialog();
\r
1138 // QColor color = QColorDialog.getColor();
\r
1139 QColor color = fontHilightColorMenu.getColor();
\r
1140 if (color.isValid())
\r
1141 browser.page().mainFrame().evaluateJavaScript(
\r
1142 "document.execCommand('backColor',false,'" + color.name()
\r
1144 browser.setFocus();
\r
1147 // Listener for when a background color change is requested
\r
1148 @SuppressWarnings("unused")
\r
1149 private void superscriptClicked() {
\r
1150 browser.page().mainFrame().evaluateJavaScript(
\r
1151 "document.execCommand('superscript');");
\r
1152 browser.setFocus();
\r
1155 // Listener for when a background color change is requested
\r
1156 @SuppressWarnings("unused")
\r
1157 private void subscriptClicked() {
\r
1158 browser.page().mainFrame().evaluateJavaScript(
\r
1159 "document.execCommand('subscript');");
\r
1160 browser.setFocus();
\r
1162 // Insert a to-do checkbox
\r
1163 @SuppressWarnings("unused")
\r
1164 private void todoClicked() {
\r
1165 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1166 String script_start = new String(
\r
1167 "document.execCommand('insertHtml', false, '");
\r
1168 String script_end = new String("');");
\r
1169 String todo = new String(
\r
1170 "<input TYPE=\"CHECKBOX\" value=\"false\" onClick=\"value=checked; window.jambi.contentChanged(); \" />");
\r
1171 browser.page().mainFrame().evaluateJavaScript(
\r
1172 script_start + todo + script_end);
\r
1173 browser.setFocus();
\r
1176 // Encrypt the selected text
\r
1177 @SuppressWarnings("unused")
\r
1178 private void encryptText() {
\r
1179 String text = browser.selectedText();
\r
1180 if (text.trim().equalsIgnoreCase(""))
\r
1183 EnCryptDialog dialog = new EnCryptDialog();
\r
1185 if (!dialog.okPressed()) {
\r
1189 EnCrypt crypt = new EnCrypt();
\r
1190 String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);
\r
1192 if (encrypted.trim().equals("")) {
\r
1193 QMessageBox.information(this, tr("Error"), tr("Error Encrypting String"));
\r
1196 StringBuffer buffer = new StringBuffer(encrypted.length() + 100);
\r
1197 buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""
\r
1198 + dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");
\r
1199 buffer.append("contentEditable=\"false\" alt=\"");
\r
1200 buffer.append(encrypted);
\r
1201 // NFC FIXME: should this be a file URL like in handleLocalAttachment and importAttachment?
\r
1202 buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png") +"\""));
\r
1203 Global.cryptCounter++;
\r
1204 buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");
\r
1205 buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");
\r
1206 buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString()
\r
1207 +"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&apos;")+"\\');\"");
\r
1208 buffer.append("style=\"display:block\" />");
\r
1210 String script_start = new String(
\r
1211 "document.execCommand('insertHtml', false, '");
\r
1212 String script_end = new String("');");
\r
1213 browser.page().mainFrame().evaluateJavaScript(
\r
1214 script_start + buffer.toString() + script_end);
\r
1218 // Insert a hyperlink
\r
1219 public void insertLink() {
\r
1220 logger.log(logger.EXTREME, "Inserting link");
\r
1221 String text = browser.selectedText();
\r
1222 if (text.trim().equalsIgnoreCase(""))
\r
1225 InsertLinkDialog dialog = new InsertLinkDialog();
\r
1226 if (currentHyperlink != null && currentHyperlink != "") {
\r
1227 dialog.setUrl(currentHyperlink);
\r
1230 if (!dialog.okPressed()) {
\r
1231 logger.log(logger.EXTREME, "Insert link canceled");
\r
1234 if (browser.insertLinkAction.text().equalsIgnoreCase("Insert Hyperlink")) {
\r
1235 String selectedText = browser.selectedText();
\r
1236 logger.log(logger.EXTREME, "Inserting link on text "+selectedText);
\r
1237 logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim());
\r
1238 String url = "<a href=\"" +dialog.getUrl().trim()
\r
1239 +"\" title=" +dialog.getUrl().trim()
\r
1240 +" >"+selectedText +"</a>";
\r
1241 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1242 browser.page().mainFrame().evaluateJavaScript(script);
\r
1245 String js = new String( "function getCursorPos() {"
\r
1247 +"if (window.getSelection) {"
\r
1248 +" var selObj = window.getSelection();"
\r
1249 +" var selRange = selObj.getRangeAt(0);"
\r
1250 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1251 +" while(workingNode != null) { "
\r
1252 +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');"
\r
1253 +" workingNode = workingNode.parentNode;"
\r
1256 +"} getCursorPos();");
\r
1257 browser.page().mainFrame().evaluateJavaScript(js);
\r
1264 public void insertTable() {
\r
1265 TableDialog dialog = new TableDialog();
\r
1267 if (!dialog.okPressed()) {
\r
1271 int cols = dialog.getCols();
\r
1272 int rows = dialog.getRows();
\r
1273 int width = dialog.getWidth();
\r
1274 boolean percent = dialog.isPercent();
\r
1276 String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();
\r
1278 newHTML = newHTML +"%";
\r
1279 newHTML = newHTML + "\"><tbody>";
\r
1281 for (int i=0; i<rows; i++) {
\r
1282 newHTML = newHTML +"<tr>";
\r
1283 for (int j=0; j<cols; j++) {
\r
1284 newHTML = newHTML +"<td> </td>";
\r
1286 newHTML = newHTML +"</tr>";
\r
1288 newHTML = newHTML+"</tbody></table>";
\r
1290 String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";
\r
1291 browser.page().mainFrame().evaluateJavaScript(script);
\r
1295 // Text content changed
\r
1296 @SuppressWarnings("unused")
\r
1297 private void selectionChanged() {
\r
1298 browser.encryptAction.setEnabled(true);
\r
1299 browser.insertLinkAction.setEnabled(true);
\r
1300 String scriptStart = "var selection_text = (window.getSelection()).toString();"
\r
1301 + "var range = (window.getSelection()).getRangeAt(0);"
\r
1302 + "var parent_html = range.commonAncestorContainer.innerHTML;"
\r
1303 + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"
\r
1304 + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"
\r
1305 + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"
\r
1306 + "var start = parent_html.indexOf(first_text);"
\r
1307 + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"
\r
1308 + "var value = parent_html.substring(start,end);"
\r
1309 + "window.jambi.saveSelectedText(value);" ;
\r
1310 browser.page().mainFrame().evaluateJavaScript(scriptStart);
\r
1314 public void saveSelectedText(String text) {
\r
1315 boolean enabled = true;
\r
1316 if (text.trim().length() == 0)
\r
1318 if (text.indexOf("en-tag=\"en-crypt\"") >= 0)
\r
1320 if (text.indexOf("<img en-tag=\"en-media\"") >= 0)
\r
1322 if (text.indexOf("<a en-tag=\"en-media\"") >= 0)
\r
1324 if (text.indexOf("<input ") >= 0)
\r
1327 browser.encryptAction.setEnabled(enabled);
\r
1328 browser.insertLinkAction.setEnabled(enabled);
\r
1329 // selectedText = text;
\r
1332 // Decrypt clicked text
\r
1333 public void decryptText(String id, String text, String hint) {
\r
1334 EnCrypt crypt = new EnCrypt();
\r
1335 String plainText = null;
\r
1336 Calendar currentTime = new GregorianCalendar();
\r
1337 Long l = new Long(currentTime.getTimeInMillis());
\r
1338 String slot = new String(Long.toString(l));
\r
1340 // First, try to decrypt with any keys we already have
\r
1341 for (int i=0; i<Global.passwordRemember.size(); i++) {
\r
1342 plainText = crypt.decrypt(text, Global.passwordRemember.get(i), 64);
\r
1343 if (plainText != null) {
\r
1344 slot = new String(Long.toString(l));
\r
1345 Global.passwordSafe.put(slot, Global.passwordRemember.get(i));
\r
1346 removeEncryption(id, plainText, false, slot);
\r
1352 EnDecryptDialog dialog = new EnDecryptDialog();
\r
1353 dialog.setHint(hint);
\r
1354 while (plainText == null || !dialog.okPressed()) {
\r
1356 if (!dialog.okPressed()) {
\r
1359 plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);
\r
1360 if (plainText == null) {
\r
1361 QMessageBox.warning(this, "Incorrect Password", "The password entered is not correct");
\r
1364 Global.passwordSafe.put(slot, dialog.getPassword());
\r
1365 removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);
\r
1366 if (dialog.rememberPassword())
\r
1367 Global.passwordRemember.add(dialog.getPassword());
\r
1371 // Get the editor tag line
\r
1372 public TagLineEdit getTagLine() {
\r
1376 // Modify a note's tags
\r
1377 @SuppressWarnings("unused")
\r
1378 private void modifyTags() {
\r
1379 TagAssign tagWindow = new TagAssign(allTags, currentTags);
\r
1381 if (tagWindow.okClicked()) {
\r
1382 currentTags.clear();
\r
1383 StringBuffer tagDisplay = new StringBuffer();
\r
1385 List<QListWidgetItem> newTags = tagWindow.getTagList()
\r
1387 for (int i = 0; i < newTags.size(); i++) {
\r
1388 currentTags.add(newTags.get(i).text());
\r
1389 tagDisplay.append(newTags.get(i).text());
\r
1390 if (i < newTags.size() - 1) {
\r
1391 tagDisplay.append(Global.tagDelimeter + " ");
\r
1394 tagEdit.setText(tagDisplay.toString());
\r
1395 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1399 // Tag line has been modified by typing text
\r
1400 @SuppressWarnings("unused")
\r
1401 private void modifyTagsTyping() {
\r
1402 String completionText = "";
\r
1403 if (tagEdit.currentCompleterSelection != null && !tagEdit.currentCompleterSelection.equals("")) {
\r
1404 completionText = tagEdit.currentCompleterSelection;
\r
1405 tagEdit.currentCompleterSelection = "";
\r
1408 if (tagEdit.text().equalsIgnoreCase(saveTagList))
\r
1411 // We know something has changed...
\r
1412 String oldTagArray[] = saveTagList.split(Global.tagDelimeter);
\r
1413 String newTagArray[] = tagEdit.text().split(Global.tagDelimeter);
\r
1415 if (!completionText.equals("") && newTagArray.length > 0) {
\r
1416 newTagArray[newTagArray.length-1] = completionText;
\r
1418 // Remove any potential duplicates from the new list
\r
1419 for (int i=0; i<newTagArray.length; i++) {
\r
1420 boolean foundOnce = false;
\r
1421 for (int j=0; j<newTagArray.length; j++) {
\r
1422 if (newTagArray[j].equalsIgnoreCase(newTagArray[i])) {
\r
1426 newTagArray[j] = "";
\r
1431 List<String> newTagList = new ArrayList<String>();
\r
1432 List<String> oldTagList = new ArrayList<String>();
\r
1434 for (int i = 0; i < oldTagArray.length; i++)
\r
1435 if (!oldTagArray[i].trim().equals(""))
\r
1436 oldTagList.add(oldTagArray[i]);
\r
1437 for (int i = 0; i < newTagArray.length; i++)
\r
1438 if (!newTagArray[i].trim().equals(""))
\r
1439 newTagList.add(newTagArray[i]);
\r
1441 // Let's cleanup the appearance of the tag list
\r
1442 Collections.sort(newTagList);
\r
1443 String newDisplay = "";
\r
1444 for (int i=0; i<newTagList.size(); i++) {
\r
1445 newDisplay = newDisplay+newTagList.get(i);
\r
1446 if (i<newTagList.size()-1)
\r
1447 newDisplay = newDisplay+", ";
\r
1449 tagEdit.blockSignals(true);
\r
1450 tagEdit.setText(newDisplay);
\r
1451 tagEdit.blockSignals(false);
\r
1453 // We now have lists of the new & old. Remove duplicates. If all
\r
1454 // are removed from both then nothing has really changed
\r
1455 for (int i = newTagList.size() - 1; i >= 0; i--) {
\r
1456 String nTag = newTagList.get(i);
\r
1457 for (int j = oldTagList.size() - 1; j >= 0; j--) {
\r
1458 String oTag = oldTagList.get(j);
\r
1459 if (oTag.equalsIgnoreCase(nTag)) {
\r
1460 oldTagList.remove(j);
\r
1461 newTagList.remove(i);
\r
1467 if (oldTagList.size() != 0 || newTagList.size() != 0) {
\r
1468 currentTags.clear();
\r
1469 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1470 for (int i = 0; i < newTagArray.length; i++)
\r
1471 if (!newTagArray[i].trim().equals(""))
\r
1472 currentTags.add(newTagArray[i].trim());
\r
1474 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1479 // Tab button was pressed
\r
1480 public void tabPressed() {
\r
1481 if (!insideList) {
\r
1482 String script_start = new String(
\r
1483 "document.execCommand('insertHtml', false, ' ');");
\r
1484 browser.page().mainFrame().evaluateJavaScript(script_start);
\r
1489 public void backtabPressed() {
\r
1494 public void setInsideList() {
\r
1495 insideList = true;
\r
1498 // The title has been edited
\r
1499 @SuppressWarnings("unused")
\r
1500 private void titleEdited() {
\r
1501 // If we don't have a good note, or if the current title
\r
1502 // matches the old title then we don't need to do anything
\r
1503 if (currentNote == null)
\r
1505 if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))
\r
1508 // If we have a real change, we need to save it.
\r
1509 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text());
\r
1510 currentNote.setTitle(titleLabel.text());
\r
1511 saveNoteTitle = titleLabel.text();
\r
1515 // Set the list of note tags
\r
1516 public void setAllTags(List<Tag> l) {
\r
1518 tagEdit.setTagList(l);
\r
1521 // Setter for the current tags
\r
1522 public void setCurrentTags(List<String> s) {
\r
1526 // Save the list of notebooks
\r
1527 public void setNotebookList(List<Notebook> n) {
\r
1529 loadNotebookList();
\r
1532 // Load the notebook list and select the current notebook
\r
1533 private void loadNotebookList() {
\r
1534 if (notebookBox.count() != 0)
\r
1535 notebookBox.clear();
\r
1536 if (notebookList == null)
\r
1539 for (int i = 0; i < notebookList.size(); i++) {
\r
1540 notebookBox.addItem(notebookList.get(i).getName());
\r
1541 if (currentNote != null) {
\r
1542 if (currentNote.getNotebookGuid().equals(
\r
1543 notebookList.get(i).getGuid())) {
\r
1544 notebookBox.setCurrentIndex(i);
\r
1550 // Get the contents of the editor
\r
1551 public String getContent() {
\r
1552 return browser.page().currentFrame().toHtml();
\r
1555 // The note contents have changed
\r
1556 public void contentChanged() {
\r
1557 String content = getContent();
\r
1559 noteSignal.noteChanged.emit(currentNote.getGuid(), content);
\r
1562 // The notebook selection has changed
\r
1563 @SuppressWarnings("unused")
\r
1564 private void notebookChanged() {
\r
1565 boolean changed = false;
\r
1566 String n = notebookBox.currentText();
\r
1567 for (int i = 0; i < notebookList.size(); i++) {
\r
1568 if (n.equals(notebookList.get(i).getName())) {
\r
1569 if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {
\r
1570 currentNote.setNotebookGuid(notebookList.get(i).getGuid());
\r
1573 i = notebookList.size();
\r
1577 // If the notebook changed, signal the update
\r
1579 noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote
\r
1580 .getNotebookGuid());
\r
1583 // Check the note title
\r
1584 private void checkNoteTitle() {
\r
1585 String text = browser.page().currentFrame().toPlainText();
\r
1586 if (saveNoteTitle.trim().equals("") || saveNoteTitle.trim().equals("Untitled Note")) {
\r
1587 int newLine = text.indexOf("\n");
\r
1588 if (newLine > 0) {
\r
1589 text = text.substring(0, newLine);
\r
1590 if (text.trim().equals(""))
\r
1591 text = tr("Untitled Note");
\r
1592 titleLabel.setText(text);
\r
1594 if (text.length() > Constants.EDAM_NOTE_TITLE_LEN_MAX)
\r
1595 titleLabel.setText(text.substring(0, Constants.EDAM_NOTE_TITLE_LEN_MAX));
\r
1597 titleLabel.blockSignals(true);
\r
1598 if (text.trim().equals(""))
\r
1599 titleLabel.setText(tr("Untitled Note"));
\r
1601 titleLabel.setText(text);
\r
1602 titleLabel.blockSignals(false);
\r
1605 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel
\r
1610 // Return the note contents so we can email them
\r
1611 public String getContentsToEmail() {
\r
1612 return browser.page().currentFrame().toPlainText().trim();
\r
1614 * int body = browser.page().currentFrame().toHtml().indexOf("<body>");
\r
1615 * String temp = browser.page().currentFrame().toHtml(); if (body == -1)
\r
1616 * temp = "<html><body><b>Test</b></body></html>"; else temp =
\r
1617 * "<html>"+temp.substring(body); return temp; // return
\r
1618 * urlEncode(browser.page().currentFrame().toHtml());
\r
1622 // Insert an image into the editor
\r
1623 private void insertImage(QMimeData mime) {
\r
1624 logger.log(logger.EXTREME, "Entering insertImage");
\r
1625 QImage img = (QImage) mime.imageData();
\r
1626 String script_start = new String(
\r
1627 "document.execCommand('insertHTML', false, '");
\r
1628 String script_end = new String("');");
\r
1630 long now = new Date().getTime();
\r
1631 String path = Global.getFileManager().getResDirPath(
\r
1632 (new Long(now).toString()) + ".jpg");
\r
1634 // This block is just a hack to make sure we wait at least 1ms so we
\r
1636 // have collisions on image names
\r
1637 long i = new Date().getTime();
\r
1639 i = new Date().getTime();
\r
1641 // Open the file & write the data
\r
1642 QFile tfile = new QFile(path);
\r
1643 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1647 Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);
\r
1648 if (newRes == null)
\r
1650 currentNote.getResources().add(newRes);
\r
1652 // do the actual insert into the note
\r
1653 StringBuffer buffer = new StringBuffer(100);
\r
1654 buffer.append("<img src=\"");
\r
1655 buffer.append(tfile.fileName());
\r
1656 buffer.append("\" en-tag=en-media type=\"image/jpeg\""
\r
1657 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1658 +" guid=\"" +newRes.getGuid() +"\""
\r
1659 // +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1660 +" onContextMenu=\"window.jambi.imageContextMenu(&." +tfile.fileName() +"&.);\""
\r
1663 browser.page().mainFrame().evaluateJavaScript(
\r
1664 script_start + buffer + script_end);
\r
1669 // Handle URLs that are trying to be pasted
\r
1670 public void handleUrls(QMimeData mime) {
\r
1671 logger.log(logger.EXTREME, "Starting handleUrls");
\r
1672 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1674 List<QUrl> urlList = mime.urls();
\r
1675 String url = new String();
\r
1676 String script_start = new String(
\r
1677 "document.execCommand('createLink', false, '");
\r
1678 String script_end = new String("');");
\r
1680 for (int i = 0; i < urlList.size(); i++) {
\r
1681 url = urlList.get(i).toString();
\r
1682 // Find out what type of file we have
\r
1683 String mimeType = fileNameMap.getContentTypeFor(url);
\r
1685 // If null returned, we need to guess at the file type
\r
1686 if (mimeType == null)
\r
1687 mimeType = "application/"
\r
1688 + url.substring(url.lastIndexOf(".") + 1);
\r
1690 // Check if we have an image or some other type of file
\r
1691 if (url.substring(0, 5).equalsIgnoreCase("file:")
\r
1692 && mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1693 handleLocalImageURLPaste(mime, mimeType);
\r
1696 String[] type = mimeType.split("/");
\r
1697 boolean valid = validAttachment(type[1]);
\r
1698 boolean smallEnough = checkFileAttachmentSize(url);
\r
1699 if (smallEnough && valid
\r
1700 && url.substring(0, 5).equalsIgnoreCase("file:")
\r
1701 && !mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1702 handleLocalAttachment(mime, mimeType);
\r
1705 browser.page().mainFrame().evaluateJavaScript(
\r
1706 script_start + url + script_end);
\r
1711 // If a URL being pasted is an image URL, then attach the image
\r
1712 private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {
\r
1713 List<QUrl> urlList = mime.urls();
\r
1714 String url = new String();
\r
1715 String script_start_image = new String(
\r
1716 "document.execCommand('insertHtml', false, '");
\r
1717 String script_end = new String("');");
\r
1718 StringBuffer buffer;
\r
1720 // Copy the image over into the resource directory and create a new resource
\r
1721 // record for each url pasted
\r
1722 for (int i = 0; i < urlList.size(); i++) {
\r
1723 url = urlList.get(i).toString();
\r
1725 Resource newRes = createResource(url, i, mimeType, false);
\r
1726 if (newRes == null)
\r
1728 currentNote.getResources().add(newRes);
\r
1729 buffer = new StringBuffer(100);
\r
1731 // Open the file & write the data
\r
1732 String fileName = Global.getFileManager().getResDirPath(newRes.getGuid());
\r
1733 QFile tfile = new QFile(fileName);
\r
1734 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1735 tfile.write(newRes.getData().getBody());
\r
1737 buffer.append(script_start_image);
\r
1738 buffer.append("<img src=\"" + FileUtils.toForwardSlashedPath(fileName));
\r
1739 // if (mimeType.equalsIgnoreCase("image/jpg"))
\r
1740 // mimeType = "image/jpeg";
\r
1741 buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""
\r
1742 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1743 +" guid=\"" +newRes.getGuid() +"\""
\r
1744 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1746 buffer.append(script_end);
\r
1747 browser.page().mainFrame().evaluateJavaScript(buffer.toString());
\r
1753 // If a URL being pasted is a local file URL, then attach the file
\r
1754 private void handleLocalAttachment(QMimeData mime, String mimeType) {
\r
1755 logger.log(logger.EXTREME, "Attaching local file");
\r
1756 List<QUrl> urlList = mime.urls();
\r
1757 String script_start = new String(
\r
1758 "document.execCommand('insertHtml', false, '");
\r
1759 String script_end = new String("');");
\r
1760 StringBuffer buffer;
\r
1762 String[] type = mimeType.split("/");
\r
1763 String icon = findIcon(type[1]);
\r
1764 if (icon.equals("attachment.png"))
\r
1765 icon = findIcon(type[0]);
\r
1766 buffer = new StringBuffer(100);
\r
1768 for (int i = 0; i < urlList.size(); i++) {
\r
1769 String url = urlList.get(i).toString();
\r
1771 // Start building the HTML
\r
1772 if (icon.equals("attachment.png"))
\r
1773 icon = findIcon(url.substring(url.lastIndexOf(".")+1));
\r
1774 String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));
\r
1776 logger.log(logger.EXTREME, "Creating resource ");
\r
1777 Resource newRes = createResource(url, i, mimeType, true);
\r
1778 if (newRes == null)
\r
1780 logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());
\r
1781 currentNote.getResources().add(newRes);
\r
1783 String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();
\r
1784 // If we have a PDF, we need to setup the preview.
\r
1785 if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {
\r
1786 logger.log(logger.EXTREME, "Setting up PDF preview");
\r
1787 if (newRes.getAttributes() != null &&
\r
1788 newRes.getAttributes().getFileName() != null &&
\r
1789 !newRes.getAttributes().getFileName().trim().equals(""))
\r
1790 fileName = newRes.getGuid()+Global.attachmentNameDelimeter+
\r
1791 newRes.getAttributes().getFileName();
\r
1793 fileName = newRes.getGuid()+".pdf";
\r
1794 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
1795 QFile.OpenMode mode = new QFile.OpenMode();
\r
1796 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
1798 QDataStream out = new QDataStream(file);
\r
1799 // Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);
\r
1800 QByteArray binData = new QByteArray(newRes.getData().getBody());
\r
1801 // resBinary = null;
\r
1802 out.writeBytes(binData.toByteArray());
\r
1805 PDFPreview pdfPreview = new PDFPreview();
\r
1806 if (pdfPreview.setupPreview(Global.getFileManager().getResDirPath(fileName), "pdf",0)) {
\r
1807 // NFC TODO: should this be a 'file://' url like the ones above?
\r
1808 imageURL = file.fileName() + ".png";
\r
1812 logger.log(logger.EXTREME, "Generating link tags");
\r
1813 buffer.delete(0, buffer.length());
\r
1814 buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");
\r
1815 buffer.append(" onContextMenu=\"window.jambi.imageContextMenu('")
\r
1816 .append(Global.getFileManager().getResDirPath(fileName))
\r
1817 .append("');\" "); buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");
\r
1818 buffer.append("<img src=\"" + imageURL + "\" title=\"" +newRes.getAttributes().getFileName());
\r
1819 buffer.append("\"></img>");
\r
1820 buffer.append("</a>");
\r
1821 browser.page().mainFrame().evaluateJavaScript(
\r
1822 script_start + buffer.toString() + script_end);
\r
1827 private Resource createResource(String url, int sequence, String mime, boolean attachment) {
\r
1828 logger.log(logger.EXTREME, "Inside create resource");
\r
1829 QFile resourceFile;
\r
1830 String urlTest = new QUrl(url).toLocalFile();
\r
1831 if (!urlTest.equals(""))
\r
1833 url = url.replace("/", File.separator);
\r
1834 resourceFile = new QFile(url);
\r
1835 resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));
\r
1836 byte[] fileData = resourceFile.readAll().toByteArray();
\r
1837 resourceFile.close();
\r
1838 if (fileData.length == 0)
\r
1842 md = MessageDigest.getInstance("MD5");
\r
1843 md.update(fileData);
\r
1844 byte[] hash = md.digest();
\r
1846 Resource r = new Resource();
\r
1847 Calendar time = new GregorianCalendar();
\r
1848 long prevTime = time.getTimeInMillis();
\r
1849 while (prevTime == time.getTimeInMillis()) {
\r
1850 time = new GregorianCalendar();
\r
1852 r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());
\r
1853 r.setNoteGuid(currentNote.getGuid());
\r
1855 r.setActive(true);
\r
1856 r.setUpdateSequenceNum(0);
\r
1857 r.setWidth((short) 0);
\r
1858 r.setHeight((short) 0);
\r
1859 r.setDuration((short) 0);
\r
1861 Data d = new Data();
\r
1862 d.setBody(fileData);
\r
1863 d.setBodyIsSet(true);
\r
1864 d.setBodyHash(hash);
\r
1865 d.setBodyHashIsSet(true);
\r
1867 d.setSize(fileData.length);
\r
1869 int fileNamePos = url.lastIndexOf(File.separator);
\r
1870 if (fileNamePos == -1)
\r
1871 fileNamePos = url.lastIndexOf("/");
\r
1872 String fileName = url.substring(fileNamePos+1);
\r
1873 ResourceAttributes a = new ResourceAttributes();
\r
1875 a.setAltitudeIsSet(false);
\r
1876 a.setLongitude(0);
\r
1877 a.setLongitudeIsSet(false);
\r
1879 a.setLatitudeIsSet(false);
\r
1880 a.setCameraMake("");
\r
1881 a.setCameraMakeIsSet(false);
\r
1882 a.setCameraModel("");
\r
1883 a.setCameraModelIsSet(false);
\r
1884 a.setAttachment(attachment);
\r
1885 a.setAttachmentIsSet(true);
\r
1886 a.setClientWillIndex(false);
\r
1887 a.setClientWillIndexIsSet(true);
\r
1888 a.setRecoType("");
\r
1889 a.setRecoTypeIsSet(false);
\r
1890 a.setSourceURL(url);
\r
1891 a.setSourceURLIsSet(true);
\r
1892 a.setTimestamp(0);
\r
1893 a.setTimestampIsSet(false);
\r
1894 a.setFileName(fileName);
\r
1895 a.setFileNameIsSet(true);
\r
1896 r.setAttributes(a);
\r
1898 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
1900 } catch (NoSuchAlgorithmException e1) {
\r
1901 e1.printStackTrace();
\r
1907 // find the appropriate icon for an attachment
\r
1908 private String findIcon(String appl) {
\r
1909 appl = appl.toLowerCase();
\r
1910 File f = Global.getFileManager().getImageDirFile(appl + ".png");
\r
1912 return appl+".png";
\r
1913 return "attachment.png";
\r
1916 // Check if the account supports this type of attachment
\r
1917 private boolean validAttachment(String type) {
\r
1918 if (Global.isPremium())
\r
1920 if (type.equalsIgnoreCase("JPG"))
\r
1922 if (type.equalsIgnoreCase("PNG"))
\r
1924 if (type.equalsIgnoreCase("GIF"))
\r
1926 if (type.equalsIgnoreCase("MP3"))
\r
1928 if (type.equalsIgnoreCase("WAV"))
\r
1930 if (type.equalsIgnoreCase("AMR"))
\r
1932 if (type.equalsIgnoreCase("PDF"))
\r
1934 String error = tr("Non-premium accounts can only attach JPG, PNG, GIF, MP3, WAV, AMR, or PDF files.");
\r
1935 QMessageBox.information(this, tr("Non-Premium Account"), error);
\r
1940 // Check the file attachment to be sure it isn't over 25 mb
\r
1941 private boolean checkFileAttachmentSize(String url) {
\r
1942 String fileName = url.substring(8);
\r
1943 QFile resourceFile = new QFile(fileName);
\r
1944 resourceFile.open(new QIODevice.OpenMode(
\r
1945 QIODevice.OpenModeFlag.ReadOnly));
\r
1946 long size = resourceFile.size();
\r
1947 resourceFile.close();
\r
1948 size = size / 1024 / 1024;
\r
1949 if (size < 50 && Global.isPremium())
\r
1954 String error = tr("A file attachment may not exceed 25MB.");
\r
1955 QMessageBox.information(this, tr("Attachment Size"), error);
\r
1960 @SuppressWarnings("unused")
\r
1961 private void createdChanged() {
\r
1962 QDateTime dt = new QDateTime();
\r
1963 dt.setDate(createdDate.date());
\r
1964 dt.setTime(createdTime.time());
\r
1965 noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);
\r
1969 @SuppressWarnings("unused")
\r
1970 private void alteredChanged() {
\r
1971 QDateTime dt = new QDateTime();
\r
1972 dt.setDate(alteredDate.date());
\r
1973 dt.setTime(alteredTime.time());
\r
1974 noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);
\r
1977 @SuppressWarnings("unused")
\r
1978 private void subjectDateTimeChanged() {
\r
1979 QDateTime dt = new QDateTime();
\r
1980 dt.setDate(subjectDate.date());
\r
1981 dt.setTime(subjectTime.time());
\r
1982 noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);
\r
1986 @SuppressWarnings("unused")
\r
1987 private void sourceUrlChanged() {
\r
1988 noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());
\r
1991 @SuppressWarnings("unused")
\r
1992 private void authorChanged() {
\r
1993 noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());
\r
1996 @SuppressWarnings("unused")
\r
1997 private void geoBoxChanged() {
\r
1998 int index = geoBox.currentIndex();
\r
1999 geoBox.setCurrentIndex(0);
\r
2001 GeoDialog box = new GeoDialog();
\r
2002 box.setLongitude(currentNote.getAttributes().getLongitude());
\r
2003 box.setLatitude(currentNote.getAttributes().getLatitude());
\r
2004 box.setAltitude(currentNote.getAttributes().getAltitude());
\r
2006 if (!box.okPressed())
\r
2008 double alt = box.getAltitude();
\r
2009 double lat = box.getLatitude();
\r
2010 double lon = box.getLongitude();
\r
2011 if (alt != currentNote.getAttributes().getAltitude() ||
\r
2012 lon != currentNote.getAttributes().getLongitude() ||
\r
2013 lat != currentNote.getAttributes().getLatitude()) {
\r
2014 noteSignal.geoChanged.emit(currentNote.getGuid(), lon, lat, alt);
\r
2015 currentNote.getAttributes().setAltitude(alt);
\r
2016 currentNote.getAttributes().setLongitude(lon);
\r
2017 currentNote.getAttributes().setLatitude(lat);
\r
2022 noteSignal.geoChanged.emit(currentNote.getGuid(), 0.0, 0.0, 0.0);
\r
2023 currentNote.getAttributes().setAltitude(0.0);
\r
2024 currentNote.getAttributes().setLongitude(0.0);
\r
2025 currentNote.getAttributes().setLatitude(0.0);
\r
2028 if (index == 3 || index == 0) {
\r
2029 QDesktopServices.openUrl(new QUrl("http://maps.google.com/maps?z=6&q="+currentNote.getAttributes().getLatitude() +"," +currentNote.getAttributes().getLongitude()));
\r
2033 // ************************************************************
\r
2034 // * User chose to save an attachment. Pares out the request *
\r
2035 // * into a guid & file. Save the result. *
\r
2036 // ************************************************************
\r
2037 public void downloadAttachment(QNetworkRequest request) {
\r
2039 QFileDialog fd = new QFileDialog(this);
\r
2040 fd.setFileMode(FileMode.AnyFile);
\r
2041 fd.setConfirmOverwrite(true);
\r
2042 fd.setWindowTitle(tr("Save File"));
\r
2043 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2044 fd.setDirectory(System.getProperty("user.home"));
\r
2045 String name = request.url().toString();
\r
2047 int pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2049 guid = name.substring(0, pos).replace("nnres://", "");
\r
2050 name = name.substring(pos +Global.attachmentNameDelimeter.length());
\r
2051 fd.selectFile(name);
\r
2052 pos = name.lastIndexOf('.');
\r
2054 String mimeType = "(*." + name.substring(pos + 1)
\r
2055 + ");; All Files (*)";
\r
2056 fd.setFilter(tr(mimeType));
\r
2062 // Strip URL prefix and base dir
\r
2063 guid = guid.replace("nnres://", "")
\r
2064 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2066 pos = guid.lastIndexOf('.');
\r
2068 guid = guid.substring(0,pos);
\r
2069 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2070 name = name.replace('\\', '/');
\r
2071 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2072 QFile saveFile = new QFile(fd.selectedFiles().get(0));
\r
2073 QFile.OpenMode mode = new QFile.OpenMode();
\r
2074 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2075 saveFile.open(mode);
\r
2076 QDataStream saveOut = new QDataStream(saveFile);
\r
2077 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2078 saveOut.writeBytes(binData.toByteArray());
\r
2085 // ************************************************************
\r
2086 // * User chose to save an attachment. Pares out the request *
\r
2087 // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!
\r
2088 // ************************************************************
\r
2089 // NFC TODO: unused? remove
\r
2090 public void downloadImage(QNetworkRequest request) {
\r
2091 QFileDialog fd = new QFileDialog(this);
\r
2092 fd.setFileMode(FileMode.AnyFile);
\r
2093 fd.setConfirmOverwrite(true);
\r
2094 fd.setWindowTitle(tr("Save File"));
\r
2095 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2096 fd.setDirectory(System.getProperty("user.home"));
\r
2097 String name = request.url().toString();
\r
2098 name = name.replace("nnres://", "");
\r
2099 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
\r
2100 name = name.replace(dPath, "");
\r
2101 int pos = name.lastIndexOf('.');
\r
2102 String guid = name;
\r
2104 String mimeType = "(*." + name.substring(pos + 1)
\r
2105 + ");; All Files (*)";
\r
2106 fd.setFilter(tr(mimeType));
\r
2107 guid = guid.substring(0,pos);
\r
2109 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2111 guid = name.substring(0, pos);
\r
2112 fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));
\r
2114 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2115 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2116 String fileName = fd.selectedFiles().get(0);
\r
2117 QFile saveFile = new QFile(fileName);
\r
2118 QFile.OpenMode mode = new QFile.OpenMode();
\r
2119 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2120 saveFile.open(mode);
\r
2121 QDataStream saveOut = new QDataStream(saveFile);
\r
2122 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2123 saveOut.writeBytes(binData.toByteArray());
\r
2129 // *************************************************************
\r
2130 // * decrypt any hidden text. We could do an XML parse, but
\r
2131 // * it is quicker here just to scan for an <img tag & do the fix
\r
2132 // * the manual way
\r
2133 // *************************************************************
\r
2134 private void removeEncryption(String id, String plainText, boolean permanent, String slot) {
\r
2136 plainText = " <en-crypt-temp slot=\""+slot +"\">" +plainText+"</en-crypt-temp> ";
\r
2139 String html = browser.page().mainFrame().toHtml();
\r
2140 String text = html;
\r
2141 int imagePos = html.indexOf("<img");
\r
2143 for ( ;imagePos>0; ) {
\r
2144 // Find the end tag
\r
2145 endPos = text.indexOf(">", imagePos);
\r
2146 String tag = text.substring(imagePos-1,endPos);
\r
2147 if (tag.indexOf("id=\""+id+"\"") > -1) {
\r
2148 text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);
\r
2150 browser.setContent(new QByteArray(text));
\r
2153 imagePos = text.indexOf("<img", imagePos+1);
\r
2158 //****************************************************************
\r
2159 //* Focus shortcuts
\r
2160 //****************************************************************
\r
2161 @SuppressWarnings("unused")
\r
2162 private void focusTitle() {
\r
2163 titleLabel.setFocus();
\r
2165 @SuppressWarnings("unused")
\r
2166 private void focusTag() {
\r
2167 tagEdit.setFocus();
\r
2169 @SuppressWarnings("unused")
\r
2170 private void focusNote() {
\r
2171 browser.setFocus();
\r
2173 @SuppressWarnings("unused")
\r
2174 private void focusAuthor() {
\r
2175 authorLabel.setFocus();
\r
2177 @SuppressWarnings("unused")
\r
2178 private void focusUrl() {
\r
2179 urlLabel.setFocus();
\r
2183 //*****************************************************************
\r
2184 //* Set the document background color
\r
2185 //*****************************************************************
\r
2186 public void setBackgroundColor(String color) {
\r
2187 String js = "function changeBackground(color) {"
\r
2188 +"document.body.style.background = color;"
\r
2190 +"changeBackground('" +color+"');";
\r
2191 browser.page().mainFrame().evaluateJavaScript(js);
\r
2196 //****************************************************************
\r
2197 //* MicroFocus changed
\r
2198 //****************************************************************
\r
2199 private void microFocusChanged() {
\r
2200 boldButton.setDown(false);
\r
2201 italicButton.setDown(false);
\r
2202 underlineButton.setDown(false);
\r
2203 browser.openAction.setEnabled(false);
\r
2204 browser.downloadAttachment.setEnabled(false);
\r
2205 browser.downloadImage.setEnabled(false);
\r
2206 browser.rotateImageLeft.setEnabled(false);
\r
2207 browser.rotateImageRight.setEnabled(false);
\r
2208 browser.insertTableAction.setEnabled(true);
\r
2209 browser.insertTableRowAction.setEnabled(false);
\r
2210 browser.deleteTableRowAction.setEnabled(false);
\r
2211 browser.insertLinkAction.setText(tr("Insert Hyperlink"));
\r
2212 currentHyperlink ="";
\r
2213 insideList = false;
\r
2214 forceTextPaste = false;
\r
2216 String js = new String( "function getCursorPos() {"
\r
2218 +"if (window.getSelection) {"
\r
2219 +" var selObj = window.getSelection();"
\r
2220 +" var selRange = selObj.getRangeAt(0);"
\r
2221 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2222 +" while(workingNode != null) { "
\r
2223 // +" window.jambi.printNode(workingNode.nodeName);"
\r
2224 +" if (workingNode.nodeName=='EN-CRYPT-TEMP') window.jambi.forceTextPaste();"
\r
2225 +" if (workingNode.nodeName=='B') window.jambi.boldActive();"
\r
2226 +" if (workingNode.nodeName=='I') window.jambi.italicActive();"
\r
2227 +" if (workingNode.nodeName=='U') window.jambi.underlineActive();"
\r
2228 +" if (workingNode.nodeName=='UL') window.jambi.setInsideList();"
\r
2229 +" if (workingNode.nodeName=='OL') window.jambi.setInsideList();"
\r
2230 +" if (workingNode.nodeName=='LI') window.jambi.setInsideList();"
\r
2231 +" if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"
\r
2232 +" 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
2233 +" if (workingNode.nodeName=='SPAN') {"
\r
2234 +" if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"
\r
2236 +" workingNode = workingNode.parentNode;"
\r
2239 +"} getCursorPos();");
\r
2240 browser.page().mainFrame().evaluateJavaScript(js);
\r
2243 public void printNode(String n) {
\r
2244 System.out.println("Node Vaule: " +n);
\r
2248 //****************************************************************
\r
2249 //* Insert a table row
\r
2250 //****************************************************************
\r
2251 public void insertTableRow() {
\r
2253 String js = new String( "function insertTableRow() {"
\r
2254 +" var selObj = window.getSelection();"
\r
2255 +" var selRange = selObj.getRangeAt(0);"
\r
2256 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2257 +" var cellCount = 0;"
\r
2258 +" while(workingNode != null) { "
\r
2259 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2260 +" row = document.createElement('TR');"
\r
2261 +" var nodes = workingNode.getElementsByTagName('td');"
\r
2262 +" for (j=0; j<nodes.length; j=j+1) {"
\r
2263 +" cell = document.createElement('TD');"
\r
2264 +" cell.innerHTML=' ';"
\r
2265 +" row.appendChild(cell);"
\r
2267 +" workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"
\r
2270 +" workingNode = workingNode.parentNode;"
\r
2272 +"} insertTableRow();");
\r
2273 browser.page().mainFrame().evaluateJavaScript(js);
\r
2276 //****************************************************************
\r
2277 //* Insert a table row
\r
2278 //****************************************************************
\r
2279 public void deleteTableRow() {
\r
2281 String js = new String( "function deleteTableRow() {"
\r
2282 +" var selObj = window.getSelection();"
\r
2283 +" var selRange = selObj.getRangeAt(0);"
\r
2284 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2285 +" var cellCount = 0;"
\r
2286 +" while(workingNode != null) { "
\r
2287 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2288 +" workingNode.parentNode.removeChild(workingNode);"
\r
2291 +" workingNode = workingNode.parentNode;"
\r
2293 +"} deleteTableRow();");
\r
2294 browser.page().mainFrame().evaluateJavaScript(js);
\r
2297 public void setInsideTable() {
\r
2298 browser.insertTableRowAction.setEnabled(true);
\r
2299 browser.deleteTableRowAction.setEnabled(true);
\r
2300 browser.insertTableAction.setEnabled(false);
\r
2301 browser.encryptAction.setEnabled(false);
\r
2304 public void setInsideLink(String link) {
\r
2305 browser.insertLinkAction.setText(tr("Edit Hyperlink"));
\r
2306 currentHyperlink = link;
\r
2309 public void italicActive() {
\r
2310 italicButton.setDown(true);
\r
2312 public void boldActive() {
\r
2313 boldButton.setDown(true);
\r
2315 public void underlineActive() {
\r
2316 underlineButton.setDown(true);
\r
2318 public void forceTextPaste() {
\r
2319 forceTextPaste = true;
\r
2321 public void imageContextMenu(String f) {
\r
2322 browser.downloadImage.setEnabled(true);
\r
2323 browser.rotateImageRight.setEnabled(true);
\r
2324 browser.rotateImageLeft.setEnabled(true);
\r
2325 browser.openAction.setEnabled(true);
\r
2328 public void rotateImageRight() {
\r
2329 QWebSettings.setMaximumPagesInCache(0);
\r
2330 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2331 QImage image = new QImage(selectedFile);
\r
2332 QMatrix matrix = new QMatrix();
\r
2333 matrix.rotate( 90.0 );
\r
2334 image = image.transformed(matrix);
\r
2335 image.save(selectedFile);
\r
2336 QWebSettings.setMaximumPagesInCache(0);
\r
2337 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2338 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2341 // resourceSignal.contentChanged.emit(selectedFile);
\r
2344 public void rotateImageLeft() {
\r
2345 QImage image = new QImage(selectedFile);
\r
2346 QMatrix matrix = new QMatrix();
\r
2347 matrix.rotate( -90.0 );
\r
2348 image = image.transformed(matrix);
\r
2349 image.save(selectedFile);
\r
2350 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2353 // resourceSignal.contentChanged.emit(selectedFile);
\r
2355 public void resourceContextMenu(String f) {
\r
2356 browser.downloadAttachment.setEnabled(true);
\r
2357 browser.openAction.setEnabled(true);
\r
2362 //****************************************************************
\r
2363 //* Apply CSS style to specified word
\r
2364 //****************************************************************
\r
2365 /* public void applyStyleToWords(String word, String style) {
\r
2366 QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");
\r
2367 script.open(OpenModeFlag.ReadOnly);
\r
2368 String s = script.readAll().toString();
\r
2369 String js = new String(s +" findit('"+word+"', '"+style+"');");
\r
2370 browser.page().mainFrame().evaluateJavaScript(js);
\r
2371 System.out.println(getContent());
\r
2374 //****************************************************************
\r
2375 //* Someone tried to paste a resource between notes, so we need *
\r
2376 //* to do some special handling. *
\r
2377 //****************************************************************
\r
2378 private String fixInternotePaste(String text) {
\r
2379 logger.log(logger.EXTREME, "Fixing internote paste");
\r
2380 String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");
\r
2381 return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");
\r
2383 private String fixInternotePasteSearch(String text, String type, String locTag) {
\r
2385 // First, let's fix the images.
\r
2386 int startPos = text.indexOf(type);
\r
2388 for (; startPos>=0;) {
\r
2389 endPos = text.indexOf(">", startPos+1);
\r
2390 String segment = text.substring(startPos, endPos);
\r
2391 if (segment.indexOf("en-tag") > -1) {
\r
2392 String newSegment = segment;
\r
2394 int guidStartPos = segment.indexOf("guid=\"");
\r
2395 int guidEndPos = segment.indexOf("\"", guidStartPos+7);
\r
2396 String guid = segment.substring(guidStartPos+6,guidEndPos);
\r
2398 int mimeStartPos = segment.indexOf("type");
\r
2399 int mimeEndPos = segment.indexOf("\"", mimeStartPos+7);
\r
2400 String mime = segment.substring(mimeStartPos+6,mimeEndPos);
\r
2402 int srcStartPos = segment.indexOf("src");
\r
2403 int srcEndPos = segment.indexOf("\"", srcStartPos+6);
\r
2404 String src = segment.substring(srcStartPos+5,srcEndPos);
\r
2406 Calendar currentTime = new GregorianCalendar();
\r
2407 Long l = new Long(currentTime.getTimeInMillis());
\r
2408 long prevTime = l;
\r
2409 while (l==prevTime) {
\r
2410 currentTime = new GregorianCalendar();
\r
2411 l= new Long(currentTime.getTimeInMillis());
\r
2414 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2415 // if r==null, then the image doesn't exist (it was probably cut out of another note, so
\r
2416 // we need to recereate it
\r
2418 r = createResource(src, 1, mime, false);
\r
2422 String randint = new String(Long.toString(l));
\r
2423 String extension = null;
\r
2424 if (r.getMime()!= null) {
\r
2425 extension = r.getMime().toLowerCase();
\r
2426 if (extension.indexOf("/")>-1)
\r
2427 extension = extension.substring(extension.indexOf("/")+1);
\r
2429 String newFile = randint;
\r
2430 if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")
\r
2431 if (!locTag.startsWith("src"))
\r
2432 newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();
\r
2433 r.setNoteGuid(currentNote.getGuid());
\r
2435 r.setGuid(randint);
\r
2436 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
2437 QFile f = new QFile(Global.getFileManager().getResDirPath(newFile));
\r
2438 QByteArray bin = new QByteArray(r.getData().getBody());
\r
2439 f.open(QFile.OpenModeFlag.WriteOnly);
\r
2442 newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);
\r
2443 currentNote.getResources().add(r);
\r
2445 int startSrcPos = newSegment.indexOf(locTag);
\r
2446 int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);
\r
2448 if (locTag.startsWith("src")) {
\r
2449 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2450 newSegment = newSegment.replace(source,
\r
2451 FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath(newFile)));
\r
2453 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2454 newSegment = newSegment.replace(source, newFile);
\r
2457 text = text.substring(0,startPos) + newSegment + text.substring(endPos);
\r
2459 startPos = text.indexOf(type, startPos+1);
\r
2465 public void nextPage(String file) {
\r
2466 logger.log(logger.EXTREME, "Starting nextPage()");
\r
2468 Integer pageNumber;
\r
2469 if (previewPageList.containsKey(file))
\r
2470 pageNumber = previewPageList.get(file)+1;
\r
2473 previewPageList.remove(file);
\r
2474 previewPageList.put(file, pageNumber);
\r
2475 PDFPreview pdfPreview = new PDFPreview();
\r
2476 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2477 if (goodPreview) {
\r
2479 // String html = getContent();
\r
2480 QWebSettings.setMaximumPagesInCache(0);
\r
2481 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2482 // browser.setContent(new QByteArray());
\r
2483 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2485 // browser.setContent(new QByteArray(html));
\r
2486 // browser.triggerPageAction(WebAction.Reload);
\r
2487 // pdfMouseOver(selectedFile);
\r
2491 public void previousPage(String file) {
\r
2492 logger.log(logger.EXTREME, "Starting previousPage()");
\r
2494 Integer pageNumber;
\r
2495 if (previewPageList.containsKey(file))
\r
2496 pageNumber = previewPageList.get(file)-1;
\r
2499 previewPageList.remove(file);
\r
2500 previewPageList.put(file, pageNumber);
\r
2501 PDFPreview pdfPreview = new PDFPreview();
\r
2502 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2503 if (goodPreview) {
\r
2505 // String html = getContent();
\r
2506 QWebSettings.setMaximumPagesInCache(0);
\r
2507 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2508 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2510 // browser.setContent(new QByteArray(html));
\r
2511 // browser.triggerPageAction(WebAction.Reload);
\r
2515 /* public void pdfMouseOver(String name) {
\r
2517 if (previewPageList.containsKey(selectedFile))
\r
2518 pageNumber = previewPageList.get(selectedFile)+1;
\r
2522 if (pageNumber <= 1)
\r
2523 browser.previousPageAction.setEnabled(false);
\r
2525 browser.previousPageAction.setEnabled(true);
\r
2527 PDFPreview pdf = new PDFPreview();
\r
2528 int totalPages = pdf.getPageCount(name);
\r
2529 if (previewPageList.containsKey(selectedFile))
\r
2530 pageNumber = previewPageList.get(selectedFile)+1;
\r
2533 if (totalPages > pageNumber)
\r
2534 browser.nextPageAction.setEnabled(true);
\r
2536 browser.nextPageAction.setEnabled(false);
\r
2540 public void pdfMouseOut() {
\r
2541 // browser.nextPageAction.setVisible(false);
\r
2542 // browser.previousPageAction.setVisible(false);
\r
2546 private void toggleUndoVisible(Boolean toggle) {
\r
2547 undoAction.setVisible(toggle);
\r
2548 Global.saveEditorButtonsVisible("undo", toggle);
\r
2550 private void toggleRedoVisible(Boolean toggle) {
\r
2551 redoAction.setVisible(toggle);
\r
2552 Global.saveEditorButtonsVisible("redo", toggle);
\r
2554 private void toggleCutVisible(Boolean toggle) {
\r
2555 cutAction.setVisible(toggle);
\r
2556 Global.saveEditorButtonsVisible("cut", toggle);
\r
2558 private void toggleCopyVisible(Boolean toggle) {
\r
2559 copyAction.setVisible(toggle);
\r
2560 Global.saveEditorButtonsVisible("copy", toggle);
\r
2562 private void togglePasteVisible(Boolean toggle) {
\r
2563 pasteAction.setVisible(toggle);
\r
2564 Global.saveEditorButtonsVisible("paste", toggle);
\r
2566 private void toggleBoldVisible(Boolean toggle) {
\r
2567 boldAction.setVisible(toggle);
\r
2568 Global.saveEditorButtonsVisible("bold", toggle);
\r
2570 private void toggleItalicVisible(Boolean toggle) {
\r
2571 italicAction.setVisible(toggle);
\r
2572 Global.saveEditorButtonsVisible("italic", toggle);
\r
2574 private void toggleUnderlineVisible(Boolean toggle) {
\r
2575 underlineAction.setVisible(toggle);
\r
2576 Global.saveEditorButtonsVisible("underline", toggle);
\r
2578 private void toggleStrikethroughVisible(Boolean toggle) {
\r
2579 strikethroughAction.setVisible(toggle);
\r
2580 Global.saveEditorButtonsVisible("strikethrough", toggle);
\r
2582 private void toggleLeftAlignVisible(Boolean toggle) {
\r
2583 leftAlignAction.setVisible(toggle);
\r
2584 Global.saveEditorButtonsVisible("alignLeft", toggle);
\r
2586 private void toggleRightAlignVisible(Boolean toggle) {
\r
2587 rightAlignAction.setVisible(toggle);
\r
2588 Global.saveEditorButtonsVisible("alignRight", toggle);
\r
2590 private void toggleCenterAlignVisible(Boolean toggle) {
\r
2591 centerAlignAction.setVisible(toggle);
\r
2592 Global.saveEditorButtonsVisible("alignCenter", toggle);
\r
2594 private void toggleHLineVisible(Boolean toggle) {
\r
2595 hlineAction.setVisible(toggle);
\r
2596 Global.saveEditorButtonsVisible("hline", toggle);
\r
2598 private void toggleIndentVisible(Boolean toggle) {
\r
2599 indentAction.setVisible(toggle);
\r
2600 Global.saveEditorButtonsVisible("indent", toggle);
\r
2602 private void toggleOutdentVisible(Boolean toggle) {
\r
2603 outdentAction.setVisible(toggle);
\r
2604 Global.saveEditorButtonsVisible("outdent", toggle);
\r
2606 private void toggleBulletListVisible(Boolean toggle) {
\r
2607 bulletListAction.setVisible(toggle);
\r
2608 Global.saveEditorButtonsVisible("bulletList", toggle);
\r
2610 private void toggleNumberListVisible(Boolean toggle) {
\r
2611 numberListAction.setVisible(toggle);
\r
2612 Global.saveEditorButtonsVisible("numberList", toggle);
\r
2614 private void toggleFontListVisible(Boolean toggle) {
\r
2615 fontListAction.setVisible(toggle);
\r
2616 Global.saveEditorButtonsVisible("font", toggle);
\r
2618 private void toggleFontColorVisible(Boolean toggle) {
\r
2619 fontColorAction.setVisible(toggle);
\r
2620 Global.saveEditorButtonsVisible("fontColor", toggle);
\r
2622 private void toggleFontSizeVisible(Boolean toggle) {
\r
2623 fontSizeAction.setVisible(toggle);
\r
2624 Global.saveEditorButtonsVisible("fontSize", toggle);
\r
2626 private void toggleFontHilightVisible(Boolean toggle) {
\r
2627 fontHilightAction.setVisible(toggle);
\r
2628 Global.saveEditorButtonsVisible("fontHilight", toggle);
\r
2632 // Invoke spell checker dialog
\r
2633 private void doSpellCheck() {
\r
2635 File wordList = new File(Global.getFileManager().getSpellDirPath()+Locale.getDefault()+".dic");
\r
2636 SpellDictionary dictionary;
\r
2638 dictionary = new SpellDictionaryHashMap(wordList);
\r
2639 SpellChecker spellChecker = new SpellChecker(dictionary);
\r
2640 SuggestionListener spellListener = new SuggestionListener(this);
\r
2641 spellChecker.addSpellCheckListener(spellListener);
\r
2643 String content = getBrowser().page().mainFrame().toPlainText();
\r
2644 StringWordTokenizer tokenizer = new StringWordTokenizer(content);
\r
2645 if (!tokenizer.hasMoreWords())
\r
2647 String word = tokenizer.nextWord();
\r
2648 getBrowser().page().action(WebAction.MoveToStartOfDocument);
\r
2649 QWebPage.FindFlags flags = new QWebPage.FindFlags();
\r
2650 flags.set(QWebPage.FindFlag.FindBackward);
\r
2652 getBrowser().setFocus();
\r
2653 boolean found = getBrowser().page().findText(word);
\r
2655 QMessageBox.critical(this, tr("Spell Check Error"),
\r
2656 tr("An error has occurred while launching the spell check. The most probable" +
\r
2657 " cause is that the cursor was not at the beginning of the document.\n\n" +
\r
2658 "Please place the cursor at the beginning & try again"));
\r
2662 found = getBrowser().page().findText(word);
\r
2665 spellChecker.checkSpelling(new StringWordTokenizer(word));
\r
2666 getBrowser().setFocus();
\r
2668 flags = new QWebPage.FindFlags();
\r
2669 tokenizer = new StringWordTokenizer(content);
\r
2671 while(tokenizer.hasMoreWords()) {
\r
2672 word = tokenizer.nextWord();
\r
2673 found = getBrowser().page().findText(word);
\r
2674 if (found && !spellListener.abortSpellCheck) {
\r
2675 spellChecker.checkSpelling(new StringWordTokenizer(word));
\r
2676 getBrowser().setFocus();
\r
2679 spellChecker.removeSpellCheckListener(spellListener);
\r
2680 if (!spellListener.errorsFound)
\r
2681 QMessageBox.information(this, tr("Spell Check Complete"),
\r
2682 tr("No spelling errors found"));
\r
2683 } catch (FileNotFoundException e) {
\r
2684 QMessageBox.critical(this, tr("Spell Check Error"),
\r
2685 tr("Dictionary "+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
2686 ".dic was not found."));
\r
2687 } catch (IOException e) {
\r
2688 QMessageBox.critical(this, tr("Spell Check Error"),
\r
2689 tr("Dictionary "+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
2690 ".dic is invalid."));
\r