2 * This file is part of NeverNote
\r
3 * Copyright 2009 Randy Baumgarte
\r
5 * This file may be licensed under the terms of of the
\r
6 * GNU General Public License Version 2 (the ``GPL'').
\r
8 * Software distributed under the License is distributed
\r
9 * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
\r
10 * express or implied. See the GPL for the specific language
\r
11 * governing rights and limitations.
\r
13 * You should have received a copy of the GPL along with this
\r
14 * program. If not, go to http://www.gnu.org/licenses/gpl.html
\r
15 * or write to the Free Software Foundation, Inc.,
\r
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
\r
20 package cx.fbn.nevernote.gui;
\r
22 import java.io.File;
\r
23 import java.io.FileNotFoundException;
\r
24 import java.io.IOException;
\r
25 import java.net.FileNameMap;
\r
26 import java.net.URI;
\r
27 import java.net.URLConnection;
\r
28 import java.security.MessageDigest;
\r
29 import java.security.NoSuchAlgorithmException;
\r
30 import java.text.SimpleDateFormat;
\r
31 import java.util.ArrayList;
\r
32 import java.util.Calendar;
\r
33 import java.util.Collections;
\r
34 import java.util.Date;
\r
35 import java.util.GregorianCalendar;
\r
36 import java.util.HashMap;
\r
37 import java.util.List;
\r
38 import java.util.Locale;
\r
40 import org.apache.commons.lang.StringUtils;
\r
42 import com.evernote.edam.limits.Constants;
\r
43 import com.evernote.edam.type.Data;
\r
44 import com.evernote.edam.type.Note;
\r
45 import com.evernote.edam.type.Notebook;
\r
46 import com.evernote.edam.type.Resource;
\r
47 import com.evernote.edam.type.ResourceAttributes;
\r
48 import com.evernote.edam.type.Tag;
\r
49 import com.swabunga.spell.engine.SpellDictionary;
\r
50 import com.swabunga.spell.engine.SpellDictionaryHashMap;
\r
51 import com.swabunga.spell.engine.Word;
\r
52 import com.swabunga.spell.event.SpellCheckEvent;
\r
53 import com.swabunga.spell.event.SpellCheckListener;
\r
54 import com.swabunga.spell.event.SpellChecker;
\r
55 import com.swabunga.spell.event.StringWordTokenizer;
\r
56 import com.trolltech.qt.core.QByteArray;
\r
57 import com.trolltech.qt.core.QDataStream;
\r
58 import com.trolltech.qt.core.QDateTime;
\r
59 import com.trolltech.qt.core.QEvent;
\r
60 import com.trolltech.qt.core.QFile;
\r
61 import com.trolltech.qt.core.QFileSystemWatcher;
\r
62 import com.trolltech.qt.core.QIODevice;
\r
63 import com.trolltech.qt.core.QMimeData;
\r
64 import com.trolltech.qt.core.QUrl;
\r
65 import com.trolltech.qt.gui.QAction;
\r
66 import com.trolltech.qt.gui.QApplication;
\r
67 import com.trolltech.qt.gui.QCalendarWidget;
\r
68 import com.trolltech.qt.gui.QClipboard;
\r
69 import com.trolltech.qt.gui.QColor;
\r
70 import com.trolltech.qt.gui.QComboBox;
\r
71 import com.trolltech.qt.gui.QDateEdit;
\r
72 import com.trolltech.qt.gui.QDesktopServices;
\r
73 import com.trolltech.qt.gui.QFileDialog;
\r
74 import com.trolltech.qt.gui.QFileDialog.AcceptMode;
\r
75 import com.trolltech.qt.gui.QFileDialog.FileMode;
\r
76 import com.trolltech.qt.gui.QFontDatabase;
\r
77 import com.trolltech.qt.gui.QFormLayout;
\r
78 import com.trolltech.qt.gui.QGridLayout;
\r
79 import com.trolltech.qt.gui.QHBoxLayout;
\r
80 import com.trolltech.qt.gui.QIcon;
\r
81 import com.trolltech.qt.gui.QImage;
\r
82 import com.trolltech.qt.gui.QKeySequence;
\r
83 import com.trolltech.qt.gui.QLabel;
\r
84 import com.trolltech.qt.gui.QLineEdit;
\r
85 import com.trolltech.qt.gui.QListWidgetItem;
\r
86 import com.trolltech.qt.gui.QMatrix;
\r
87 import com.trolltech.qt.gui.QMessageBox;
\r
88 import com.trolltech.qt.gui.QPushButton;
\r
89 import com.trolltech.qt.gui.QShortcut;
\r
90 import com.trolltech.qt.gui.QTimeEdit;
\r
91 import com.trolltech.qt.gui.QToolButton;
\r
92 import com.trolltech.qt.gui.QToolButton.ToolButtonPopupMode;
\r
93 import com.trolltech.qt.gui.QVBoxLayout;
\r
94 import com.trolltech.qt.gui.QWidget;
\r
95 import com.trolltech.qt.network.QNetworkRequest;
\r
96 import com.trolltech.qt.webkit.QWebPage;
\r
97 import com.trolltech.qt.webkit.QWebPage.WebAction;
\r
98 import com.trolltech.qt.webkit.QWebSettings;
\r
99 import com.trolltech.qt.webkit.QWebView;
\r
101 import cx.fbn.nevernote.Global;
\r
102 import cx.fbn.nevernote.dialog.EnCryptDialog;
\r
103 import cx.fbn.nevernote.dialog.EnDecryptDialog;
\r
104 import cx.fbn.nevernote.dialog.GeoDialog;
\r
105 import cx.fbn.nevernote.dialog.InsertLinkDialog;
\r
106 import cx.fbn.nevernote.dialog.SpellCheck;
\r
107 import cx.fbn.nevernote.dialog.TableDialog;
\r
108 import cx.fbn.nevernote.dialog.TagAssign;
\r
109 import cx.fbn.nevernote.evernote.EnCrypt;
\r
110 import cx.fbn.nevernote.signals.NoteResourceSignal;
\r
111 import cx.fbn.nevernote.signals.NoteSignal;
\r
112 import cx.fbn.nevernote.sql.DatabaseConnection;
\r
113 import cx.fbn.nevernote.utilities.ApplicationLogger;
\r
114 import cx.fbn.nevernote.utilities.FileUtils;
\r
116 public class BrowserWindow extends QWidget {
\r
118 public final QLineEdit titleLabel;
\r
119 private final QLineEdit urlText;
\r
120 private final QLabel authorLabel;
\r
121 private final QLineEdit authorText;
\r
122 private final QComboBox geoBox;
\r
123 public final TagLineEdit tagEdit;
\r
124 public final QLabel tagLabel;
\r
125 private final QPushButton urlLabel;
\r
126 private final QLabel alteredLabel;
\r
127 private final QDateEdit alteredDate;
\r
128 private final QTimeEdit alteredTime;
\r
129 private final QDateEdit createdDate;
\r
130 private final QTimeEdit createdTime;
\r
131 private final QLabel subjectLabel;
\r
132 private final QDateEdit subjectDate;
\r
133 private final QTimeEdit subjectTime;
\r
134 public final QComboBox notebookBox;
\r
135 private final QLabel notebookLabel;
\r
136 private final QLabel createdLabel;
\r
137 public final QComboBox fontSize;
\r
138 public final QAction fontSizeAction;
\r
139 private boolean extendedOn;
\r
140 public boolean buttonsVisible;
\r
141 private final String iconPath = new String("classpath:cx/fbn/nevernote/icons/");
\r
142 private final ContentView browser;
\r
143 private List<Tag> allTags;
\r
144 private List<String> currentTags;
\r
145 public NoteSignal noteSignal;
\r
146 private List<Notebook> notebookList;
\r
147 private Note currentNote;
\r
148 private String saveNoteTitle;
\r
149 private String saveTagList;
\r
150 private boolean insideList;
\r
151 // private String selectedText;
\r
152 private final DatabaseConnection conn;
\r
153 private final QCalendarWidget createdCalendarWidget;
\r
154 private final QCalendarWidget alteredCalendarWidget;
\r
155 private final QCalendarWidget subjectCalendarWidget;
\r
157 public final QPushButton undoButton;
\r
158 public final QAction undoAction;
\r
159 public final QPushButton redoButton;
\r
160 public final QAction redoAction;
\r
161 public final QPushButton cutButton;
\r
162 public final QAction cutAction;
\r
163 public final QPushButton copyButton;
\r
164 public final QAction copyAction;
\r
165 public final QPushButton pasteButton;
\r
166 public final QAction pasteAction;
\r
167 public final QPushButton boldButton;
\r
168 public final QAction boldAction;
\r
169 public final QPushButton underlineButton;
\r
170 public final QAction underlineAction;
\r
171 public final QPushButton italicButton;
\r
172 public final QAction italicAction;
\r
173 public final Signal0 focusLost;
\r
174 public final NoteResourceSignal resourceSignal;
\r
176 public QPushButton rightAlignButton;
\r
177 public final QAction rightAlignAction;
\r
178 public QPushButton leftAlignButton;
\r
179 public final QAction leftAlignAction;
\r
180 public QPushButton centerAlignButton;
\r
181 public final QAction centerAlignAction;
\r
183 public final QPushButton strikethroughButton;
\r
184 public final QAction strikethroughAction;
\r
185 public final QPushButton hlineButton;
\r
186 public final QAction hlineAction;
\r
187 public final QPushButton indentButton;
\r
188 public final QAction indentAction;
\r
189 public final QPushButton outdentButton;
\r
190 public final QAction outdentAction;
\r
191 public final QPushButton bulletListButton;
\r
192 public final QAction bulletListAction;
\r
193 public final QPushButton numberListButton;
\r
194 public final QAction numberListAction;
\r
196 public final QShortcut focusTitleShortcut;
\r
197 public final QShortcut focusTagShortcut;
\r
198 public final QShortcut focusNoteShortcut;
\r
199 public final QShortcut focusUrlShortcut;
\r
200 public final QShortcut focusAuthorShortcut;
\r
202 public EditorButtonBar buttonLayout;
\r
203 public final QComboBox fontList;
\r
204 public final QAction fontListAction;
\r
205 public final QToolButton fontColor;
\r
206 public final QAction fontColorAction;
\r
207 private final ColorMenu fontColorMenu;
\r
208 public final QToolButton fontHilight;
\r
209 public final QAction fontHilightAction;
\r
210 private final ColorMenu fontHilightColorMenu;
\r
211 public final QFileSystemWatcher fileWatcher;
\r
212 public int cursorPosition;
\r
213 private boolean forceTextPaste = false;
\r
214 private String selectedFile;
\r
215 private String currentHyperlink;
\r
216 public boolean keepPDFNavigationHidden;
\r
217 private final ApplicationLogger logger;
\r
219 private final HashMap<String,Integer> previewPageList;
\r
222 public static class SuggestionListener implements SpellCheckListener {
\r
223 public boolean abortSpellCheck = false;
\r
224 public boolean errorsFound = false;
\r
226 private final BrowserWindow parent;
\r
227 public SuggestionListener(BrowserWindow parent) {
\r
228 this.parent = parent;
\r
230 public void spellingError(SpellCheckEvent event) {
\r
231 errorsFound = true;
\r
232 SpellCheck dialog = new SpellCheck();
\r
233 dialog.setWord(event.getInvalidWord());
\r
235 List<Word> suggestions = event.getSuggestions();
\r
236 if (suggestions.isEmpty()) {
\r
237 dialog.setNoSuggestions(true);
\r
239 dialog.setCurrentSuggestion(suggestions.get(0).getWord());
\r
240 for (int i=0; i<suggestions.size(); i++) {
\r
241 dialog.addSuggestion(suggestions.get(i).getWord());
\r
243 dialog.setSelectedSuggestion(0);
\r
246 if (dialog.cancelPressed()) {
\r
247 abortSpellCheck = true;
\r
250 if (dialog.replacePressed()) {
\r
251 QClipboard clipboard = QApplication.clipboard();
\r
252 clipboard.setText(dialog.getReplacementWord());
\r
253 parent.pasteClicked();
\r
260 public BrowserWindow(DatabaseConnection c) {
\r
261 logger = new ApplicationLogger("browser.log");
\r
262 logger.log(logger.HIGH, "Setting up browser");
\r
264 fileWatcher = new QFileSystemWatcher();
\r
265 // fileWatcher.fileChanged.connect(this, "fileChanged(String)");
\r
266 noteSignal = new NoteSignal();
\r
267 titleLabel = new QLineEdit();
\r
268 titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX);
\r
269 urlText = new QLineEdit();
\r
270 authorText = new QLineEdit();
\r
271 geoBox = new QComboBox();
\r
272 urlLabel = new QPushButton();
\r
273 urlLabel.clicked.connect(this, "sourceUrlClicked()");
\r
274 authorLabel = new QLabel();
\r
277 focusLost = new Signal0();
\r
279 tagEdit = new TagLineEdit(allTags);
\r
280 tagLabel = new QLabel("Tags:");
\r
281 tagEdit.focusLost.connect(this, "modifyTagsTyping()");
\r
283 createdCalendarWidget = new QCalendarWidget();
\r
284 createdDate = new QDateEdit();
\r
285 createdDate.setDisplayFormat(Global.getDateFormat());
\r
286 createdDate.setCalendarPopup(true);
\r
287 createdDate.setCalendarWidget(createdCalendarWidget);
\r
288 createdTime = new QTimeEdit();
\r
289 createdDate.dateChanged.connect(this, "createdChanged()");
\r
290 createdTime.timeChanged.connect(this, "createdChanged()");
\r
292 alteredCalendarWidget = new QCalendarWidget();
\r
293 alteredDate = new QDateEdit();
\r
294 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
295 alteredDate.setCalendarPopup(true);
\r
296 alteredDate.setCalendarWidget(alteredCalendarWidget);
\r
297 alteredTime = new QTimeEdit();
\r
298 alteredLabel = new QLabel("Altered:");
\r
299 alteredDate.dateChanged.connect(this, "alteredChanged()");
\r
300 alteredTime.timeChanged.connect(this, "alteredChanged()");
\r
302 subjectCalendarWidget = new QCalendarWidget();
\r
303 subjectDate = new QDateEdit();
\r
304 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
305 subjectDate.setCalendarPopup(true);
\r
306 subjectDate.setCalendarWidget(subjectCalendarWidget);
\r
307 subjectTime = new QTimeEdit();
\r
308 subjectLabel = new QLabel(tr("Subject Date:"));
\r
309 subjectDate.dateChanged.connect(this, "subjectDateTimeChanged()");
\r
310 subjectTime.timeChanged.connect(this, "subjectDateTimeChanged()");
\r
311 authorText.textChanged.connect(this, "authorChanged()");
\r
312 urlText.textChanged.connect(this, "sourceUrlChanged()");
\r
314 notebookBox = new QComboBox();
\r
315 notebookLabel = new QLabel(tr("Notebook"));
\r
316 createdLabel = new QLabel(tr("Created:"));
\r
317 // selectedText = new String();
\r
319 urlLabel.setVisible(false);
\r
320 urlText.setVisible(false);
\r
321 authorLabel.setVisible(false);
\r
323 geoBox.setVisible(false);
\r
324 geoBox.addItem(new QIcon(iconPath+"globe.png"), "");
\r
325 geoBox.addItem(new String(tr("Set")));
\r
326 geoBox.addItem(new String(tr("Clear")));
\r
327 geoBox.addItem(new String(tr("View On Map")));
\r
328 geoBox.activated.connect(this, "geoBoxChanged()");
\r
330 authorText.setVisible(false);
\r
331 createdDate.setVisible(false);
\r
332 alteredLabel.setVisible(false);
\r
333 //notebookBox.setVisible(false);
\r
334 notebookLabel.setVisible(false);
\r
335 createdLabel.setVisible(false);
\r
336 createdTime.setVisible(false);
\r
337 alteredDate.setVisible(false);
\r
338 alteredTime.setVisible(false);
\r
339 subjectLabel.setVisible(false);
\r
340 subjectDate.setVisible(false);
\r
341 subjectTime.setVisible(false);
\r
342 extendedOn = false;
\r
343 buttonsVisible = true;
\r
344 setAcceptDrops(true);
\r
346 browser = new ContentView(this);
\r
347 browser.page().setLinkDelegationPolicy(
\r
348 QWebPage.LinkDelegationPolicy.DelegateAllLinks);
\r
349 browser.linkClicked.connect(this, "linkClicked(QUrl)");
\r
350 currentHyperlink = "";
\r
352 QVBoxLayout v = new QVBoxLayout();
\r
353 QFormLayout notebookLayout = new QFormLayout();
\r
354 QGridLayout dateLayout = new QGridLayout();
\r
355 titleLabel.setReadOnly(false);
\r
356 titleLabel.editingFinished.connect(this, "titleEdited()");
\r
357 browser.page().contentsChanged.connect(this, "contentChanged()");
\r
358 browser.page().selectionChanged.connect(this, "selectionChanged()");
\r
359 browser.page().mainFrame().javaScriptWindowObjectCleared.connect(this,
\r
360 "exposeToJavascript()");
\r
362 notebookBox.activated.connect(this, "notebookChanged()");
\r
363 resourceSignal = new NoteResourceSignal();
\r
365 QHBoxLayout tagLayout = new QHBoxLayout();
\r
366 v.addWidget(titleLabel, 0);
\r
367 notebookLayout.addRow(notebookLabel, notebookBox);
\r
368 tagLayout.addLayout(notebookLayout, 0);
\r
369 tagLayout.stretch(4);
\r
370 tagLayout.addWidget(tagLabel, 0);
\r
371 tagLayout.addWidget(tagEdit, 1);
\r
372 v.addLayout(tagLayout);
\r
374 QHBoxLayout urlLayout = new QHBoxLayout();
\r
375 urlLayout.addWidget(urlLabel, 0);
\r
376 urlLayout.addWidget(urlText, 0);
\r
377 v.addLayout(urlLayout);
\r
379 QHBoxLayout authorLayout = new QHBoxLayout();
\r
380 authorLayout.addWidget(authorLabel, 0);
\r
381 authorLayout.addWidget(authorText, 0);
\r
382 authorLayout.addWidget(geoBox);
\r
383 v.addLayout(authorLayout);
\r
385 dateLayout.addWidget(createdLabel, 0, 0);
\r
386 dateLayout.addWidget(createdDate, 0, 1);
\r
387 dateLayout.addWidget(createdTime, 0, 2);
\r
388 dateLayout.setColumnStretch(9, 100);
\r
389 dateLayout.addWidget(alteredLabel, 0, 3);
\r
390 dateLayout.addWidget(alteredDate, 0, 4);
\r
391 dateLayout.addWidget(alteredTime, 0, 5);
\r
392 dateLayout.addWidget(subjectLabel, 0, 6);
\r
393 dateLayout.addWidget(subjectDate, 0, 7);
\r
394 dateLayout.addWidget(subjectTime, 0, 8);
\r
395 v.addLayout(dateLayout, 0);
\r
397 undoButton = newEditorButton("undo", tr("Undo Change"));
\r
398 redoButton = newEditorButton("redo", tr("Redo Change"));
\r
399 cutButton = newEditorButton("cut", tr("Cut"));
\r
400 copyButton = newEditorButton("copy", tr("Copy"));
\r
401 pasteButton = newEditorButton("paste", tr("Paste"));
\r
402 boldButton = newEditorButton("bold", tr("Bold"));
\r
403 underlineButton = newEditorButton("underline", tr("Underline"));
\r
404 italicButton = newEditorButton("italic", tr("Italic"));
\r
406 rightAlignButton = newEditorButton("justifyRight", tr("Right Align"));
\r
407 leftAlignButton = newEditorButton("justifyLeft", tr("Left Align"));
\r
408 centerAlignButton = newEditorButton("justifyCenter", tr("Center Align"));
\r
410 strikethroughButton = newEditorButton("strikethrough", tr("Strikethrough"));
\r
411 hlineButton = newEditorButton("hline", tr("Insert Horizontal Line"));
\r
412 indentButton = newEditorButton("indent", tr("Shift Right"));
\r
413 outdentButton = newEditorButton("outdent", tr("Shift Left"));
\r
414 bulletListButton = newEditorButton("bulletList", tr("Bullet List"));
\r
415 numberListButton = newEditorButton("numberList", tr("Number List"));
\r
418 buttonLayout = new EditorButtonBar();
\r
419 // buttonLayout.setSpacing(0);
\r
420 v.addWidget(buttonLayout);
\r
422 undoAction = buttonLayout.addWidget(undoButton);
\r
423 buttonLayout.toggleUndoVisible.triggered.connect(this, "toggleUndoVisible(Boolean)");
\r
424 redoAction = buttonLayout.addWidget(redoButton);
\r
425 buttonLayout.toggleRedoVisible.triggered.connect(this, "toggleRedoVisible(Boolean)");
\r
427 buttonLayout.addWidget(newSeparator());
\r
428 cutAction = buttonLayout.addWidget(cutButton);
\r
429 buttonLayout.toggleCutVisible.triggered.connect(this, "toggleCutVisible(Boolean)");
\r
430 copyAction = buttonLayout.addWidget(copyButton);
\r
431 buttonLayout.toggleCopyVisible.triggered.connect(this, "toggleCopyVisible(Boolean)");
\r
432 pasteAction = buttonLayout.addWidget(pasteButton);
\r
433 buttonLayout.togglePasteVisible.triggered.connect(this, "togglePasteVisible(Boolean)");
\r
435 buttonLayout.addWidget(newSeparator());
\r
436 boldAction = buttonLayout.addWidget(boldButton);
\r
437 buttonLayout.toggleBoldVisible.triggered.connect(this, "toggleBoldVisible(Boolean)");
\r
438 italicAction = buttonLayout.addWidget(italicButton);
\r
439 buttonLayout.toggleItalicVisible.triggered.connect(this, "toggleItalicVisible(Boolean)");
\r
440 underlineAction = buttonLayout.addWidget(underlineButton);
\r
441 buttonLayout.toggleUnderlineVisible.triggered.connect(this, "toggleUnderlineVisible(Boolean)");
\r
442 strikethroughAction = buttonLayout.addWidget(strikethroughButton);
\r
443 buttonLayout.toggleStrikethroughVisible.triggered.connect(this, "toggleStrikethroughVisible(Boolean)");
\r
446 buttonLayout.addWidget(newSeparator());
\r
447 leftAlignAction = buttonLayout.addWidget(leftAlignButton);
\r
448 buttonLayout.toggleLeftAlignVisible.triggered.connect(this, "toggleLeftAlignVisible(Boolean)");
\r
449 centerAlignAction = buttonLayout.addWidget(centerAlignButton);
\r
450 buttonLayout.toggleCenterAlignVisible.triggered.connect(this, "toggleCenterAlignVisible(Boolean)");
\r
451 rightAlignAction = buttonLayout.addWidget(rightAlignButton);
\r
452 buttonLayout.toggleRightAlignVisible.triggered.connect(this, "toggleRightAlignVisible(Boolean)");
\r
454 buttonLayout.addWidget(newSeparator());
\r
455 hlineAction = buttonLayout.addWidget(hlineButton);
\r
456 buttonLayout.toggleHLineVisible.triggered.connect(this, "toggleHLineVisible(Boolean)");
\r
458 indentAction = buttonLayout.addWidget(indentButton);
\r
459 buttonLayout.toggleIndentVisible.triggered.connect(this, "toggleIndentVisible(Boolean)");
\r
460 outdentAction = buttonLayout.addWidget(outdentButton);
\r
461 buttonLayout.toggleOutdentVisible.triggered.connect(this, "toggleOutdentVisible(Boolean)");
\r
462 bulletListAction = buttonLayout.addWidget(bulletListButton);
\r
463 buttonLayout.toggleBulletListVisible.triggered.connect(this, "toggleBulletListVisible(Boolean)");
\r
464 numberListAction = buttonLayout.addWidget(numberListButton);
\r
465 buttonLayout.toggleNumberListVisible.triggered.connect(this, "toggleNumberListVisible(Boolean)");
\r
467 // Setup the font & font size combo boxes
\r
468 buttonLayout.addWidget(newSeparator());
\r
469 fontList = new QComboBox();
\r
470 fontSize = new QComboBox();
\r
471 fontList.setToolTip("Font");
\r
472 fontSize.setToolTip("Font Size");
\r
473 fontList.activated.connect(this, "fontChanged(String)");
\r
474 fontSize.activated.connect(this, "fontSizeChanged(String)");
\r
475 fontListAction = buttonLayout.addWidget(fontList);
\r
476 buttonLayout.toggleFontVisible.triggered.connect(this, "toggleFontListVisible(Boolean)");
\r
477 fontSizeAction = buttonLayout.addWidget(fontSize);
\r
478 buttonLayout.toggleFontSizeVisible.triggered.connect(this, "toggleFontSizeVisible(Boolean)");
\r
479 QFontDatabase fonts = new QFontDatabase();
\r
480 List<String> fontFamilies = fonts.families();
\r
481 for (int i = 0; i < fontFamilies.size(); i++) {
\r
482 fontList.addItem(fontFamilies.get(i));
\r
484 loadFontSize(fontFamilies.get(i));
\r
488 // buttonLayout.addWidget(newSeparator(), 0);
\r
489 fontColor = newToolButton("fontColor", tr("Font Color"));
\r
490 fontColorMenu = new ColorMenu(this);
\r
491 fontColor.setMenu(fontColorMenu.getMenu());
\r
492 fontColor.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
493 fontColor.setAutoRaise(false);
\r
494 fontColorMenu.getMenu().triggered.connect(this, "fontColorClicked()");
\r
495 fontColorAction = buttonLayout.addWidget(fontColor);
\r
496 buttonLayout.toggleFontColorVisible.triggered.connect(this, "toggleFontColorVisible(Boolean)");
\r
497 fontHilight = newToolButton("fontHilight", tr("Font Hilight Color"));
\r
498 fontHilight.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
499 fontHilight.setAutoRaise(false);
\r
500 fontHilightColorMenu = new ColorMenu(this);
\r
501 fontHilightColorMenu.setDefault(QColor.yellow);
\r
502 fontHilight.setMenu(fontHilightColorMenu.getMenu());
\r
503 fontHilightColorMenu.getMenu().triggered.connect(this, "fontHilightClicked()");
\r
504 fontHilightAction = buttonLayout.addWidget(fontHilight);
\r
505 fontHilightColorMenu.setDefault(QColor.yellow);
\r
506 buttonLayout.toggleFontHilight.triggered.connect(this, "toggleFontHilightVisible(Boolean)");
\r
508 // buttonLayout.addWidget(new QLabel(), 1);
\r
509 v.addWidget(browser, 1);
\r
512 browser.downloadAttachmentRequested.connect(this,
\r
513 "downloadAttachment(QNetworkRequest)");
\r
514 browser.downloadImageRequested.connect(this,
\r
515 "downloadImage(QNetworkRequest)");
\r
516 setTabOrder(notebookBox, tagEdit);
\r
517 setTabOrder(tagEdit, browser);
\r
519 focusNoteShortcut = new QShortcut(this);
\r
520 setupShortcut(focusNoteShortcut, "Focus_Note");
\r
521 focusNoteShortcut.activated.connect(this, "focusNote()");
\r
522 focusTitleShortcut = new QShortcut(this);
\r
523 setupShortcut(focusTitleShortcut, "Focus_Title");
\r
524 focusTitleShortcut.activated.connect(this, "focusTitle()");
\r
525 focusTagShortcut = new QShortcut(this);
\r
526 setupShortcut(focusTagShortcut, "Focus_Tag");
\r
527 focusTagShortcut.activated.connect(this, "focusTag()");
\r
528 focusAuthorShortcut = new QShortcut(this);
\r
529 setupShortcut(focusAuthorShortcut, "Focus_Author");
\r
530 focusAuthorShortcut.activated.connect(this, "focusAuthor()");
\r
531 focusUrlShortcut = new QShortcut(this);
\r
532 setupShortcut(focusUrlShortcut, "Focus_Url");
\r
533 focusUrlShortcut.activated.connect(this, "focusUrl()");
\r
535 browser.page().mainFrame().setTextSizeMultiplier(Global.getTextSizeMultiplier());
\r
536 browser.page().mainFrame().setZoomFactor(Global.getZoomFactor());
\r
538 previewPageList = new HashMap<String,Integer>();
\r
540 browser.page().microFocusChanged.connect(this, "microFocusChanged()");
\r
542 logger.log(logger.HIGH, "Browser setup complete");
\r
547 private void setupShortcut(QShortcut action, String text) {
\r
548 if (!Global.shortcutKeys.containsAction(text))
\r
550 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
\r
556 // Getter for the QWebView
\r
557 public QWebView getBrowser() {
\r
561 // Block signals while loading data or things are flagged as dirty by
\r
563 public void loadingData(boolean val) {
\r
564 logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val);
\r
565 notebookBox.blockSignals(val);
\r
566 browser.page().blockSignals(val);
\r
567 browser.page().mainFrame().blockSignals(val);
\r
568 titleLabel.blockSignals(val);
\r
569 alteredDate.blockSignals(val);
\r
570 alteredTime.blockSignals(val);
\r
571 createdTime.blockSignals(val);
\r
572 createdDate.blockSignals(val);
\r
573 subjectDate.blockSignals(val);
\r
574 subjectTime.blockSignals(val);
\r
575 urlText.blockSignals(val);
\r
576 authorText.blockSignals(val);
\r
578 exposeToJavascript();
\r
579 logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val);
\r
583 public void setReadOnly(boolean v) {
\r
585 titleLabel.setEnabled(!v);
\r
586 notebookBox.setEnabled(!v);
\r
587 tagEdit.setEnabled(!v);
\r
588 authorLabel.setEnabled(!v);
\r
589 geoBox.setEnabled(!v);
\r
590 urlText.setEnabled(!v);
\r
591 createdDate.setEnabled(!v);
\r
592 subjectDate.setEnabled(!v);
\r
593 alteredDate.setEnabled(!v);
\r
594 getBrowser().setEnabled(true);
\r
597 // expose this class to Javascript on the web page
\r
598 private void exposeToJavascript() {
\r
599 browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this);
\r
602 // Custom event queue
\r
604 public boolean event(QEvent e) {
\r
605 if (e.type().equals(QEvent.Type.FocusOut)) {
\r
606 logger.log(logger.EXTREME, "Focus lost");
\r
609 return super.event(e);
\r
612 // clear out browser
\r
613 public void clear() {
\r
614 logger.log(logger.EXTREME, "Entering BrowserWindow.clear()");
\r
616 browser.setContent(new QByteArray());
\r
617 tagEdit.setText("");
\r
618 tagEdit.tagCompleter.reset();
\r
619 urlLabel.setText(tr("Source URL:"));
\r
620 titleLabel.setText("");
\r
621 logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()");
\r
624 // get/set current note
\r
625 public void setNote(Note n) {
\r
629 saveNoteTitle = n.getTitle();
\r
633 public Note getNote() {
\r
634 return currentNote;
\r
637 // New Editor Button
\r
638 private QPushButton newEditorButton(String name, String toolTip) {
\r
639 QPushButton button = new QPushButton();
\r
640 QIcon icon = new QIcon(iconPath + name + ".gif");
\r
641 button.setIcon(icon);
\r
642 button.setToolTip(toolTip);
\r
643 button.clicked.connect(this, name + "Clicked()");
\r
646 // New Editor Button
\r
647 private QToolButton newToolButton(String name, String toolTip) {
\r
648 QToolButton button = new QToolButton();
\r
649 QIcon icon = new QIcon(iconPath + name + ".gif");
\r
650 button.setIcon(icon);
\r
651 button.setToolTip(toolTip);
\r
652 button.clicked.connect(this, name + "Clicked()");
\r
657 private QLabel newSeparator() {
\r
658 return new QLabel(" ");
\r
661 // Set the title in the window
\r
662 public void setTitle(String t) {
\r
663 titleLabel.setText(t);
\r
668 // Return the current text title
\r
669 public String getTitle() {
\r
670 return titleLabel.text();
\r
673 // Set the tag name string
\r
674 public void setTag(String t) {
\r
676 tagEdit.setText(t);
\r
677 tagEdit.tagCompleter.reset();
\r
680 // Set the source URL
\r
681 public void setUrl(String t) {
\r
682 urlLabel.setText(tr("Source URL:\t"));
\r
683 urlText.setText(t);
\r
686 // The user want's to launch a web browser on the source of the URL
\r
687 public void sourceUrlClicked() {
\r
688 // Make sure we have a valid URL
\r
689 if (urlText.text().trim().equals(""))
\r
692 String url = urlText.text();
\r
693 if (!url.toLowerCase().startsWith(tr("http://")))
\r
694 url = tr("http://") +url;
\r
696 if (!QDesktopServices.openUrl(new QUrl(url))) {
\r
697 logger.log(logger.LOW, "Error opening file :" +url);
\r
701 public void setAuthor(String t) {
\r
702 authorLabel.setText(tr("Author:\t"));
\r
703 authorText.setText(t);
\r
706 // Set the creation date
\r
707 public void setCreation(long date) {
\r
708 QDateTime dt = new QDateTime();
\r
709 dt.setTime_t((int) (date / 1000));
\r
710 createdDate.setDateTime(dt);
\r
711 createdTime.setDateTime(dt);
\r
712 createdDate.setDisplayFormat(Global.getDateFormat());
\r
713 createdTime.setDisplayFormat(Global.getTimeFormat());
\r
716 // Set the creation date
\r
717 public void setAltered(long date) {
\r
718 QDateTime dt = new QDateTime();
\r
719 dt.setTime_t((int) (date / 1000));
\r
720 alteredDate.setDateTime(dt);
\r
721 alteredTime.setDateTime(dt);
\r
722 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
723 alteredTime.setDisplayFormat(Global.getTimeFormat());
\r
726 // Set the subject date
\r
727 public void setSubjectDate(long date) {
\r
728 QDateTime dt = new QDateTime();
\r
729 dt.setTime_t((int) (date / 1000));
\r
730 subjectDate.setDateTime(dt);
\r
731 subjectTime.setDateTime(dt);
\r
732 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
733 subjectTime.setDisplayFormat(Global.getTimeFormat());
\r
736 // Toggle the extended attribute information
\r
737 public void toggleInformation() {
\r
739 extendedOn = false;
\r
743 urlLabel.setVisible(extendedOn);
\r
744 urlText.setVisible(extendedOn);
\r
745 authorText.setVisible(extendedOn);
\r
746 geoBox.setVisible(extendedOn);
\r
747 authorLabel.setVisible(extendedOn);
\r
748 createdDate.setVisible(extendedOn);
\r
749 createdTime.setVisible(extendedOn);
\r
750 createdLabel.setVisible(extendedOn);
\r
751 alteredLabel.setVisible(extendedOn);
\r
752 alteredDate.setVisible(extendedOn);
\r
753 alteredTime.setVisible(extendedOn);
\r
754 //notebookBox.setVisible(extendedOn);
\r
755 notebookLabel.setVisible(extendedOn);
\r
756 subjectLabel.setVisible(extendedOn);
\r
757 subjectDate.setVisible(extendedOn);
\r
758 subjectTime.setVisible(extendedOn);
\r
761 public void hideButtons() {
\r
763 undoButton.parentWidget().setVisible(false);
\r
764 buttonsVisible = false;
\r
768 // Is the extended view on?
\r
769 public boolean isExtended() {
\r
773 // Listener for when a link is clicked
\r
774 @SuppressWarnings("unused")
\r
775 private void openFile() {
\r
776 logger.log(logger.EXTREME, "Starting openFile()");
\r
777 File fileHandle = new File(selectedFile);
\r
778 URI fileURL = fileHandle.toURI();
\r
779 String localURL = fileURL.toString();
\r
780 QUrl url = new QUrl(localURL);
\r
781 QFile file = new QFile(selectedFile);
\r
783 logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName());
\r
784 fileWatcher.addPath(file.fileName());
\r
786 if (!QDesktopServices.openUrl(url)) {
\r
787 logger.log(logger.LOW, "Error opening file :" +url);
\r
792 // Listener for when a link is clicked
\r
793 @SuppressWarnings("unused")
\r
794 private void linkClicked(QUrl url) {
\r
795 logger.log(logger.EXTREME, "URL Clicked: " +url.toString());
\r
796 if (url.toString().substring(0,8).equals("nnres://")) {
\r
797 logger.log(logger.EXTREME, "URL is NN resource");
\r
798 if (url.toString().endsWith("/vnd.evernote.ink")) {
\r
799 logger.log(logger.EXTREME, "Unable to open ink note");
\r
800 QMessageBox.information(this, tr("Unable Open"), tr("This is an ink note.\n"+
\r
801 "Ink notes are not supported since Evernote has not\n published any specifications on them\n" +
\r
802 "and I'm too lazy to figure them out by myself."));
\r
805 String fullName = url.toString().substring(8);
\r
806 int index = fullName.indexOf(".");
\r
810 type = fullName.substring(index+1);
\r
811 guid = fullName.substring(0,index);
\r
813 index = guid.indexOf(Global.attachmentNameDelimeter);
\r
815 guid = guid.substring(0,index);
\r
817 List<Resource> resList = currentNote.getResources();
\r
818 Resource res = null;
\r
819 for (int i=0; i<resList.size(); i++) {
\r
820 if (resList.get(i).getGuid().equals(guid)) {
\r
821 res = resList.get(i);
\r
826 String resGuid = Global.resourceMap.get(guid);
\r
827 if (resGuid != null)
\r
828 res = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, true);
\r
832 if (res.getAttributes() != null &&
\r
833 res.getAttributes().getFileName() != null &&
\r
834 !res.getAttributes().getFileName().trim().equals(""))
\r
835 fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();
\r
837 fileName = res.getGuid()+"."+type;
\r
838 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
839 QFile.OpenMode mode = new QFile.OpenMode();
\r
840 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
841 boolean openResult = file.open(mode);
\r
842 logger.log(logger.EXTREME, "File opened:" +openResult);
\r
843 QDataStream out = new QDataStream(file);
\r
844 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);
\r
845 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
847 logger.log(logger.EXTREME, "Writing resource");
\r
848 out.writeBytes(binData.toByteArray());
\r
851 String whichOS = System.getProperty("os.name");
\r
852 if (whichOS.contains("Windows"))
\r
853 url.setUrl("file:///"+file.fileName());
\r
855 url.setUrl("file://"+file.fileName());
\r
856 // fileWatcher.removePath(file.fileName());
\r
857 logger.log(logger.EXTREME, "Adding file watcher " +file.fileName());
\r
858 fileWatcher.addPath(file.fileName());
\r
860 // If we can't open it, then prompt the user to save it.
\r
861 if (!QDesktopServices.openUrl(url)) {
\r
862 logger.log(logger.EXTREME, "We can't handle this. Where do we put it?");
\r
863 QFileDialog dialog = new QFileDialog();
\r
865 if (dialog.exec()!=0) {
\r
866 List<String> fileNames = dialog.selectedFiles(); //gets all selected filenames
\r
867 if (fileNames.size() == 0)
\r
869 String sf = fileNames.get(0);
\r
870 QFile saveFile = new QFile(sf);
\r
871 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
872 saveFile.open(mode);
\r
873 QDataStream saveOut = new QDataStream(saveFile);
\r
874 saveOut.writeBytes(binData.toByteArray());
\r
882 logger.log(logger.EXTREME, "Launching URL");
\r
883 QDesktopServices.openUrl(url);
\r
886 // Listener for when BOLD is clicked
\r
887 @SuppressWarnings("unused")
\r
888 private void undoClicked() {
\r
889 browser.page().triggerAction(WebAction.Undo);
\r
890 browser.setFocus();
\r
893 // Listener for when BOLD is clicked
\r
894 @SuppressWarnings("unused")
\r
895 private void redoClicked() {
\r
896 browser.page().triggerAction(WebAction.Redo);
\r
897 browser.setFocus();
\r
900 // Listener for when BOLD is clicked
\r
901 @SuppressWarnings("unused")
\r
902 private void boldClicked() {
\r
903 browser.page().triggerAction(WebAction.ToggleBold);
\r
904 microFocusChanged();
\r
905 browser.setFocus();
\r
908 // Listener for when Italics is clicked
\r
909 @SuppressWarnings("unused")
\r
910 private void italicClicked() {
\r
911 browser.page().triggerAction(WebAction.ToggleItalic);
\r
912 microFocusChanged();
\r
913 browser.setFocus();
\r
916 // Listener for when UNDERLINE is clicked
\r
917 @SuppressWarnings("unused")
\r
918 private void underlineClicked() {
\r
919 browser.page().triggerAction(WebAction.ToggleUnderline);
\r
920 microFocusChanged();
\r
921 browser.setFocus();
\r
924 // Listener for when Strikethrough is clicked
\r
925 @SuppressWarnings("unused")
\r
926 private void strikethroughClicked() {
\r
927 browser.page().mainFrame().evaluateJavaScript(
\r
928 "document.execCommand('strikeThrough', false, '');");
\r
929 browser.setFocus();
\r
932 // Listener for when cut is clicked
\r
933 @SuppressWarnings("unused")
\r
934 private void cutClicked() {
\r
935 browser.page().triggerAction(WebAction.Cut);
\r
936 browser.setFocus();
\r
939 // Listener when COPY is clicked
\r
940 @SuppressWarnings("unused")
\r
941 private void copyClicked() {
\r
942 browser.page().triggerAction(WebAction.Copy);
\r
943 browser.setFocus();
\r
946 // Listener when PASTE is clicked
\r
947 public void pasteClicked() {
\r
948 logger.log(logger.EXTREME, "Paste Clicked");
\r
949 if (forceTextPaste) {
\r
950 pasteWithoutFormattingClicked();
\r
953 QClipboard clipboard = QApplication.clipboard();
\r
954 QMimeData mime = clipboard.mimeData();
\r
956 // String x = mime.html();
\r
958 if (mime.hasImage()) {
\r
959 logger.log(logger.EXTREME, "Image paste found");
\r
961 browser.setFocus();
\r
965 if (mime.hasUrls()) {
\r
966 logger.log(logger.EXTREME, "URL paste found");
\r
968 browser.setFocus();
\r
972 String text = mime.html();
\r
973 if (text.contains("en-tag") && mime.hasHtml()) {
\r
974 logger.log(logger.EXTREME, "Intra-note paste found");
\r
975 text = fixInternotePaste(text);
\r
976 mime.setHtml(text);
\r
977 clipboard.setMimeData(mime);
\r
980 logger.log(logger.EXTREME, "Final paste choice encountered");
\r
981 browser.page().triggerAction(WebAction.Paste);
\r
982 browser.setFocus();
\r
986 // Paste text without formatting
\r
987 private void pasteWithoutFormattingClicked() {
\r
988 logger.log(logger.EXTREME, "Paste without format clipped");
\r
989 QClipboard clipboard = QApplication.clipboard();
\r
990 QMimeData mime = clipboard.mimeData();
\r
991 if (!mime.hasText())
\r
993 String text = mime.text();
\r
994 clipboard.setText(text);
\r
995 browser.page().triggerAction(WebAction.Paste);
\r
996 QApplication.clipboard().setMimeData(mime);
\r
997 browser.setFocus();
\r
1001 // insert date/time
\r
1002 @SuppressWarnings("unused")
\r
1003 private void insertDateTime() {
\r
1004 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
\r
1005 String dateTimeFormat = new String(fmt);
\r
1006 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
\r
1007 Calendar cal = Calendar.getInstance();
\r
1009 browser.page().mainFrame().evaluateJavaScript(
\r
1010 "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");
\r
1012 browser.setFocus();
\r
1016 // Listener when Left is clicked
\r
1017 @SuppressWarnings("unused")
\r
1018 private void justifyLeftClicked() {
\r
1019 browser.page().mainFrame().evaluateJavaScript(
\r
1020 "document.execCommand('JustifyLeft', false, '');");
\r
1021 browser.setFocus();
\r
1024 // Listener when Center is clicked
\r
1025 @SuppressWarnings("unused")
\r
1026 private void justifyCenterClicked() {
\r
1027 browser.page().mainFrame().evaluateJavaScript(
\r
1028 "document.execCommand('JustifyCenter', false, '');");
\r
1029 browser.setFocus();
\r
1032 // Listener when Left is clicked
\r
1033 @SuppressWarnings("unused")
\r
1034 private void justifyRightClicked() {
\r
1035 browser.page().mainFrame().evaluateJavaScript(
\r
1036 "document.execCommand('JustifyRight', false, '');");
\r
1037 browser.setFocus();
\r
1040 // Listener when HLINE is clicked
\r
1041 @SuppressWarnings("unused")
\r
1042 private void hlineClicked() {
\r
1043 browser.page().mainFrame().evaluateJavaScript(
\r
1044 "document.execCommand('insertHorizontalRule', false, '');");
\r
1045 browser.setFocus();
\r
1048 // Listener when outdent is clicked
\r
1049 private void outdentClicked() {
\r
1050 browser.page().mainFrame().evaluateJavaScript(
\r
1051 "document.execCommand('outdent', false, '');");
\r
1052 browser.setFocus();
\r
1055 // Listener when a bullet list is clicked
\r
1056 @SuppressWarnings("unused")
\r
1057 private void bulletListClicked() {
\r
1058 browser.page().mainFrame().evaluateJavaScript(
\r
1059 "document.execCommand('InsertUnorderedList', false, '');");
\r
1060 browser.setFocus();
\r
1063 // Listener when a bullet list is clicked
\r
1064 @SuppressWarnings("unused")
\r
1065 private void numberListClicked() {
\r
1066 browser.page().mainFrame().evaluateJavaScript(
\r
1067 "document.execCommand('InsertOrderedList', false, '');");
\r
1068 browser.setFocus();
\r
1071 // Listener when indent is clicked
\r
1072 private void indentClicked() {
\r
1073 browser.page().mainFrame().evaluateJavaScript(
\r
1074 "document.execCommand('indent', false, '');");
\r
1075 browser.setFocus();
\r
1078 // Listener when the font name is changed
\r
1079 @SuppressWarnings("unused")
\r
1080 private void fontChanged(String font) {
\r
1081 browser.page().mainFrame().evaluateJavaScript(
\r
1082 "document.execCommand('fontName',false,'" + font + "');");
\r
1083 browser.setFocus();
\r
1086 // Listener when a font size is changed
\r
1087 @SuppressWarnings("unused")
\r
1088 private void fontSizeChanged(String font) {
\r
1089 String text = browser.selectedText();
\r
1090 if (text.trim().equalsIgnoreCase(""))
\r
1093 String selectedText = browser.selectedText();
\r
1094 String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";
\r
1095 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1096 browser.page().mainFrame().evaluateJavaScript(script);
\r
1097 /* browser.page().mainFrame().evaluateJavaScript(
\r
1098 "document.execCommand('fontSize',false,'"
\r
1101 browser.setFocus();
\r
1104 // Load the font combo box based upon the font selected
\r
1105 private void loadFontSize(String name) {
\r
1106 QFontDatabase db = new QFontDatabase();
\r
1108 List<Integer> points = db.pointSizes(name);
\r
1109 for (int i=0; i<points.size(); i++) {
\r
1110 fontSize.addItem(points.get(i).toString());
\r
1113 fontSize.addItem("x-small");
\r
1114 fontSize.addItem("small");
\r
1115 fontSize.addItem("medium");
\r
1116 fontSize.addItem("large");
\r
1117 fontSize.addItem("x-large");
\r
1118 fontSize.addItem("xx-large");
\r
1119 fontSize.addItem("xxx-large");
\r
1123 // Listener when a font size is changed
\r
1124 @SuppressWarnings("unused")
\r
1125 private void fontColorClicked() {
\r
1126 // QColorDialog dialog = new QColorDialog();
\r
1127 // QColor color = QColorDialog.getColor();
\r
1128 QColor color = fontColorMenu.getColor();
\r
1129 if (color.isValid())
\r
1130 browser.page().mainFrame().evaluateJavaScript(
\r
1131 "document.execCommand('foreColor',false,'" + color.name()
\r
1133 browser.setFocus();
\r
1136 // Listener for when a background color change is requested
\r
1137 @SuppressWarnings("unused")
\r
1138 private void fontHilightClicked() {
\r
1139 // QColorDialog dialog = new QColorDialog();
\r
1140 // QColor color = QColorDialog.getColor();
\r
1141 QColor color = fontHilightColorMenu.getColor();
\r
1142 if (color.isValid())
\r
1143 browser.page().mainFrame().evaluateJavaScript(
\r
1144 "document.execCommand('backColor',false,'" + color.name()
\r
1146 browser.setFocus();
\r
1149 // Listener for when a background color change is requested
\r
1150 @SuppressWarnings("unused")
\r
1151 private void superscriptClicked() {
\r
1152 browser.page().mainFrame().evaluateJavaScript(
\r
1153 "document.execCommand('superscript');");
\r
1154 browser.setFocus();
\r
1157 // Listener for when a background color change is requested
\r
1158 @SuppressWarnings("unused")
\r
1159 private void subscriptClicked() {
\r
1160 browser.page().mainFrame().evaluateJavaScript(
\r
1161 "document.execCommand('subscript');");
\r
1162 browser.setFocus();
\r
1164 // Insert a to-do checkbox
\r
1165 @SuppressWarnings("unused")
\r
1166 private void todoClicked() {
\r
1167 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1168 String script_start = new String(
\r
1169 "document.execCommand('insertHtml', false, '");
\r
1170 String script_end = new String("');");
\r
1171 String todo = new String(
\r
1172 "<input TYPE=\"CHECKBOX\" value=\"false\" onClick=\"value=checked; window.jambi.contentChanged(); \" />");
\r
1173 browser.page().mainFrame().evaluateJavaScript(
\r
1174 script_start + todo + script_end);
\r
1175 browser.setFocus();
\r
1178 // Encrypt the selected text
\r
1179 @SuppressWarnings("unused")
\r
1180 private void encryptText() {
\r
1181 String text = browser.selectedText();
\r
1182 if (text.trim().equalsIgnoreCase(""))
\r
1185 EnCryptDialog dialog = new EnCryptDialog();
\r
1187 if (!dialog.okPressed()) {
\r
1191 EnCrypt crypt = new EnCrypt();
\r
1192 String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);
\r
1194 if (encrypted.trim().equals("")) {
\r
1195 QMessageBox.information(this, tr("Error"), tr("Error Encrypting String"));
\r
1198 StringBuffer buffer = new StringBuffer(encrypted.length() + 100);
\r
1199 buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""
\r
1200 + dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");
\r
1201 buffer.append("contentEditable=\"false\" alt=\"");
\r
1202 buffer.append(encrypted);
\r
1203 // NFC FIXME: should this be a file URL like in handleLocalAttachment and importAttachment?
\r
1204 buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png") +"\""));
\r
1205 Global.cryptCounter++;
\r
1206 buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");
\r
1207 buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");
\r
1208 buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString()
\r
1209 +"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&apos;")+"\\');\"");
\r
1210 buffer.append("style=\"display:block\" />");
\r
1212 String script_start = new String(
\r
1213 "document.execCommand('insertHtml', false, '");
\r
1214 String script_end = new String("');");
\r
1215 browser.page().mainFrame().evaluateJavaScript(
\r
1216 script_start + buffer.toString() + script_end);
\r
1220 // Insert a hyperlink
\r
1221 public void insertLink() {
\r
1222 logger.log(logger.EXTREME, "Inserting link");
\r
1223 String text = browser.selectedText();
\r
1224 if (text.trim().equalsIgnoreCase(""))
\r
1227 InsertLinkDialog dialog = new InsertLinkDialog();
\r
1228 if (currentHyperlink != null && currentHyperlink != "") {
\r
1229 dialog.setUrl(currentHyperlink);
\r
1232 if (!dialog.okPressed()) {
\r
1233 logger.log(logger.EXTREME, "Insert link canceled");
\r
1236 if (browser.insertLinkAction.text().equalsIgnoreCase("Insert Hyperlink")) {
\r
1237 String selectedText = browser.selectedText();
\r
1238 logger.log(logger.EXTREME, "Inserting link on text "+selectedText);
\r
1239 logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim());
\r
1240 String dUrl = StringUtils.replace(dialog.getUrl().trim(), "'", "\\'");
\r
1241 String url = "<a href=\"" +dUrl
\r
1242 +"\" title=" +dUrl
\r
1243 +" >"+selectedText +"</a>";
\r
1244 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1245 browser.page().mainFrame().evaluateJavaScript(script);
\r
1248 String js = new String( "function getCursorPos() {"
\r
1250 +"if (window.getSelection) {"
\r
1251 +" var selObj = window.getSelection();"
\r
1252 +" var selRange = selObj.getRangeAt(0);"
\r
1253 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1254 +" while(workingNode != null) { "
\r
1255 +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');"
\r
1256 +" workingNode = workingNode.parentNode;"
\r
1259 +"} getCursorPos();");
\r
1260 browser.page().mainFrame().evaluateJavaScript(js);
\r
1267 public void insertTable() {
\r
1268 TableDialog dialog = new TableDialog();
\r
1270 if (!dialog.okPressed()) {
\r
1274 int cols = dialog.getCols();
\r
1275 int rows = dialog.getRows();
\r
1276 int width = dialog.getWidth();
\r
1277 boolean percent = dialog.isPercent();
\r
1279 String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();
\r
1281 newHTML = newHTML +"%";
\r
1282 newHTML = newHTML + "\"><tbody>";
\r
1284 for (int i=0; i<rows; i++) {
\r
1285 newHTML = newHTML +"<tr>";
\r
1286 for (int j=0; j<cols; j++) {
\r
1287 newHTML = newHTML +"<td> </td>";
\r
1289 newHTML = newHTML +"</tr>";
\r
1291 newHTML = newHTML+"</tbody></table>";
\r
1293 String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";
\r
1294 browser.page().mainFrame().evaluateJavaScript(script);
\r
1298 // Text content changed
\r
1299 @SuppressWarnings("unused")
\r
1300 private void selectionChanged() {
\r
1301 browser.encryptAction.setEnabled(true);
\r
1302 browser.insertLinkAction.setEnabled(true);
\r
1303 String scriptStart = "var selection_text = (window.getSelection()).toString();"
\r
1304 + "var range = (window.getSelection()).getRangeAt(0);"
\r
1305 + "var parent_html = range.commonAncestorContainer.innerHTML;"
\r
1306 + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"
\r
1307 + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"
\r
1308 + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"
\r
1309 + "var start = parent_html.indexOf(first_text);"
\r
1310 + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"
\r
1311 + "var value = parent_html.substring(start,end);"
\r
1312 + "window.jambi.saveSelectedText(value);" ;
\r
1313 browser.page().mainFrame().evaluateJavaScript(scriptStart);
\r
1317 public void saveSelectedText(String text) {
\r
1318 boolean enabled = true;
\r
1319 if (text.trim().length() == 0)
\r
1321 if (text.indexOf("en-tag=\"en-crypt\"") >= 0)
\r
1323 if (text.indexOf("<img en-tag=\"en-media\"") >= 0)
\r
1325 if (text.indexOf("<a en-tag=\"en-media\"") >= 0)
\r
1327 if (text.indexOf("<input ") >= 0)
\r
1330 browser.encryptAction.setEnabled(enabled);
\r
1331 browser.insertLinkAction.setEnabled(enabled);
\r
1332 // selectedText = text;
\r
1335 // Decrypt clicked text
\r
1336 public void decryptText(String id, String text, String hint) {
\r
1337 EnCrypt crypt = new EnCrypt();
\r
1338 String plainText = null;
\r
1339 Calendar currentTime = new GregorianCalendar();
\r
1340 Long l = new Long(currentTime.getTimeInMillis());
\r
1341 String slot = new String(Long.toString(l));
\r
1343 // First, try to decrypt with any keys we already have
\r
1344 for (int i=0; i<Global.passwordRemember.size(); i++) {
\r
1345 plainText = crypt.decrypt(text, Global.passwordRemember.get(i), 64);
\r
1346 if (plainText != null) {
\r
1347 slot = new String(Long.toString(l));
\r
1348 Global.passwordSafe.put(slot, Global.passwordRemember.get(i));
\r
1349 removeEncryption(id, plainText, false, slot);
\r
1355 EnDecryptDialog dialog = new EnDecryptDialog();
\r
1356 dialog.setHint(hint);
\r
1357 while (plainText == null || !dialog.okPressed()) {
\r
1359 if (!dialog.okPressed()) {
\r
1362 plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);
\r
1363 if (plainText == null) {
\r
1364 QMessageBox.warning(this, "Incorrect Password", "The password entered is not correct");
\r
1367 Global.passwordSafe.put(slot, dialog.getPassword());
\r
1368 removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);
\r
1369 if (dialog.rememberPassword())
\r
1370 Global.passwordRemember.add(dialog.getPassword());
\r
1374 // Get the editor tag line
\r
1375 public TagLineEdit getTagLine() {
\r
1379 // Modify a note's tags
\r
1380 @SuppressWarnings("unused")
\r
1381 private void modifyTags() {
\r
1382 TagAssign tagWindow = new TagAssign(allTags, currentTags);
\r
1384 if (tagWindow.okClicked()) {
\r
1385 currentTags.clear();
\r
1386 StringBuffer tagDisplay = new StringBuffer();
\r
1388 List<QListWidgetItem> newTags = tagWindow.getTagList()
\r
1390 for (int i = 0; i < newTags.size(); i++) {
\r
1391 currentTags.add(newTags.get(i).text());
\r
1392 tagDisplay.append(newTags.get(i).text());
\r
1393 if (i < newTags.size() - 1) {
\r
1394 tagDisplay.append(Global.tagDelimeter + " ");
\r
1397 tagEdit.setText(tagDisplay.toString());
\r
1398 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1402 // Tag line has been modified by typing text
\r
1403 @SuppressWarnings("unused")
\r
1404 private void modifyTagsTyping() {
\r
1405 String completionText = "";
\r
1406 if (tagEdit.currentCompleterSelection != null && !tagEdit.currentCompleterSelection.equals("")) {
\r
1407 completionText = tagEdit.currentCompleterSelection;
\r
1408 tagEdit.currentCompleterSelection = "";
\r
1411 if (tagEdit.text().equalsIgnoreCase(saveTagList))
\r
1414 // We know something has changed...
\r
1415 String oldTagArray[] = saveTagList.split(Global.tagDelimeter);
\r
1416 String newTagArray[] = tagEdit.text().split(Global.tagDelimeter);
\r
1418 if (!completionText.equals("") && newTagArray.length > 0) {
\r
1419 newTagArray[newTagArray.length-1] = completionText;
\r
1421 // Remove any potential duplicates from the new list
\r
1422 for (int i=0; i<newTagArray.length; i++) {
\r
1423 boolean foundOnce = false;
\r
1424 for (int j=0; j<newTagArray.length; j++) {
\r
1425 if (newTagArray[j].equalsIgnoreCase(newTagArray[i])) {
\r
1429 newTagArray[j] = "";
\r
1434 List<String> newTagList = new ArrayList<String>();
\r
1435 List<String> oldTagList = new ArrayList<String>();
\r
1437 for (int i = 0; i < oldTagArray.length; i++)
\r
1438 if (!oldTagArray[i].trim().equals(""))
\r
1439 oldTagList.add(oldTagArray[i]);
\r
1440 for (int i = 0; i < newTagArray.length; i++)
\r
1441 if (!newTagArray[i].trim().equals(""))
\r
1442 newTagList.add(newTagArray[i]);
\r
1444 // Let's cleanup the appearance of the tag list
\r
1445 Collections.sort(newTagList);
\r
1446 String newDisplay = "";
\r
1447 for (int i=0; i<newTagList.size(); i++) {
\r
1448 newDisplay = newDisplay+newTagList.get(i);
\r
1449 if (i<newTagList.size()-1)
\r
1450 newDisplay = newDisplay+", ";
\r
1452 tagEdit.blockSignals(true);
\r
1453 tagEdit.setText(newDisplay);
\r
1454 tagEdit.blockSignals(false);
\r
1456 // We now have lists of the new & old. Remove duplicates. If all
\r
1457 // are removed from both then nothing has really changed
\r
1458 for (int i = newTagList.size() - 1; i >= 0; i--) {
\r
1459 String nTag = newTagList.get(i);
\r
1460 for (int j = oldTagList.size() - 1; j >= 0; j--) {
\r
1461 String oTag = oldTagList.get(j);
\r
1462 if (oTag.equalsIgnoreCase(nTag)) {
\r
1463 oldTagList.remove(j);
\r
1464 newTagList.remove(i);
\r
1470 if (oldTagList.size() != 0 || newTagList.size() != 0) {
\r
1471 currentTags.clear();
\r
1472 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1473 for (int i = 0; i < newTagArray.length; i++)
\r
1474 if (!newTagArray[i].trim().equals(""))
\r
1475 currentTags.add(newTagArray[i].trim());
\r
1477 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1482 // Tab button was pressed
\r
1483 public void tabPressed() {
\r
1484 if (!insideList) {
\r
1485 String script_start = new String(
\r
1486 "document.execCommand('insertHtml', false, ' ');");
\r
1487 browser.page().mainFrame().evaluateJavaScript(script_start);
\r
1492 public void backtabPressed() {
\r
1497 public void setInsideList() {
\r
1498 insideList = true;
\r
1501 // The title has been edited
\r
1502 @SuppressWarnings("unused")
\r
1503 private void titleEdited() {
\r
1504 // If we don't have a good note, or if the current title
\r
1505 // matches the old title then we don't need to do anything
\r
1506 if (currentNote == null)
\r
1508 if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))
\r
1511 // If we have a real change, we need to save it.
\r
1512 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text());
\r
1513 currentNote.setTitle(titleLabel.text());
\r
1514 saveNoteTitle = titleLabel.text();
\r
1518 // Set the list of note tags
\r
1519 public void setAllTags(List<Tag> l) {
\r
1521 tagEdit.setTagList(l);
\r
1524 // Setter for the current tags
\r
1525 public void setCurrentTags(List<String> s) {
\r
1529 // Save the list of notebooks
\r
1530 public void setNotebookList(List<Notebook> n) {
\r
1532 loadNotebookList();
\r
1535 // Load the notebook list and select the current notebook
\r
1536 private void loadNotebookList() {
\r
1537 if (notebookBox.count() != 0)
\r
1538 notebookBox.clear();
\r
1539 if (notebookList == null)
\r
1542 for (int i = 0; i < notebookList.size(); i++) {
\r
1543 notebookBox.addItem(notebookList.get(i).getName());
\r
1544 if (currentNote != null) {
\r
1545 if (currentNote.getNotebookGuid().equals(
\r
1546 notebookList.get(i).getGuid())) {
\r
1547 notebookBox.setCurrentIndex(i);
\r
1553 // Get the contents of the editor
\r
1554 public String getContent() {
\r
1555 return browser.page().currentFrame().toHtml();
\r
1558 // The note contents have changed
\r
1559 public void contentChanged() {
\r
1560 String content = getContent();
\r
1562 noteSignal.noteChanged.emit(currentNote.getGuid(), content);
\r
1565 // The notebook selection has changed
\r
1566 @SuppressWarnings("unused")
\r
1567 private void notebookChanged() {
\r
1568 boolean changed = false;
\r
1569 String n = notebookBox.currentText();
\r
1570 for (int i = 0; i < notebookList.size(); i++) {
\r
1571 if (n.equals(notebookList.get(i).getName())) {
\r
1572 if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {
\r
1573 currentNote.setNotebookGuid(notebookList.get(i).getGuid());
\r
1576 i = notebookList.size();
\r
1580 // If the notebook changed, signal the update
\r
1582 noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote
\r
1583 .getNotebookGuid());
\r
1586 // Check the note title
\r
1587 private void checkNoteTitle() {
\r
1588 String text = browser.page().currentFrame().toPlainText();
\r
1589 if (saveNoteTitle.trim().equals("") || saveNoteTitle.trim().equals("Untitled Note")) {
\r
1590 int newLine = text.indexOf("\n");
\r
1591 if (newLine > 0) {
\r
1592 text = text.substring(0, newLine);
\r
1593 if (text.trim().equals(""))
\r
1594 text = tr("Untitled Note");
\r
1595 titleLabel.setText(text);
\r
1597 if (text.length() > Constants.EDAM_NOTE_TITLE_LEN_MAX)
\r
1598 titleLabel.setText(text.substring(0, Constants.EDAM_NOTE_TITLE_LEN_MAX));
\r
1600 titleLabel.blockSignals(true);
\r
1601 if (text.trim().equals(""))
\r
1602 titleLabel.setText(tr("Untitled Note"));
\r
1604 titleLabel.setText(text);
\r
1605 titleLabel.blockSignals(false);
\r
1608 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel
\r
1613 // Return the note contents so we can email them
\r
1614 public String getContentsToEmail() {
\r
1615 return browser.page().currentFrame().toPlainText().trim();
\r
1617 * int body = browser.page().currentFrame().toHtml().indexOf("<body>");
\r
1618 * String temp = browser.page().currentFrame().toHtml(); if (body == -1)
\r
1619 * temp = "<html><body><b>Test</b></body></html>"; else temp =
\r
1620 * "<html>"+temp.substring(body); return temp; // return
\r
1621 * urlEncode(browser.page().currentFrame().toHtml());
\r
1625 // Insert an image into the editor
\r
1626 private void insertImage(QMimeData mime) {
\r
1627 logger.log(logger.EXTREME, "Entering insertImage");
\r
1628 QImage img = (QImage) mime.imageData();
\r
1629 String script_start = new String(
\r
1630 "document.execCommand('insertHTML', false, '");
\r
1631 String script_end = new String("');");
\r
1633 long now = new Date().getTime();
\r
1634 String path = Global.getFileManager().getResDirPath(
\r
1635 (new Long(now).toString()) + ".jpg");
\r
1637 // This block is just a hack to make sure we wait at least 1ms so we
\r
1639 // have collisions on image names
\r
1640 long i = new Date().getTime();
\r
1642 i = new Date().getTime();
\r
1644 // Open the file & write the data
\r
1645 QFile tfile = new QFile(path);
\r
1646 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1650 Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);
\r
1651 if (newRes == null)
\r
1653 currentNote.getResources().add(newRes);
\r
1655 // do the actual insert into the note
\r
1656 StringBuffer buffer = new StringBuffer(100);
\r
1657 buffer.append("<img src=\"");
\r
1658 buffer.append(tfile.fileName());
\r
1659 buffer.append("\" en-tag=en-media type=\"image/jpeg\""
\r
1660 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1661 +" guid=\"" +newRes.getGuid() +"\""
\r
1662 // +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1663 +" onContextMenu=\"window.jambi.imageContextMenu(&." +tfile.fileName() +"&.);\""
\r
1666 browser.page().mainFrame().evaluateJavaScript(
\r
1667 script_start + buffer + script_end);
\r
1672 // Handle URLs that are trying to be pasted
\r
1673 public void handleUrls(QMimeData mime) {
\r
1674 logger.log(logger.EXTREME, "Starting handleUrls");
\r
1675 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1677 List<QUrl> urlList = mime.urls();
\r
1678 String url = new String();
\r
1679 String script_start = new String(
\r
1680 "document.execCommand('createLink', false, '");
\r
1681 String script_end = new String("');");
\r
1683 for (int i = 0; i < urlList.size(); i++) {
\r
1684 url = urlList.get(i).toString();
\r
1685 // Find out what type of file we have
\r
1686 String mimeType = fileNameMap.getContentTypeFor(url);
\r
1688 // If null returned, we need to guess at the file type
\r
1689 if (mimeType == null)
\r
1690 mimeType = "application/"
\r
1691 + url.substring(url.lastIndexOf(".") + 1);
\r
1693 // Check if we have an image or some other type of file
\r
1694 if (url.substring(0, 5).equalsIgnoreCase("file:")
\r
1695 && mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1696 handleLocalImageURLPaste(mime, mimeType);
\r
1699 String[] type = mimeType.split("/");
\r
1700 boolean valid = validAttachment(type[1]);
\r
1701 boolean smallEnough = checkFileAttachmentSize(url);
\r
1702 if (smallEnough && valid
\r
1703 && url.substring(0, 5).equalsIgnoreCase("file:")
\r
1704 && !mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1705 handleLocalAttachment(mime, mimeType);
\r
1708 browser.page().mainFrame().evaluateJavaScript(
\r
1709 script_start + url + script_end);
\r
1714 // If a URL being pasted is an image URL, then attach the image
\r
1715 private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {
\r
1716 List<QUrl> urlList = mime.urls();
\r
1717 String url = new String();
\r
1718 String script_start_image = new String(
\r
1719 "document.execCommand('insertHtml', false, '");
\r
1720 String script_end = new String("');");
\r
1721 StringBuffer buffer;
\r
1723 // Copy the image over into the resource directory and create a new resource
\r
1724 // record for each url pasted
\r
1725 for (int i = 0; i < urlList.size(); i++) {
\r
1726 url = urlList.get(i).toString();
\r
1728 Resource newRes = createResource(url, i, mimeType, false);
\r
1729 if (newRes == null)
\r
1731 currentNote.getResources().add(newRes);
\r
1732 buffer = new StringBuffer(100);
\r
1734 // Open the file & write the data
\r
1735 String fileName = Global.getFileManager().getResDirPath(newRes.getGuid());
\r
1736 QFile tfile = new QFile(fileName);
\r
1737 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1738 tfile.write(newRes.getData().getBody());
\r
1740 buffer.append(script_start_image);
\r
1741 buffer.append("<img src=\"" + FileUtils.toForwardSlashedPath(fileName));
\r
1742 // if (mimeType.equalsIgnoreCase("image/jpg"))
\r
1743 // mimeType = "image/jpeg";
\r
1744 buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""
\r
1745 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1746 +" guid=\"" +newRes.getGuid() +"\""
\r
1747 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1749 buffer.append(script_end);
\r
1750 browser.page().mainFrame().evaluateJavaScript(buffer.toString());
\r
1756 // If a URL being pasted is a local file URL, then attach the file
\r
1757 private void handleLocalAttachment(QMimeData mime, String mimeType) {
\r
1758 logger.log(logger.EXTREME, "Attaching local file");
\r
1759 List<QUrl> urlList = mime.urls();
\r
1760 String script_start = new String(
\r
1761 "document.execCommand('insertHtml', false, '");
\r
1762 String script_end = new String("');");
\r
1763 StringBuffer buffer;
\r
1765 String[] type = mimeType.split("/");
\r
1766 String icon = findIcon(type[1]);
\r
1767 if (icon.equals("attachment.png"))
\r
1768 icon = findIcon(type[0]);
\r
1769 buffer = new StringBuffer(100);
\r
1771 for (int i = 0; i < urlList.size(); i++) {
\r
1772 String url = urlList.get(i).toString();
\r
1774 // Start building the HTML
\r
1775 if (icon.equals("attachment.png"))
\r
1776 icon = findIcon(url.substring(url.lastIndexOf(".")+1));
\r
1777 String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));
\r
1779 logger.log(logger.EXTREME, "Creating resource ");
\r
1780 Resource newRes = createResource(url, i, mimeType, true);
\r
1781 if (newRes == null)
\r
1783 logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());
\r
1784 currentNote.getResources().add(newRes);
\r
1786 String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();
\r
1787 // If we have a PDF, we need to setup the preview.
\r
1788 if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {
\r
1789 logger.log(logger.EXTREME, "Setting up PDF preview");
\r
1790 if (newRes.getAttributes() != null &&
\r
1791 newRes.getAttributes().getFileName() != null &&
\r
1792 !newRes.getAttributes().getFileName().trim().equals(""))
\r
1793 fileName = newRes.getGuid()+Global.attachmentNameDelimeter+
\r
1794 newRes.getAttributes().getFileName();
\r
1796 fileName = newRes.getGuid()+".pdf";
\r
1797 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
1798 QFile.OpenMode mode = new QFile.OpenMode();
\r
1799 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
1801 QDataStream out = new QDataStream(file);
\r
1802 // Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);
\r
1803 QByteArray binData = new QByteArray(newRes.getData().getBody());
\r
1804 // resBinary = null;
\r
1805 out.writeBytes(binData.toByteArray());
\r
1808 PDFPreview pdfPreview = new PDFPreview();
\r
1809 if (pdfPreview.setupPreview(Global.getFileManager().getResDirPath(fileName), "pdf",0)) {
\r
1810 // NFC TODO: should this be a 'file://' url like the ones above?
\r
1811 imageURL = file.fileName() + ".png";
\r
1815 logger.log(logger.EXTREME, "Generating link tags");
\r
1816 buffer.delete(0, buffer.length());
\r
1817 buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");
\r
1818 buffer.append(" onContextMenu=\"window.jambi.imageContextMenu('")
\r
1819 .append(Global.getFileManager().getResDirPath(fileName))
\r
1820 .append("');\" "); buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");
\r
1821 buffer.append("<img src=\"" + imageURL + "\" title=\"" +newRes.getAttributes().getFileName());
\r
1822 buffer.append("\"></img>");
\r
1823 buffer.append("</a>");
\r
1824 browser.page().mainFrame().evaluateJavaScript(
\r
1825 script_start + buffer.toString() + script_end);
\r
1830 private Resource createResource(String url, int sequence, String mime, boolean attachment) {
\r
1831 logger.log(logger.EXTREME, "Inside create resource");
\r
1832 QFile resourceFile;
\r
1833 String urlTest = new QUrl(url).toLocalFile();
\r
1834 if (!urlTest.equals(""))
\r
1836 url = url.replace("/", File.separator);
\r
1837 resourceFile = new QFile(url);
\r
1838 resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));
\r
1839 byte[] fileData = resourceFile.readAll().toByteArray();
\r
1840 resourceFile.close();
\r
1841 if (fileData.length == 0)
\r
1845 md = MessageDigest.getInstance("MD5");
\r
1846 md.update(fileData);
\r
1847 byte[] hash = md.digest();
\r
1849 Resource r = new Resource();
\r
1850 Calendar time = new GregorianCalendar();
\r
1851 long prevTime = time.getTimeInMillis();
\r
1852 while (prevTime == time.getTimeInMillis()) {
\r
1853 time = new GregorianCalendar();
\r
1855 r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());
\r
1856 r.setNoteGuid(currentNote.getGuid());
\r
1858 r.setActive(true);
\r
1859 r.setUpdateSequenceNum(0);
\r
1860 r.setWidth((short) 0);
\r
1861 r.setHeight((short) 0);
\r
1862 r.setDuration((short) 0);
\r
1864 Data d = new Data();
\r
1865 d.setBody(fileData);
\r
1866 d.setBodyIsSet(true);
\r
1867 d.setBodyHash(hash);
\r
1868 d.setBodyHashIsSet(true);
\r
1870 d.setSize(fileData.length);
\r
1872 int fileNamePos = url.lastIndexOf(File.separator);
\r
1873 if (fileNamePos == -1)
\r
1874 fileNamePos = url.lastIndexOf("/");
\r
1875 String fileName = url.substring(fileNamePos+1);
\r
1876 ResourceAttributes a = new ResourceAttributes();
\r
1878 a.setAltitudeIsSet(false);
\r
1879 a.setLongitude(0);
\r
1880 a.setLongitudeIsSet(false);
\r
1882 a.setLatitudeIsSet(false);
\r
1883 a.setCameraMake("");
\r
1884 a.setCameraMakeIsSet(false);
\r
1885 a.setCameraModel("");
\r
1886 a.setCameraModelIsSet(false);
\r
1887 a.setAttachment(attachment);
\r
1888 a.setAttachmentIsSet(true);
\r
1889 a.setClientWillIndex(false);
\r
1890 a.setClientWillIndexIsSet(true);
\r
1891 a.setRecoType("");
\r
1892 a.setRecoTypeIsSet(false);
\r
1893 a.setSourceURL(url);
\r
1894 a.setSourceURLIsSet(true);
\r
1895 a.setTimestamp(0);
\r
1896 a.setTimestampIsSet(false);
\r
1897 a.setFileName(fileName);
\r
1898 a.setFileNameIsSet(true);
\r
1899 r.setAttributes(a);
\r
1901 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
1903 } catch (NoSuchAlgorithmException e1) {
\r
1904 e1.printStackTrace();
\r
1910 // find the appropriate icon for an attachment
\r
1911 private String findIcon(String appl) {
\r
1912 appl = appl.toLowerCase();
\r
1913 File f = Global.getFileManager().getImageDirFile(appl + ".png");
\r
1915 return appl+".png";
\r
1916 return "attachment.png";
\r
1919 // Check if the account supports this type of attachment
\r
1920 private boolean validAttachment(String type) {
\r
1921 if (Global.isPremium())
\r
1923 if (type.equalsIgnoreCase("JPG"))
\r
1925 if (type.equalsIgnoreCase("PNG"))
\r
1927 if (type.equalsIgnoreCase("GIF"))
\r
1929 if (type.equalsIgnoreCase("MP3"))
\r
1931 if (type.equalsIgnoreCase("WAV"))
\r
1933 if (type.equalsIgnoreCase("AMR"))
\r
1935 if (type.equalsIgnoreCase("PDF"))
\r
1937 String error = tr("Non-premium accounts can only attach JPG, PNG, GIF, MP3, WAV, AMR, or PDF files.");
\r
1938 QMessageBox.information(this, tr("Non-Premium Account"), error);
\r
1943 // Check the file attachment to be sure it isn't over 25 mb
\r
1944 private boolean checkFileAttachmentSize(String url) {
\r
1945 String fileName = url.substring(8);
\r
1946 QFile resourceFile = new QFile(fileName);
\r
1947 resourceFile.open(new QIODevice.OpenMode(
\r
1948 QIODevice.OpenModeFlag.ReadOnly));
\r
1949 long size = resourceFile.size();
\r
1950 resourceFile.close();
\r
1951 size = size / 1024 / 1024;
\r
1952 if (size < 50 && Global.isPremium())
\r
1957 String error = tr("A file attachment may not exceed 25MB.");
\r
1958 QMessageBox.information(this, tr("Attachment Size"), error);
\r
1963 @SuppressWarnings("unused")
\r
1964 private void createdChanged() {
\r
1965 QDateTime dt = new QDateTime();
\r
1966 dt.setDate(createdDate.date());
\r
1967 dt.setTime(createdTime.time());
\r
1968 noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);
\r
1972 @SuppressWarnings("unused")
\r
1973 private void alteredChanged() {
\r
1974 QDateTime dt = new QDateTime();
\r
1975 dt.setDate(alteredDate.date());
\r
1976 dt.setTime(alteredTime.time());
\r
1977 noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);
\r
1980 @SuppressWarnings("unused")
\r
1981 private void subjectDateTimeChanged() {
\r
1982 QDateTime dt = new QDateTime();
\r
1983 dt.setDate(subjectDate.date());
\r
1984 dt.setTime(subjectTime.time());
\r
1985 noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);
\r
1989 @SuppressWarnings("unused")
\r
1990 private void sourceUrlChanged() {
\r
1991 noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());
\r
1994 @SuppressWarnings("unused")
\r
1995 private void authorChanged() {
\r
1996 noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());
\r
1999 @SuppressWarnings("unused")
\r
2000 private void geoBoxChanged() {
\r
2001 int index = geoBox.currentIndex();
\r
2002 geoBox.setCurrentIndex(0);
\r
2004 GeoDialog box = new GeoDialog();
\r
2005 box.setLongitude(currentNote.getAttributes().getLongitude());
\r
2006 box.setLatitude(currentNote.getAttributes().getLatitude());
\r
2007 box.setAltitude(currentNote.getAttributes().getAltitude());
\r
2009 if (!box.okPressed())
\r
2011 double alt = box.getAltitude();
\r
2012 double lat = box.getLatitude();
\r
2013 double lon = box.getLongitude();
\r
2014 if (alt != currentNote.getAttributes().getAltitude() ||
\r
2015 lon != currentNote.getAttributes().getLongitude() ||
\r
2016 lat != currentNote.getAttributes().getLatitude()) {
\r
2017 noteSignal.geoChanged.emit(currentNote.getGuid(), lon, lat, alt);
\r
2018 currentNote.getAttributes().setAltitude(alt);
\r
2019 currentNote.getAttributes().setLongitude(lon);
\r
2020 currentNote.getAttributes().setLatitude(lat);
\r
2025 noteSignal.geoChanged.emit(currentNote.getGuid(), 0.0, 0.0, 0.0);
\r
2026 currentNote.getAttributes().setAltitude(0.0);
\r
2027 currentNote.getAttributes().setLongitude(0.0);
\r
2028 currentNote.getAttributes().setLatitude(0.0);
\r
2031 if (index == 3 || index == 0) {
\r
2032 QDesktopServices.openUrl(new QUrl("http://maps.google.com/maps?z=6&q="+currentNote.getAttributes().getLatitude() +"," +currentNote.getAttributes().getLongitude()));
\r
2036 // ************************************************************
\r
2037 // * User chose to save an attachment. Pares out the request *
\r
2038 // * into a guid & file. Save the result. *
\r
2039 // ************************************************************
\r
2040 public void downloadAttachment(QNetworkRequest request) {
\r
2042 QFileDialog fd = new QFileDialog(this);
\r
2043 fd.setFileMode(FileMode.AnyFile);
\r
2044 fd.setConfirmOverwrite(true);
\r
2045 fd.setWindowTitle(tr("Save File"));
\r
2046 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2047 fd.setDirectory(System.getProperty("user.home"));
\r
2048 String name = request.url().toString();
\r
2050 int pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2052 guid = name.substring(0, pos).replace("nnres://", "");
\r
2053 name = name.substring(pos +Global.attachmentNameDelimeter.length());
\r
2054 fd.selectFile(name);
\r
2055 pos = name.lastIndexOf('.');
\r
2057 String mimeType = "(*." + name.substring(pos + 1)
\r
2058 + ");; All Files (*)";
\r
2059 fd.setFilter(tr(mimeType));
\r
2065 // Strip URL prefix and base dir
\r
2066 guid = guid.replace("nnres://", "")
\r
2067 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2069 pos = guid.lastIndexOf('.');
\r
2071 guid = guid.substring(0,pos);
\r
2072 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2073 name = name.replace('\\', '/');
\r
2074 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2075 QFile saveFile = new QFile(fd.selectedFiles().get(0));
\r
2076 QFile.OpenMode mode = new QFile.OpenMode();
\r
2077 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2078 saveFile.open(mode);
\r
2079 QDataStream saveOut = new QDataStream(saveFile);
\r
2080 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2081 saveOut.writeBytes(binData.toByteArray());
\r
2088 // ************************************************************
\r
2089 // * User chose to save an attachment. Pares out the request *
\r
2090 // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!
\r
2091 // ************************************************************
\r
2092 // NFC TODO: unused? remove
\r
2093 public void downloadImage(QNetworkRequest request) {
\r
2094 QFileDialog fd = new QFileDialog(this);
\r
2095 fd.setFileMode(FileMode.AnyFile);
\r
2096 fd.setConfirmOverwrite(true);
\r
2097 fd.setWindowTitle(tr("Save File"));
\r
2098 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2099 fd.setDirectory(System.getProperty("user.home"));
\r
2100 String name = request.url().toString();
\r
2101 name = name.replace("nnres://", "");
\r
2102 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
\r
2103 name = name.replace(dPath, "");
\r
2104 int pos = name.lastIndexOf('.');
\r
2105 String guid = name;
\r
2107 String mimeType = "(*." + name.substring(pos + 1)
\r
2108 + ");; All Files (*)";
\r
2109 fd.setFilter(tr(mimeType));
\r
2110 guid = guid.substring(0,pos);
\r
2112 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2114 guid = name.substring(0, pos);
\r
2115 fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));
\r
2117 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2118 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2119 String fileName = fd.selectedFiles().get(0);
\r
2120 QFile saveFile = new QFile(fileName);
\r
2121 QFile.OpenMode mode = new QFile.OpenMode();
\r
2122 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2123 saveFile.open(mode);
\r
2124 QDataStream saveOut = new QDataStream(saveFile);
\r
2125 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2126 saveOut.writeBytes(binData.toByteArray());
\r
2132 // *************************************************************
\r
2133 // * decrypt any hidden text. We could do an XML parse, but
\r
2134 // * it is quicker here just to scan for an <img tag & do the fix
\r
2135 // * the manual way
\r
2136 // *************************************************************
\r
2137 private void removeEncryption(String id, String plainText, boolean permanent, String slot) {
\r
2139 plainText = " <en-crypt-temp slot=\""+slot +"\">" +plainText+"</en-crypt-temp> ";
\r
2142 String html = browser.page().mainFrame().toHtml();
\r
2143 String text = html;
\r
2144 int imagePos = html.indexOf("<img");
\r
2146 for ( ;imagePos>0; ) {
\r
2147 // Find the end tag
\r
2148 endPos = text.indexOf(">", imagePos);
\r
2149 String tag = text.substring(imagePos-1,endPos);
\r
2150 if (tag.indexOf("id=\""+id+"\"") > -1) {
\r
2151 text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);
\r
2153 browser.setContent(new QByteArray(text));
\r
2156 imagePos = text.indexOf("<img", imagePos+1);
\r
2161 //****************************************************************
\r
2162 //* Focus shortcuts
\r
2163 //****************************************************************
\r
2164 @SuppressWarnings("unused")
\r
2165 private void focusTitle() {
\r
2166 titleLabel.setFocus();
\r
2168 @SuppressWarnings("unused")
\r
2169 private void focusTag() {
\r
2170 tagEdit.setFocus();
\r
2172 @SuppressWarnings("unused")
\r
2173 private void focusNote() {
\r
2174 browser.setFocus();
\r
2176 @SuppressWarnings("unused")
\r
2177 private void focusAuthor() {
\r
2178 authorLabel.setFocus();
\r
2180 @SuppressWarnings("unused")
\r
2181 private void focusUrl() {
\r
2182 urlLabel.setFocus();
\r
2186 //*****************************************************************
\r
2187 //* Set the document background color
\r
2188 //*****************************************************************
\r
2189 public void setBackgroundColor(String color) {
\r
2190 String js = "function changeBackground(color) {"
\r
2191 +"document.body.style.background = color;"
\r
2193 +"changeBackground('" +color+"');";
\r
2194 browser.page().mainFrame().evaluateJavaScript(js);
\r
2199 //****************************************************************
\r
2200 //* MicroFocus changed
\r
2201 //****************************************************************
\r
2202 private void microFocusChanged() {
\r
2203 boldButton.setDown(false);
\r
2204 italicButton.setDown(false);
\r
2205 underlineButton.setDown(false);
\r
2206 browser.openAction.setEnabled(false);
\r
2207 browser.downloadAttachment.setEnabled(false);
\r
2208 browser.downloadImage.setEnabled(false);
\r
2209 browser.rotateImageLeft.setEnabled(false);
\r
2210 browser.rotateImageRight.setEnabled(false);
\r
2211 browser.insertTableAction.setEnabled(true);
\r
2212 browser.insertTableRowAction.setEnabled(false);
\r
2213 browser.deleteTableRowAction.setEnabled(false);
\r
2214 browser.insertLinkAction.setText(tr("Insert Hyperlink"));
\r
2215 currentHyperlink ="";
\r
2216 insideList = false;
\r
2217 forceTextPaste = false;
\r
2219 String js = new String( "function getCursorPos() {"
\r
2221 +"if (window.getSelection) {"
\r
2222 +" var selObj = window.getSelection();"
\r
2223 +" var selRange = selObj.getRangeAt(0);"
\r
2224 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2225 +" while(workingNode != null) { "
\r
2226 // +" window.jambi.printNode(workingNode.nodeName);"
\r
2227 +" if (workingNode.nodeName=='EN-CRYPT-TEMP') window.jambi.forceTextPaste();"
\r
2228 +" if (workingNode.nodeName=='B') window.jambi.boldActive();"
\r
2229 +" if (workingNode.nodeName=='I') window.jambi.italicActive();"
\r
2230 +" if (workingNode.nodeName=='U') window.jambi.underlineActive();"
\r
2231 +" if (workingNode.nodeName=='UL') window.jambi.setInsideList();"
\r
2232 +" if (workingNode.nodeName=='OL') window.jambi.setInsideList();"
\r
2233 +" if (workingNode.nodeName=='LI') window.jambi.setInsideList();"
\r
2234 +" if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"
\r
2235 +" 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
2236 +" if (workingNode.nodeName=='SPAN') {"
\r
2237 +" if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"
\r
2239 +" workingNode = workingNode.parentNode;"
\r
2242 +"} getCursorPos();");
\r
2243 browser.page().mainFrame().evaluateJavaScript(js);
\r
2246 public void printNode(String n) {
\r
2247 System.out.println("Node Vaule: " +n);
\r
2251 //****************************************************************
\r
2252 //* Insert a table row
\r
2253 //****************************************************************
\r
2254 public void insertTableRow() {
\r
2256 String js = new String( "function insertTableRow() {"
\r
2257 +" var selObj = window.getSelection();"
\r
2258 +" var selRange = selObj.getRangeAt(0);"
\r
2259 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2260 +" var cellCount = 0;"
\r
2261 +" while(workingNode != null) { "
\r
2262 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2263 +" row = document.createElement('TR');"
\r
2264 +" var nodes = workingNode.getElementsByTagName('td');"
\r
2265 +" for (j=0; j<nodes.length; j=j+1) {"
\r
2266 +" cell = document.createElement('TD');"
\r
2267 +" cell.innerHTML=' ';"
\r
2268 +" row.appendChild(cell);"
\r
2270 +" workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"
\r
2273 +" workingNode = workingNode.parentNode;"
\r
2275 +"} insertTableRow();");
\r
2276 browser.page().mainFrame().evaluateJavaScript(js);
\r
2279 //****************************************************************
\r
2280 //* Insert a table row
\r
2281 //****************************************************************
\r
2282 public void deleteTableRow() {
\r
2284 String js = new String( "function deleteTableRow() {"
\r
2285 +" var selObj = window.getSelection();"
\r
2286 +" var selRange = selObj.getRangeAt(0);"
\r
2287 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2288 +" var cellCount = 0;"
\r
2289 +" while(workingNode != null) { "
\r
2290 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2291 +" workingNode.parentNode.removeChild(workingNode);"
\r
2294 +" workingNode = workingNode.parentNode;"
\r
2296 +"} deleteTableRow();");
\r
2297 browser.page().mainFrame().evaluateJavaScript(js);
\r
2300 public void setInsideTable() {
\r
2301 browser.insertTableRowAction.setEnabled(true);
\r
2302 browser.deleteTableRowAction.setEnabled(true);
\r
2303 browser.insertTableAction.setEnabled(false);
\r
2304 browser.encryptAction.setEnabled(false);
\r
2307 public void setInsideLink(String link) {
\r
2308 browser.insertLinkAction.setText(tr("Edit Hyperlink"));
\r
2309 currentHyperlink = link;
\r
2312 public void italicActive() {
\r
2313 italicButton.setDown(true);
\r
2315 public void boldActive() {
\r
2316 boldButton.setDown(true);
\r
2318 public void underlineActive() {
\r
2319 underlineButton.setDown(true);
\r
2321 public void forceTextPaste() {
\r
2322 forceTextPaste = true;
\r
2324 public void imageContextMenu(String f) {
\r
2325 browser.downloadImage.setEnabled(true);
\r
2326 browser.rotateImageRight.setEnabled(true);
\r
2327 browser.rotateImageLeft.setEnabled(true);
\r
2328 browser.openAction.setEnabled(true);
\r
2331 public void rotateImageRight() {
\r
2332 QWebSettings.setMaximumPagesInCache(0);
\r
2333 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2334 QImage image = new QImage(selectedFile);
\r
2335 QMatrix matrix = new QMatrix();
\r
2336 matrix.rotate( 90.0 );
\r
2337 image = image.transformed(matrix);
\r
2338 image.save(selectedFile);
\r
2339 QWebSettings.setMaximumPagesInCache(0);
\r
2340 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2341 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2344 // resourceSignal.contentChanged.emit(selectedFile);
\r
2347 public void rotateImageLeft() {
\r
2348 QImage image = new QImage(selectedFile);
\r
2349 QMatrix matrix = new QMatrix();
\r
2350 matrix.rotate( -90.0 );
\r
2351 image = image.transformed(matrix);
\r
2352 image.save(selectedFile);
\r
2353 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2356 // resourceSignal.contentChanged.emit(selectedFile);
\r
2358 public void resourceContextMenu(String f) {
\r
2359 browser.downloadAttachment.setEnabled(true);
\r
2360 browser.openAction.setEnabled(true);
\r
2365 //****************************************************************
\r
2366 //* Apply CSS style to specified word
\r
2367 //****************************************************************
\r
2368 /* public void applyStyleToWords(String word, String style) {
\r
2369 QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");
\r
2370 script.open(OpenModeFlag.ReadOnly);
\r
2371 String s = script.readAll().toString();
\r
2372 String js = new String(s +" findit('"+word+"', '"+style+"');");
\r
2373 browser.page().mainFrame().evaluateJavaScript(js);
\r
2374 System.out.println(getContent());
\r
2377 //****************************************************************
\r
2378 //* Someone tried to paste a resource between notes, so we need *
\r
2379 //* to do some special handling. *
\r
2380 //****************************************************************
\r
2381 private String fixInternotePaste(String text) {
\r
2382 logger.log(logger.EXTREME, "Fixing internote paste");
\r
2383 String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");
\r
2384 return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");
\r
2386 private String fixInternotePasteSearch(String text, String type, String locTag) {
\r
2388 // First, let's fix the images.
\r
2389 int startPos = text.indexOf(type);
\r
2391 for (; startPos>=0;) {
\r
2392 endPos = text.indexOf(">", startPos+1);
\r
2393 String segment = text.substring(startPos, endPos);
\r
2394 if (segment.indexOf("en-tag") > -1) {
\r
2395 String newSegment = segment;
\r
2397 int guidStartPos = segment.indexOf("guid=\"");
\r
2398 int guidEndPos = segment.indexOf("\"", guidStartPos+7);
\r
2399 String guid = segment.substring(guidStartPos+6,guidEndPos);
\r
2401 int mimeStartPos = segment.indexOf("type");
\r
2402 int mimeEndPos = segment.indexOf("\"", mimeStartPos+7);
\r
2403 String mime = segment.substring(mimeStartPos+6,mimeEndPos);
\r
2405 int srcStartPos = segment.indexOf("src");
\r
2406 int srcEndPos = segment.indexOf("\"", srcStartPos+6);
\r
2407 String src = segment.substring(srcStartPos+5,srcEndPos);
\r
2409 Calendar currentTime = new GregorianCalendar();
\r
2410 Long l = new Long(currentTime.getTimeInMillis());
\r
2411 long prevTime = l;
\r
2412 while (l==prevTime) {
\r
2413 currentTime = new GregorianCalendar();
\r
2414 l= new Long(currentTime.getTimeInMillis());
\r
2417 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2418 // if r==null, then the image doesn't exist (it was probably cut out of another note, so
\r
2419 // we need to recereate it
\r
2421 r = createResource(src, 1, mime, false);
\r
2425 String randint = new String(Long.toString(l));
\r
2426 String extension = null;
\r
2427 if (r.getMime()!= null) {
\r
2428 extension = r.getMime().toLowerCase();
\r
2429 if (extension.indexOf("/")>-1)
\r
2430 extension = extension.substring(extension.indexOf("/")+1);
\r
2432 String newFile = randint;
\r
2433 if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")
\r
2434 if (!locTag.startsWith("src"))
\r
2435 newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();
\r
2436 r.setNoteGuid(currentNote.getGuid());
\r
2438 r.setGuid(randint);
\r
2439 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
2440 QFile f = new QFile(Global.getFileManager().getResDirPath(newFile));
\r
2441 QByteArray bin = new QByteArray(r.getData().getBody());
\r
2442 f.open(QFile.OpenModeFlag.WriteOnly);
\r
2445 newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);
\r
2446 currentNote.getResources().add(r);
\r
2448 int startSrcPos = newSegment.indexOf(locTag);
\r
2449 int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);
\r
2451 if (locTag.startsWith("src")) {
\r
2452 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2453 newSegment = newSegment.replace(source,
\r
2454 FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath(newFile)));
\r
2456 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2457 newSegment = newSegment.replace(source, newFile);
\r
2460 text = text.substring(0,startPos) + newSegment + text.substring(endPos);
\r
2462 startPos = text.indexOf(type, startPos+1);
\r
2468 public void nextPage(String file) {
\r
2469 logger.log(logger.EXTREME, "Starting nextPage()");
\r
2471 Integer pageNumber;
\r
2472 if (previewPageList.containsKey(file))
\r
2473 pageNumber = previewPageList.get(file)+1;
\r
2476 previewPageList.remove(file);
\r