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.net.FileNameMap;
\r
24 import java.net.URI;
\r
25 import java.net.URLConnection;
\r
26 import java.security.MessageDigest;
\r
27 import java.security.NoSuchAlgorithmException;
\r
28 import java.text.SimpleDateFormat;
\r
29 import java.util.ArrayList;
\r
30 import java.util.Calendar;
\r
31 import java.util.Date;
\r
32 import java.util.GregorianCalendar;
\r
33 import java.util.HashMap;
\r
34 import java.util.List;
\r
36 import com.evernote.edam.limits.Constants;
\r
37 import com.evernote.edam.type.Data;
\r
38 import com.evernote.edam.type.Note;
\r
39 import com.evernote.edam.type.Notebook;
\r
40 import com.evernote.edam.type.Resource;
\r
41 import com.evernote.edam.type.ResourceAttributes;
\r
42 import com.evernote.edam.type.Tag;
\r
43 import com.trolltech.qt.core.QByteArray;
\r
44 import com.trolltech.qt.core.QDataStream;
\r
45 import com.trolltech.qt.core.QDateTime;
\r
46 import com.trolltech.qt.core.QEvent;
\r
47 import com.trolltech.qt.core.QFile;
\r
48 import com.trolltech.qt.core.QFileSystemWatcher;
\r
49 import com.trolltech.qt.core.QIODevice;
\r
50 import com.trolltech.qt.core.QMimeData;
\r
51 import com.trolltech.qt.core.QUrl;
\r
52 import com.trolltech.qt.gui.QApplication;
\r
53 import com.trolltech.qt.gui.QCalendarWidget;
\r
54 import com.trolltech.qt.gui.QClipboard;
\r
55 import com.trolltech.qt.gui.QColor;
\r
56 import com.trolltech.qt.gui.QComboBox;
\r
57 import com.trolltech.qt.gui.QDateEdit;
\r
58 import com.trolltech.qt.gui.QDesktopServices;
\r
59 import com.trolltech.qt.gui.QFileDialog;
\r
60 import com.trolltech.qt.gui.QFontDatabase;
\r
61 import com.trolltech.qt.gui.QFormLayout;
\r
62 import com.trolltech.qt.gui.QGridLayout;
\r
63 import com.trolltech.qt.gui.QHBoxLayout;
\r
64 import com.trolltech.qt.gui.QIcon;
\r
65 import com.trolltech.qt.gui.QImage;
\r
66 import com.trolltech.qt.gui.QKeySequence;
\r
67 import com.trolltech.qt.gui.QLabel;
\r
68 import com.trolltech.qt.gui.QLineEdit;
\r
69 import com.trolltech.qt.gui.QListWidgetItem;
\r
70 import com.trolltech.qt.gui.QMatrix;
\r
71 import com.trolltech.qt.gui.QMessageBox;
\r
72 import com.trolltech.qt.gui.QPushButton;
\r
73 import com.trolltech.qt.gui.QShortcut;
\r
74 import com.trolltech.qt.gui.QTimeEdit;
\r
75 import com.trolltech.qt.gui.QVBoxLayout;
\r
76 import com.trolltech.qt.gui.QWidget;
\r
77 import com.trolltech.qt.gui.QFileDialog.AcceptMode;
\r
78 import com.trolltech.qt.gui.QFileDialog.FileMode;
\r
79 import com.trolltech.qt.network.QNetworkRequest;
\r
80 import com.trolltech.qt.webkit.QWebPage;
\r
81 import com.trolltech.qt.webkit.QWebSettings;
\r
82 import com.trolltech.qt.webkit.QWebView;
\r
83 import com.trolltech.qt.webkit.QWebPage.WebAction;
\r
85 import cx.fbn.nevernote.Global;
\r
86 import cx.fbn.nevernote.dialog.EnCryptDialog;
\r
87 import cx.fbn.nevernote.dialog.EnDecryptDialog;
\r
88 import cx.fbn.nevernote.dialog.InsertLinkDialog;
\r
89 import cx.fbn.nevernote.dialog.TableDialog;
\r
90 import cx.fbn.nevernote.dialog.TagAssign;
\r
91 import cx.fbn.nevernote.evernote.EnCrypt;
\r
92 import cx.fbn.nevernote.signals.NoteResourceSignal;
\r
93 import cx.fbn.nevernote.signals.NoteSignal;
\r
94 import cx.fbn.nevernote.sql.DatabaseConnection;
\r
95 import cx.fbn.nevernote.utilities.ApplicationLogger;
\r
96 import cx.fbn.nevernote.utilities.FileUtils;
\r
98 public class BrowserWindow extends QWidget {
\r
100 public final QLineEdit titleLabel;
\r
101 private final QLineEdit urlText;
\r
102 private final QLabel authorLabel;
\r
103 private final QLineEdit authorText;
\r
104 public final TagLineEdit tagEdit;
\r
105 public final QLabel tagLabel;
\r
106 private final QLabel urlLabel;
\r
107 private final QLabel alteredLabel;
\r
108 private final QDateEdit alteredDate;
\r
109 private final QTimeEdit alteredTime;
\r
110 private final QDateEdit createdDate;
\r
111 private final QTimeEdit createdTime;
\r
112 private final QLabel subjectLabel;
\r
113 private final QDateEdit subjectDate;
\r
114 private final QTimeEdit subjectTime;
\r
115 public final QComboBox notebookBox;
\r
116 private final QLabel notebookLabel;
\r
117 private final QLabel createdLabel;
\r
118 public final QComboBox fontSize;
\r
119 private boolean extendedOn;
\r
120 public boolean buttonsVisible;
\r
121 private final String iconPath = new String("classpath:cx/fbn/nevernote/icons/");
\r
122 private final ContentView browser;
\r
123 private List<Tag> allTags;
\r
124 private List<String> currentTags;
\r
125 public NoteSignal noteSignal;
\r
126 private List<Notebook> notebookList;
\r
127 private Note currentNote;
\r
128 private String saveNoteTitle;
\r
129 private String saveTagList;
\r
130 private boolean insideList;
\r
131 // private String selectedText;
\r
132 private final DatabaseConnection conn;
\r
133 private final QCalendarWidget createdCalendarWidget;
\r
134 private final QCalendarWidget alteredCalendarWidget;
\r
135 private final QCalendarWidget subjectCalendarWidget;
\r
137 public final QPushButton undoButton;
\r
138 public final QPushButton redoButton;
\r
139 public final QPushButton cutButton;
\r
140 public final QPushButton copyButton;
\r
141 public final QPushButton pasteButton;
\r
142 public final QPushButton boldButton;
\r
143 public final QPushButton underlineButton;
\r
144 public final QPushButton italicButton;
\r
145 public final Signal0 focusLost;
\r
146 public final NoteResourceSignal resourceSignal;
\r
148 public QPushButton rightAlignButton;
\r
149 public QPushButton leftAlignButton;
\r
150 public QPushButton centerAlignButton;
\r
152 public final QPushButton strikethroughButton;
\r
153 public final QPushButton hlineButton;
\r
154 public final QPushButton indentButton;
\r
155 public final QPushButton outdentButton;
\r
156 public final QPushButton bulletListButton;
\r
157 public final QPushButton numberListButton;
\r
159 public final QShortcut focusTitleShortcut;
\r
160 public final QShortcut focusTagShortcut;
\r
161 public final QShortcut focusNoteShortcut;
\r
162 public final QShortcut focusUrlShortcut;
\r
163 public final QShortcut focusAuthorShortcut;
\r
165 public final QComboBox fontList;
\r
166 public final QPushButton fontColor;
\r
167 private final ColorMenu fontColorMenu;
\r
168 public final QPushButton fontHilight;
\r
169 // public final ColorComboBox fontHilight;
\r
170 private final ColorMenu fontHilightColorMenu;
\r
171 public final QFileSystemWatcher fileWatcher;
\r
172 public int cursorPosition;
\r
173 private boolean forceTextPaste = false;
\r
174 private String selectedFile;
\r
175 private String currentHyperlink;
\r
176 public boolean keepPDFNavigationHidden;
\r
177 private final ApplicationLogger logger;
\r
179 private final HashMap<String,Integer> previewPageList;
\r
182 public BrowserWindow(DatabaseConnection c) {
\r
183 logger = new ApplicationLogger("browser.log");
\r
184 logger.log(logger.HIGH, "Setting up browser");
\r
186 fileWatcher = new QFileSystemWatcher();
\r
187 // fileWatcher.fileChanged.connect(this, "fileChanged(String)");
\r
188 noteSignal = new NoteSignal();
\r
189 titleLabel = new QLineEdit();
\r
190 titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX);
\r
191 urlText = new QLineEdit();
\r
192 authorText = new QLineEdit();
\r
193 urlLabel = new QLabel();
\r
194 authorLabel = new QLabel();
\r
197 focusLost = new Signal0();
\r
199 tagEdit = new TagLineEdit(allTags);
\r
200 tagLabel = new QLabel("Tags:");
\r
201 tagEdit.focusLost.connect(this, "modifyTagsTyping()");
\r
203 createdCalendarWidget = new QCalendarWidget();
\r
204 createdDate = new QDateEdit();
\r
205 createdDate.setDisplayFormat(Global.getDateFormat());
\r
206 createdDate.setCalendarPopup(true);
\r
207 createdDate.setCalendarWidget(createdCalendarWidget);
\r
208 createdTime = new QTimeEdit();
\r
209 createdDate.dateChanged.connect(this, "createdChanged()");
\r
210 createdTime.timeChanged.connect(this, "createdChanged()");
\r
212 alteredCalendarWidget = new QCalendarWidget();
\r
213 alteredDate = new QDateEdit();
\r
214 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
215 alteredDate.setCalendarPopup(true);
\r
216 alteredDate.setCalendarWidget(alteredCalendarWidget);
\r
217 alteredTime = new QTimeEdit();
\r
218 alteredLabel = new QLabel("Altered:");
\r
219 alteredDate.dateChanged.connect(this, "alteredChanged()");
\r
220 alteredTime.timeChanged.connect(this, "alteredChanged()");
\r
222 subjectCalendarWidget = new QCalendarWidget();
\r
223 subjectDate = new QDateEdit();
\r
224 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
225 subjectDate.setCalendarPopup(true);
\r
226 subjectDate.setCalendarWidget(subjectCalendarWidget);
\r
227 subjectTime = new QTimeEdit();
\r
228 subjectLabel = new QLabel("Subject Date:");
\r
229 subjectDate.dateChanged.connect(this, "subjectDateTimeChanged()");
\r
230 subjectTime.timeChanged.connect(this, "subjectDateTimeChanged()");
\r
231 authorText.textChanged.connect(this, "authorChanged()");
\r
232 urlText.textChanged.connect(this, "sourceUrlChanged()");
\r
234 notebookBox = new QComboBox();
\r
235 notebookLabel = new QLabel("Notebook");
\r
236 createdLabel = new QLabel("Created:");
\r
237 // selectedText = new String();
\r
239 urlLabel.setVisible(false);
\r
240 urlText.setVisible(false);
\r
241 authorLabel.setVisible(false);
\r
242 authorText.setVisible(false);
\r
243 createdDate.setVisible(false);
\r
244 alteredLabel.setVisible(false);
\r
245 //notebookBox.setVisible(false);
\r
246 notebookLabel.setVisible(false);
\r
247 createdLabel.setVisible(false);
\r
248 createdTime.setVisible(false);
\r
249 alteredDate.setVisible(false);
\r
250 alteredTime.setVisible(false);
\r
251 subjectLabel.setVisible(false);
\r
252 subjectDate.setVisible(false);
\r
253 subjectTime.setVisible(false);
\r
254 extendedOn = false;
\r
255 buttonsVisible = true;
\r
256 setAcceptDrops(true);
\r
258 browser = new ContentView(this);
\r
259 browser.page().setLinkDelegationPolicy(
\r
260 QWebPage.LinkDelegationPolicy.DelegateAllLinks);
\r
261 browser.linkClicked.connect(this, "linkClicked(QUrl)");
\r
262 currentHyperlink = "";
\r
264 QVBoxLayout v = new QVBoxLayout();
\r
265 QFormLayout notebookLayout = new QFormLayout();
\r
266 QGridLayout dateLayout = new QGridLayout();
\r
267 titleLabel.setReadOnly(false);
\r
268 titleLabel.editingFinished.connect(this, "titleEdited()");
\r
269 browser.page().contentsChanged.connect(this, "contentChanged()");
\r
270 browser.page().selectionChanged.connect(this, "selectionChanged()");
\r
271 browser.page().mainFrame().javaScriptWindowObjectCleared.connect(this,
\r
272 "exposeToJavascript()");
\r
274 notebookBox.activated.connect(this, "notebookChanged()");
\r
275 resourceSignal = new NoteResourceSignal();
\r
277 QHBoxLayout tagLayout = new QHBoxLayout();
\r
278 v.addWidget(titleLabel, 0);
\r
279 notebookLayout.addRow(notebookLabel, notebookBox);
\r
280 tagLayout.addLayout(notebookLayout, 0);
\r
281 tagLayout.stretch(4);
\r
282 tagLayout.addWidget(tagLabel, 0);
\r
283 tagLayout.addWidget(tagEdit, 1);
\r
284 v.addLayout(tagLayout);
\r
286 QHBoxLayout urlLayout = new QHBoxLayout();
\r
287 urlLayout.addWidget(urlLabel, 0);
\r
288 urlLayout.addWidget(urlText, 0);
\r
289 v.addLayout(urlLayout);
\r
291 QHBoxLayout authorLayout = new QHBoxLayout();
\r
292 authorLayout.addWidget(authorLabel, 0);
\r
293 authorLayout.addWidget(authorText, 0);
\r
294 v.addLayout(authorLayout);
\r
296 dateLayout.addWidget(createdLabel, 0, 0);
\r
297 dateLayout.addWidget(createdDate, 0, 1);
\r
298 dateLayout.addWidget(createdTime, 0, 2);
\r
299 dateLayout.setColumnStretch(9, 100);
\r
300 dateLayout.addWidget(alteredLabel, 0, 3);
\r
301 dateLayout.addWidget(alteredDate, 0, 4);
\r
302 dateLayout.addWidget(alteredTime, 0, 5);
\r
303 dateLayout.addWidget(subjectLabel, 0, 6);
\r
304 dateLayout.addWidget(subjectDate, 0, 7);
\r
305 dateLayout.addWidget(subjectTime, 0, 8);
\r
306 v.addLayout(dateLayout, 0);
\r
308 undoButton = newEditorButton("undo", "Undo Change");
\r
309 redoButton = newEditorButton("redo", "Redo Change");
\r
310 cutButton = newEditorButton("cut", "Cut");
\r
311 copyButton = newEditorButton("copy", "Copy");
\r
312 pasteButton = newEditorButton("paste", "Paste");
\r
313 boldButton = newEditorButton("bold", "Bold");
\r
314 underlineButton = newEditorButton("underline", "Underline");
\r
315 italicButton = newEditorButton("italic", "Italic");
\r
317 rightAlignButton = newEditorButton("justifyRight", "Right Align");
\r
318 leftAlignButton = newEditorButton("justifyLeft", "Left Align");
\r
319 centerAlignButton = newEditorButton("justifyCenter", "Center Align");
\r
321 strikethroughButton = newEditorButton("strikethrough", "Strikethrough");
\r
322 hlineButton = newEditorButton("hline", "Insert Horizontal Line");
\r
323 indentButton = newEditorButton("indent", "Shift Right");
\r
324 outdentButton = newEditorButton("outdent", "Shift Left");
\r
325 bulletListButton = newEditorButton("bulletList", "Bullet List");
\r
326 numberListButton = newEditorButton("numberList", "Number List");
\r
329 QHBoxLayout buttonLayout;
\r
330 buttonLayout = new QHBoxLayout();
\r
331 buttonLayout.setSpacing(0);
\r
332 v.addLayout(buttonLayout);
\r
334 buttonLayout.addWidget(undoButton);
\r
335 buttonLayout.addWidget(redoButton);
\r
337 buttonLayout.addWidget(newSeparator(), 0);
\r
338 buttonLayout.addWidget(cutButton);
\r
339 buttonLayout.addWidget(copyButton);
\r
340 buttonLayout.addWidget(pasteButton);
\r
342 buttonLayout.addWidget(newSeparator(), 0);
\r
343 buttonLayout.addWidget(boldButton);
\r
344 buttonLayout.addWidget(italicButton);
\r
345 buttonLayout.addWidget(underlineButton);
\r
346 buttonLayout.addWidget(strikethroughButton);
\r
348 buttonLayout.addWidget(newSeparator(), 0);
\r
349 buttonLayout.addWidget(leftAlignButton);
\r
350 buttonLayout.addWidget(centerAlignButton);
\r
351 buttonLayout.addWidget(rightAlignButton);
\r
353 buttonLayout.addWidget(newSeparator(), 0);
\r
354 buttonLayout.addWidget(hlineButton);
\r
356 buttonLayout.addWidget(indentButton);
\r
357 buttonLayout.addWidget(outdentButton);
\r
358 buttonLayout.addWidget(bulletListButton);
\r
359 buttonLayout.addWidget(numberListButton);
\r
361 // Setup the font & font size combo boxes
\r
362 buttonLayout.addWidget(newSeparator(), 0);
\r
363 fontList = new QComboBox();
\r
364 fontSize = new QComboBox();
\r
365 fontList.setToolTip("Font");
\r
366 fontSize.setToolTip("Font Size");
\r
367 fontList.activated.connect(this, "fontChanged(String)");
\r
368 fontSize.activated.connect(this, "fontSizeChanged(String)");
\r
369 buttonLayout.addWidget(fontList, 0);
\r
370 buttonLayout.addWidget(fontSize, 0);
\r
371 QFontDatabase fonts = new QFontDatabase();
\r
372 List<String> fontFamilies = fonts.families();
\r
373 for (int i = 0; i < fontFamilies.size(); i++) {
\r
374 fontList.addItem(fontFamilies.get(i));
\r
376 loadFontSize(fontFamilies.get(i));
\r
380 buttonLayout.addWidget(newSeparator(), 0);
\r
381 fontColor = newEditorButton("fontColor", "Font Color");
\r
382 fontColorMenu = new ColorMenu(this);
\r
383 fontColor.setMenu(fontColorMenu.getMenu());
\r
384 fontColorMenu.getMenu().triggered.connect(this, "fontColorClicked()");
\r
385 buttonLayout.addWidget(fontColor);
\r
386 fontHilight = newEditorButton("fontHilight", "Font Hilight Color");
\r
387 fontHilightColorMenu = new ColorMenu(this);
\r
388 fontHilight.setMenu(fontHilightColorMenu.getMenu());
\r
389 fontHilightColorMenu.getMenu().triggered.connect(this, "fontHilightClicked()");
\r
390 buttonLayout.addWidget(fontHilight);
\r
392 buttonLayout.addWidget(new QLabel(), 1);
\r
393 v.addWidget(browser, 1);
\r
394 // v.addLayout(buttonLayout,0);
\r
397 browser.downloadAttachmentRequested.connect(this,
\r
398 "downloadAttachment(QNetworkRequest)");
\r
399 browser.downloadImageRequested.connect(this,
\r
400 "downloadImage(QNetworkRequest)");
\r
401 setTabOrder(notebookBox, tagEdit);
\r
402 setTabOrder(tagEdit, browser);
\r
404 focusNoteShortcut = new QShortcut(this);
\r
405 setupShortcut(focusNoteShortcut, "Focus_Note");
\r
406 focusNoteShortcut.activated.connect(this, "focusNote()");
\r
407 focusTitleShortcut = new QShortcut(this);
\r
408 setupShortcut(focusTitleShortcut, "Focus_Title");
\r
409 focusTitleShortcut.activated.connect(this, "focusTitle()");
\r
410 focusTagShortcut = new QShortcut(this);
\r
411 setupShortcut(focusTagShortcut, "Focus_Tag");
\r
412 focusTagShortcut.activated.connect(this, "focusTag()");
\r
413 focusAuthorShortcut = new QShortcut(this);
\r
414 setupShortcut(focusAuthorShortcut, "Focus_Author");
\r
415 focusAuthorShortcut.activated.connect(this, "focusAuthor()");
\r
416 focusUrlShortcut = new QShortcut(this);
\r
417 setupShortcut(focusUrlShortcut, "Focus_Url");
\r
418 focusUrlShortcut.activated.connect(this, "focusUrl()");
\r
420 browser.page().mainFrame().setTextSizeMultiplier(Global.getTextSizeMultiplier());
\r
421 browser.page().mainFrame().setZoomFactor(Global.getZoomFactor());
\r
423 previewPageList = new HashMap<String,Integer>();
\r
425 browser.page().microFocusChanged.connect(this, "microFocusChanged()");
\r
426 logger.log(logger.HIGH, "Browser setup complete");
\r
430 private void setupShortcut(QShortcut action, String text) {
\r
431 if (!Global.shortcutKeys.containsAction(text))
\r
433 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
\r
439 // Getter for the QWebView
\r
440 public QWebView getBrowser() {
\r
444 // Block signals while loading data or things are flagged as dirty by
\r
446 public void loadingData(boolean val) {
\r
447 logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val);
\r
448 notebookBox.blockSignals(val);
\r
449 browser.page().blockSignals(val);
\r
450 browser.page().mainFrame().blockSignals(val);
\r
451 titleLabel.blockSignals(val);
\r
452 alteredDate.blockSignals(val);
\r
453 alteredTime.blockSignals(val);
\r
454 createdTime.blockSignals(val);
\r
455 createdDate.blockSignals(val);
\r
456 subjectDate.blockSignals(val);
\r
457 subjectTime.blockSignals(val);
\r
458 urlText.blockSignals(val);
\r
459 authorText.blockSignals(val);
\r
461 exposeToJavascript();
\r
462 logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val);
\r
466 public void setReadOnly(boolean v) {
\r
468 titleLabel.setEnabled(!v);
\r
469 notebookBox.setEnabled(!v);
\r
470 tagEdit.setEnabled(!v);
\r
471 authorLabel.setEnabled(!v);
\r
472 urlText.setEnabled(!v);
\r
473 createdDate.setEnabled(!v);
\r
474 subjectDate.setEnabled(!v);
\r
475 alteredDate.setEnabled(!v);
\r
476 getBrowser().setEnabled(true);
\r
479 // expose this class to Javascript on the web page
\r
480 private void exposeToJavascript() {
\r
481 browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this);
\r
484 // Custom event queue
\r
486 public boolean event(QEvent e) {
\r
487 if (e.type().equals(QEvent.Type.FocusOut)) {
\r
488 logger.log(logger.EXTREME, "Focus lost");
\r
491 return super.event(e);
\r
494 // clear out browser
\r
495 public void clear() {
\r
496 logger.log(logger.EXTREME, "Entering BrowserWindow.clear()");
\r
498 browser.setContent(new QByteArray());
\r
499 tagEdit.setText("");
\r
500 urlLabel.setText("Source URL:");
\r
501 titleLabel.setText("");
\r
502 logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()");
\r
505 // get/set current note
\r
506 public void setNote(Note n) {
\r
510 saveNoteTitle = n.getTitle();
\r
514 public Note getNote() {
\r
515 return currentNote;
\r
518 // New Editor Button
\r
519 private QPushButton newEditorButton(String name, String toolTip) {
\r
520 QPushButton button = new QPushButton();
\r
521 QIcon icon = new QIcon(iconPath + name + ".gif");
\r
522 button.setIcon(icon);
\r
523 button.setToolTip(toolTip);
\r
524 button.clicked.connect(this, name + "Clicked()");
\r
529 private QLabel newSeparator() {
\r
530 return new QLabel(" ");
\r
533 // Set the title in the window
\r
534 public void setTitle(String t) {
\r
535 titleLabel.setText(t);
\r
540 // Return the current text title
\r
541 public String getTitle() {
\r
542 return titleLabel.text();
\r
545 // Set the tag name string
\r
546 public void setTag(String t) {
\r
548 tagEdit.setText(t);
\r
551 // Set the source URL
\r
552 public void setUrl(String t) {
\r
553 urlLabel.setText("Source URL:\t");
\r
554 urlText.setText(t);
\r
557 public void setAuthor(String t) {
\r
558 authorLabel.setText("Author:\t");
\r
559 authorText.setText(t);
\r
562 // Set the creation date
\r
563 public void setCreation(long date) {
\r
564 QDateTime dt = new QDateTime();
\r
565 dt.setTime_t((int) (date / 1000));
\r
566 createdDate.setDateTime(dt);
\r
567 createdTime.setDateTime(dt);
\r
568 createdDate.setDisplayFormat(Global.getDateFormat());
\r
569 createdTime.setDisplayFormat(Global.getTimeFormat());
\r
572 // Set the creation date
\r
573 public void setAltered(long date) {
\r
574 QDateTime dt = new QDateTime();
\r
575 dt.setTime_t((int) (date / 1000));
\r
576 alteredDate.setDateTime(dt);
\r
577 alteredTime.setDateTime(dt);
\r
578 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
579 alteredTime.setDisplayFormat(Global.getTimeFormat());
\r
582 // Set the subject date
\r
583 public void setSubjectDate(long date) {
\r
584 QDateTime dt = new QDateTime();
\r
585 dt.setTime_t((int) (date / 1000));
\r
586 subjectDate.setDateTime(dt);
\r
587 subjectTime.setDateTime(dt);
\r
588 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
589 subjectTime.setDisplayFormat(Global.getTimeFormat());
\r
592 // Toggle the extended attribute information
\r
593 public void toggleInformation() {
\r
595 extendedOn = false;
\r
599 urlLabel.setVisible(extendedOn);
\r
600 urlText.setVisible(extendedOn);
\r
601 authorText.setVisible(extendedOn);
\r
602 authorLabel.setVisible(extendedOn);
\r
603 createdDate.setVisible(extendedOn);
\r
604 createdTime.setVisible(extendedOn);
\r
605 createdLabel.setVisible(extendedOn);
\r
606 alteredLabel.setVisible(extendedOn);
\r
607 alteredDate.setVisible(extendedOn);
\r
608 alteredTime.setVisible(extendedOn);
\r
609 //notebookBox.setVisible(extendedOn);
\r
610 notebookLabel.setVisible(extendedOn);
\r
611 subjectLabel.setVisible(extendedOn);
\r
612 subjectDate.setVisible(extendedOn);
\r
613 subjectTime.setVisible(extendedOn);
\r
616 public void hideButtons() {
\r
618 buttonsVisible = false;
\r
620 undoButton.setVisible(false);
\r
621 redoButton.setVisible(false);
\r
622 cutButton.setVisible(false);
\r
623 copyButton.setVisible(false);
\r
624 pasteButton.setVisible(false);
\r
625 boldButton.setVisible(false);
\r
626 underlineButton.setVisible(false);
\r
627 italicButton.setVisible(false);
\r
629 rightAlignButton.setVisible(false);
\r
630 leftAlignButton.setVisible(false);
\r
631 centerAlignButton.setVisible(false);
\r
633 strikethroughButton.setVisible(false);
\r
634 hlineButton.setVisible(false);
\r
635 indentButton.setVisible(false);
\r
636 outdentButton.setVisible(false);
\r
637 bulletListButton.setVisible(false);
\r
638 numberListButton.setVisible(false);
\r
640 fontList.setVisible(false);
\r
641 fontSize.setVisible(false);
\r
642 fontColor.setVisible(false);
\r
643 fontHilight.setVisible(false);
\r
648 // Is the extended view on?
\r
649 public boolean isExtended() {
\r
653 // Listener for when a link is clicked
\r
654 @SuppressWarnings("unused")
\r
655 private void openFile() {
\r
656 logger.log(logger.EXTREME, "Starting openFile()");
\r
657 File fileHandle = new File(selectedFile);
\r
658 URI fileURL = fileHandle.toURI();
\r
659 String localURL = fileURL.toString();
\r
660 QUrl url = new QUrl(localURL);
\r
661 QFile file = new QFile(selectedFile);
\r
663 logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName());
\r
664 fileWatcher.addPath(file.fileName());
\r
666 if (!QDesktopServices.openUrl(url)) {
\r
667 logger.log(logger.LOW, "Error opening file :" +url);
\r
672 // Listener for when a link is clicked
\r
673 @SuppressWarnings("unused")
\r
674 private void linkClicked(QUrl url) {
\r
675 logger.log(logger.EXTREME, "URL Clicked: " +url.toString());
\r
676 if (url.toString().substring(0,8).equals("nnres://")) {
\r
677 logger.log(logger.EXTREME, "URL is NN resource");
\r
678 if (url.toString().endsWith("/vnd.evernote.ink")) {
\r
679 logger.log(logger.EXTREME, "Unable to open ink note");
\r
680 QMessageBox.information(this, "Unable Open", "This is an ink note.\n"+
\r
681 "Ink notes are not supported since Evernote has not\n published any specifications on them\n" +
\r
682 "and I'm too lazy to figure them out by myself.");
\r
685 String fullName = url.toString().substring(8);
\r
686 int index = fullName.indexOf(".");
\r
690 type = fullName.substring(index+1);
\r
691 guid = fullName.substring(0,index);
\r
693 index = guid.indexOf(Global.attachmentNameDelimeter);
\r
695 guid = guid.substring(0,index);
\r
697 List<Resource> resList = currentNote.getResources();
\r
698 Resource res = null;
\r
699 for (int i=0; i<resList.size(); i++) {
\r
700 if (resList.get(i).getGuid().equals(guid)) {
\r
701 res = resList.get(i);
\r
706 String resGuid = Global.resourceMap.get(guid);
\r
707 if (resGuid != null)
\r
708 res = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, true);
\r
712 if (res.getAttributes() != null &&
\r
713 res.getAttributes().getFileName() != null &&
\r
714 !res.getAttributes().getFileName().trim().equals(""))
\r
715 fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();
\r
717 fileName = res.getGuid()+"."+type;
\r
718 QFile file = new QFile(Global.getDirectoryPath() +"res/"+fileName);
\r
719 QFile.OpenMode mode = new QFile.OpenMode();
\r
720 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
721 boolean openResult = file.open(mode);
\r
722 logger.log(logger.EXTREME, "File opened:" +openResult);
\r
723 QDataStream out = new QDataStream(file);
\r
724 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);
\r
725 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
727 logger.log(logger.EXTREME, "Writing resource");
\r
728 out.writeBytes(binData.toByteArray());
\r
731 String whichOS = System.getProperty("os.name");
\r
732 if (whichOS.contains("Windows"))
\r
733 url.setUrl("file:///"+file.fileName());
\r
735 url.setUrl("file://"+file.fileName());
\r
736 // fileWatcher.removePath(file.fileName());
\r
737 logger.log(logger.EXTREME, "Adding file watcher " +file.fileName());
\r
738 fileWatcher.addPath(file.fileName());
\r
740 // If we can't open it, then prompt the user to save it.
\r
741 if (!QDesktopServices.openUrl(url)) {
\r
742 logger.log(logger.EXTREME, "We can't handle this. Where do we put it?");
\r
743 QFileDialog dialog = new QFileDialog();
\r
745 if (dialog.exec()!=0) {
\r
746 List<String> fileNames = dialog.selectedFiles(); //gets all selected filenames
\r
747 if (fileNames.size() == 0)
\r
749 String sf = fileNames.get(0);
\r
750 QFile saveFile = new QFile(sf);
\r
751 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
752 saveFile.open(mode);
\r
753 QDataStream saveOut = new QDataStream(saveFile);
\r
754 saveOut.writeBytes(binData.toByteArray());
\r
762 logger.log(logger.EXTREME, "Launching URL");
\r
763 QDesktopServices.openUrl(url);
\r
766 // Listener for when BOLD is clicked
\r
767 @SuppressWarnings("unused")
\r
768 private void undoClicked() {
\r
769 browser.page().triggerAction(WebAction.Undo);
\r
770 browser.setFocus();
\r
773 // Listener for when BOLD is clicked
\r
774 @SuppressWarnings("unused")
\r
775 private void redoClicked() {
\r
776 browser.page().triggerAction(WebAction.Redo);
\r
777 browser.setFocus();
\r
780 // Listener for when BOLD is clicked
\r
781 @SuppressWarnings("unused")
\r
782 private void boldClicked() {
\r
783 browser.page().triggerAction(WebAction.ToggleBold);
\r
784 microFocusChanged();
\r
785 browser.setFocus();
\r
788 // Listener for when Italics is clicked
\r
789 @SuppressWarnings("unused")
\r
790 private void italicClicked() {
\r
791 browser.page().triggerAction(WebAction.ToggleItalic);
\r
792 microFocusChanged();
\r
793 browser.setFocus();
\r
796 // Listener for when UNDERLINE is clicked
\r
797 @SuppressWarnings("unused")
\r
798 private void underlineClicked() {
\r
799 browser.page().triggerAction(WebAction.ToggleUnderline);
\r
800 microFocusChanged();
\r
801 browser.setFocus();
\r
804 // Listener for when Strikethrough is clicked
\r
805 @SuppressWarnings("unused")
\r
806 private void strikethroughClicked() {
\r
807 browser.page().mainFrame().evaluateJavaScript(
\r
808 "document.execCommand('strikeThrough', false, '');");
\r
809 browser.setFocus();
\r
812 // Listener for when cut is clicked
\r
813 @SuppressWarnings("unused")
\r
814 private void cutClicked() {
\r
815 browser.page().triggerAction(WebAction.Cut);
\r
816 browser.setFocus();
\r
819 // Listener when COPY is clicked
\r
820 @SuppressWarnings("unused")
\r
821 private void copyClicked() {
\r
822 browser.page().triggerAction(WebAction.Copy);
\r
823 browser.setFocus();
\r
826 // Listener when PASTE is clicked
\r
827 void pasteClicked() {
\r
828 logger.log(logger.EXTREME, "Paste Clicked");
\r
829 if (forceTextPaste) {
\r
830 pasteWithoutFormattingClicked();
\r
833 QClipboard clipboard = QApplication.clipboard();
\r
834 QMimeData mime = clipboard.mimeData();
\r
836 // String x = mime.html();
\r
838 if (mime.hasImage()) {
\r
839 logger.log(logger.EXTREME, "Image paste found");
\r
841 browser.setFocus();
\r
845 if (mime.hasUrls()) {
\r
846 logger.log(logger.EXTREME, "URL paste found");
\r
848 browser.setFocus();
\r
852 String text = mime.html();
\r
853 if (text.contains("en-tag") && mime.hasHtml()) {
\r
854 logger.log(logger.EXTREME, "Intra-note paste found");
\r
855 text = fixInternotePaste(text);
\r
856 mime.setHtml(text);
\r
857 clipboard.setMimeData(mime);
\r
860 logger.log(logger.EXTREME, "Final paste choice encountered");
\r
861 browser.page().triggerAction(WebAction.Paste);
\r
862 browser.setFocus();
\r
866 // Paste text without formatting
\r
867 private void pasteWithoutFormattingClicked() {
\r
868 logger.log(logger.EXTREME, "Paste without format clipped");
\r
869 QClipboard clipboard = QApplication.clipboard();
\r
870 QMimeData mime = clipboard.mimeData();
\r
871 if (!mime.hasText())
\r
873 String text = mime.text();
\r
874 clipboard.setText(text);
\r
875 browser.page().triggerAction(WebAction.Paste);
\r
876 QApplication.clipboard().setMimeData(mime);
\r
877 browser.setFocus();
\r
881 // insert date/time
\r
882 @SuppressWarnings("unused")
\r
883 private void insertDateTime() {
\r
884 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
\r
885 String dateTimeFormat = new String(fmt);
\r
886 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
\r
887 Calendar cal = Calendar.getInstance();
\r
889 browser.page().mainFrame().evaluateJavaScript(
\r
890 "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");
\r
892 browser.setFocus();
\r
896 // Listener when Left is clicked
\r
897 @SuppressWarnings("unused")
\r
898 private void justifyLeftClicked() {
\r
899 browser.page().mainFrame().evaluateJavaScript(
\r
900 "document.execCommand('JustifyLeft', false, '');");
\r
901 browser.setFocus();
\r
904 // Listener when Center is clicked
\r
905 @SuppressWarnings("unused")
\r
906 private void justifyCenterClicked() {
\r
907 browser.page().mainFrame().evaluateJavaScript(
\r
908 "document.execCommand('JustifyCenter', false, '');");
\r
909 browser.setFocus();
\r
912 // Listener when Left is clicked
\r
913 @SuppressWarnings("unused")
\r
914 private void justifyRightClicked() {
\r
915 browser.page().mainFrame().evaluateJavaScript(
\r
916 "document.execCommand('JustifyRight', false, '');");
\r
917 browser.setFocus();
\r
920 // Listener when HLINE is clicked
\r
921 @SuppressWarnings("unused")
\r
922 private void hlineClicked() {
\r
923 browser.page().mainFrame().evaluateJavaScript(
\r
924 "document.execCommand('insertHorizontalRule', false, '');");
\r
925 browser.setFocus();
\r
928 // Listener when outdent is clicked
\r
929 private void outdentClicked() {
\r
930 browser.page().mainFrame().evaluateJavaScript(
\r
931 "document.execCommand('outdent', false, '');");
\r
932 browser.setFocus();
\r
935 // Listener when a bullet list is clicked
\r
936 @SuppressWarnings("unused")
\r
937 private void bulletListClicked() {
\r
938 browser.page().mainFrame().evaluateJavaScript(
\r
939 "document.execCommand('InsertUnorderedList', false, '');");
\r
940 browser.setFocus();
\r
943 // Listener when a bullet list is clicked
\r
944 @SuppressWarnings("unused")
\r
945 private void numberListClicked() {
\r
946 browser.page().mainFrame().evaluateJavaScript(
\r
947 "document.execCommand('InsertOrderedList', false, '');");
\r
948 browser.setFocus();
\r
951 // Listener when indent is clicked
\r
952 private void indentClicked() {
\r
953 browser.page().mainFrame().evaluateJavaScript(
\r
954 "document.execCommand('indent', false, '');");
\r
955 browser.setFocus();
\r
958 // Listener when the font name is changed
\r
959 @SuppressWarnings("unused")
\r
960 private void fontChanged(String font) {
\r
961 browser.page().mainFrame().evaluateJavaScript(
\r
962 "document.execCommand('fontName',false,'" + font + "');");
\r
963 browser.setFocus();
\r
966 // Listener when a font size is changed
\r
967 @SuppressWarnings("unused")
\r
968 private void fontSizeChanged(String font) {
\r
969 String text = browser.selectedText();
\r
970 if (text.trim().equalsIgnoreCase(""))
\r
973 String selectedText = browser.selectedText();
\r
974 String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";
\r
975 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
976 browser.page().mainFrame().evaluateJavaScript(script);
\r
977 /* browser.page().mainFrame().evaluateJavaScript(
\r
978 "document.execCommand('fontSize',false,'"
\r
981 browser.setFocus();
\r
984 // Load the font combo box based upon the font selected
\r
985 private void loadFontSize(String name) {
\r
986 QFontDatabase db = new QFontDatabase();
\r
988 List<Integer> points = db.pointSizes(name);
\r
989 for (int i=0; i<points.size(); i++) {
\r
990 fontSize.addItem(points.get(i).toString());
\r
993 fontSize.addItem("x-small");
\r
994 fontSize.addItem("small");
\r
995 fontSize.addItem("medium");
\r
996 fontSize.addItem("large");
\r
997 fontSize.addItem("x-large");
\r
998 fontSize.addItem("xx-large");
\r
999 fontSize.addItem("xxx-large");
\r
1003 // Listener when a font size is changed
\r
1004 @SuppressWarnings("unused")
\r
1005 private void fontColorClicked() {
\r
1006 // QColorDialog dialog = new QColorDialog();
\r
1007 // QColor color = QColorDialog.getColor();
\r
1008 QColor color = fontColorMenu.getColor();
\r
1009 if (color.isValid())
\r
1010 browser.page().mainFrame().evaluateJavaScript(
\r
1011 "document.execCommand('foreColor',false,'" + color.name()
\r
1013 browser.setFocus();
\r
1016 // Listener for when a background color change is requested
\r
1017 @SuppressWarnings("unused")
\r
1018 private void fontHilightClicked() {
\r
1019 // QColorDialog dialog = new QColorDialog();
\r
1020 // QColor color = QColorDialog.getColor();
\r
1021 QColor color = fontHilightColorMenu.getColor();
\r
1022 if (color.isValid())
\r
1023 browser.page().mainFrame().evaluateJavaScript(
\r
1024 "document.execCommand('backColor',false,'" + color.name()
\r
1026 browser.setFocus();
\r
1029 // Listener for when a background color change is requested
\r
1030 @SuppressWarnings("unused")
\r
1031 private void superscriptClicked() {
\r
1032 browser.page().mainFrame().evaluateJavaScript(
\r
1033 "document.execCommand('superscript');");
\r
1034 browser.setFocus();
\r
1037 // Listener for when a background color change is requested
\r
1038 @SuppressWarnings("unused")
\r
1039 private void subscriptClicked() {
\r
1040 browser.page().mainFrame().evaluateJavaScript(
\r
1041 "document.execCommand('subscript');");
\r
1042 browser.setFocus();
\r
1044 // Insert a to-do checkbox
\r
1045 @SuppressWarnings("unused")
\r
1046 private void todoClicked() {
\r
1047 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1048 String script_start = new String(
\r
1049 "document.execCommand('insertHtml', false, '");
\r
1050 String script_end = new String("');");
\r
1051 String todo = new String(
\r
1052 "<input TYPE=\"CHECKBOX\" value=\"false\" onClick=\"value=checked; window.jambi.contentChanged(); \" />");
\r
1053 browser.page().mainFrame().evaluateJavaScript(
\r
1054 script_start + todo + script_end);
\r
1055 browser.setFocus();
\r
1058 // Encrypt the selected text
\r
1059 @SuppressWarnings("unused")
\r
1060 private void encryptText() {
\r
1061 String text = browser.selectedText();
\r
1062 if (text.trim().equalsIgnoreCase(""))
\r
1065 EnCryptDialog dialog = new EnCryptDialog();
\r
1067 if (!dialog.okPressed()) {
\r
1071 EnCrypt crypt = new EnCrypt();
\r
1072 String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);
\r
1074 if (encrypted.trim().equals("")) {
\r
1075 QMessageBox.information(this, "Error", "Error Encrypting String");
\r
1078 StringBuffer buffer = new StringBuffer(encrypted.length() + 100);
\r
1079 buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""
\r
1080 + dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");
\r
1081 buffer.append("contentEditable=\"false\" alt=\"");
\r
1082 buffer.append(encrypted);
\r
1083 // NFC FIXME: should this be a file URL like in handleLocalAttachment and importAttachment?
\r
1084 buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png")));
\r
1085 Global.cryptCounter++;
\r
1086 buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");
\r
1087 buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");
\r
1088 buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString()
\r
1089 +"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&apos;")+"\\');\"");
\r
1090 buffer.append("style=\"display:block\" />");
\r
1092 String script_start = new String(
\r
1093 "document.execCommand('insertHtml', false, '");
\r
1094 String script_end = new String("');");
\r
1095 browser.page().mainFrame().evaluateJavaScript(
\r
1096 script_start + buffer.toString() + script_end);
\r
1100 // Insert a hyperlink
\r
1101 public void insertLink() {
\r
1102 logger.log(logger.EXTREME, "Inserting link");
\r
1103 String text = browser.selectedText();
\r
1104 if (text.trim().equalsIgnoreCase(""))
\r
1107 InsertLinkDialog dialog = new InsertLinkDialog();
\r
1108 if (currentHyperlink != null && currentHyperlink != "") {
\r
1109 dialog.setUrl(currentHyperlink);
\r
1112 if (!dialog.okPressed()) {
\r
1113 logger.log(logger.EXTREME, "Insert link canceled");
\r
1116 if (browser.insertLinkAction.text().equalsIgnoreCase("Insert Hyperlink")) {
\r
1117 String selectedText = browser.selectedText();
\r
1118 logger.log(logger.EXTREME, "Inserting link on text "+selectedText);
\r
1119 logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim());
\r
1120 String url = "<a href=\"" +dialog.getUrl().trim()+"\" >"+selectedText +"</a>";
\r
1121 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1122 browser.page().mainFrame().evaluateJavaScript(script);
\r
1125 String js = new String( "function getCursorPos() {"
\r
1127 +"if (window.getSelection) {"
\r
1128 +" var selObj = window.getSelection();"
\r
1129 +" var selRange = selObj.getRangeAt(0);"
\r
1130 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1131 +" while(workingNode != null) { "
\r
1132 +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');"
\r
1133 +" workingNode = workingNode.parentNode;"
\r
1136 +"} getCursorPos();");
\r
1137 browser.page().mainFrame().evaluateJavaScript(js);
\r
1144 public void insertTable() {
\r
1145 TableDialog dialog = new TableDialog();
\r
1147 if (!dialog.okPressed()) {
\r
1151 int cols = dialog.getCols();
\r
1152 int rows = dialog.getRows();
\r
1153 int width = dialog.getWidth();
\r
1154 boolean percent = dialog.isPercent();
\r
1156 String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();
\r
1158 newHTML = newHTML +"%";
\r
1159 newHTML = newHTML + "\"><tbody>";
\r
1161 for (int i=0; i<rows; i++) {
\r
1162 newHTML = newHTML +"<tr>";
\r
1163 for (int j=0; j<cols; j++) {
\r
1164 newHTML = newHTML +"<td> </td>";
\r
1166 newHTML = newHTML +"</tr>";
\r
1168 newHTML = newHTML+"</tbody></table>";
\r
1170 String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";
\r
1171 browser.page().mainFrame().evaluateJavaScript(script);
\r
1175 // Text content changed
\r
1176 @SuppressWarnings("unused")
\r
1177 private void selectionChanged() {
\r
1178 browser.encryptAction.setEnabled(true);
\r
1179 browser.insertLinkAction.setEnabled(true);
\r
1180 String scriptStart = "var selection_text = (window.getSelection()).toString();"
\r
1181 + "var range = (window.getSelection()).getRangeAt(0);"
\r
1182 + "var parent_html = range.commonAncestorContainer.innerHTML;"
\r
1183 + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"
\r
1184 + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"
\r
1185 + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"
\r
1186 + "var start = parent_html.indexOf(first_text);"
\r
1187 + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"
\r
1188 + "var value = parent_html.substring(start,end);"
\r
1189 + "window.jambi.saveSelectedText(value);" ;
\r
1190 browser.page().mainFrame().evaluateJavaScript(scriptStart);
\r
1194 public void saveSelectedText(String text) {
\r
1195 boolean enabled = true;
\r
1196 if (text.trim().length() == 0)
\r
1198 if (text.indexOf("en-tag=\"en-crypt\"") >= 0)
\r
1200 if (text.indexOf("<img en-tag=\"en-media\"") >= 0)
\r
1202 if (text.indexOf("<a en-tag=\"en-media\"") >= 0)
\r
1204 if (text.indexOf("<input ") >= 0)
\r
1207 browser.encryptAction.setEnabled(enabled);
\r
1208 browser.insertLinkAction.setEnabled(enabled);
\r
1209 // selectedText = text;
\r
1212 // Decrypt clicked text
\r
1213 public void decryptText(String id, String text, String hint) {
\r
1214 EnCrypt crypt = new EnCrypt();
\r
1215 String plainText = null;
\r
1216 Calendar currentTime = new GregorianCalendar();
\r
1217 Long l = new Long(currentTime.getTimeInMillis());
\r
1218 String slot = new String(Long.toString(l));
\r
1220 // First, try to decrypt with any keys we already have
\r
1221 for (int i=0; i<Global.passwordRemember.size(); i++) {
\r
1222 plainText = crypt.decrypt(text, Global.passwordRemember.get(i), 64);
\r
1223 if (plainText != null) {
\r
1224 slot = new String(Long.toString(l));
\r
1225 Global.passwordSafe.put(slot, Global.passwordRemember.get(i));
\r
1226 removeEncryption(id, plainText, false, slot);
\r
1232 EnDecryptDialog dialog = new EnDecryptDialog();
\r
1233 dialog.setHint(hint);
\r
1234 while (plainText == null || !dialog.okPressed()) {
\r
1236 if (!dialog.okPressed()) {
\r
1239 plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);
\r
1240 if (plainText == null) {
\r
1241 QMessageBox.warning(this, "Incorrect Password", "The password entered is not correct");
\r
1244 Global.passwordSafe.put(slot, dialog.getPassword());
\r
1245 removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);
\r
1246 if (dialog.rememberPassword())
\r
1247 Global.passwordRemember.add(dialog.getPassword());
\r
1251 // Get the editor tag line
\r
1252 public TagLineEdit getTagLine() {
\r
1256 // Modify a note's tags
\r
1257 @SuppressWarnings("unused")
\r
1258 private void modifyTags() {
\r
1259 TagAssign tagWindow = new TagAssign(allTags, currentTags);
\r
1261 if (tagWindow.okClicked()) {
\r
1262 currentTags.clear();
\r
1263 StringBuffer tagDisplay = new StringBuffer();
\r
1265 List<QListWidgetItem> newTags = tagWindow.getTagList()
\r
1267 for (int i = 0; i < newTags.size(); i++) {
\r
1268 currentTags.add(newTags.get(i).text());
\r
1269 tagDisplay.append(newTags.get(i).text());
\r
1270 if (i < newTags.size() - 1) {
\r
1271 tagDisplay.append(Global.tagDelimeter + " ");
\r
1274 tagEdit.setText(tagDisplay.toString());
\r
1275 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1279 // Tag line has been modified by typing text
\r
1280 @SuppressWarnings("unused")
\r
1281 private void modifyTagsTyping() {
\r
1283 String newTags = tagEdit.text();
\r
1284 List<String> test = tagEdit.tagCompleter.getTagList();
\r
1285 if (newTags.equalsIgnoreCase(saveTagList))
\r
1288 // We know something has changed...
\r
1289 String oldTagArray[] = saveTagList.split(Global.tagDelimeter);
\r
1290 String newTagArray[] = newTags.split(Global.tagDelimeter);
\r
1292 List<String> newTagList = new ArrayList<String>();
\r
1293 List<String> oldTagList = new ArrayList<String>();
\r
1295 for (int i = 0; i < oldTagArray.length; i++)
\r
1296 if (!oldTagArray[i].trim().equals(""))
\r
1297 oldTagList.add(oldTagArray[i]);
\r
1298 for (int i = 0; i < newTagArray.length; i++)
\r
1299 if (!newTagArray[i].trim().equals(""))
\r
1300 newTagList.add(newTagArray[i]);
\r
1302 // We now have lists of the new & old. Remove duplicates. If all
\r
1303 // are removed from both then nothing has really changed
\r
1304 for (int i = newTagList.size() - 1; i >= 0; i--) {
\r
1305 String nTag = newTagList.get(i);
\r
1306 for (int j = oldTagList.size() - 1; j >= 0; j--) {
\r
1307 String oTag = oldTagList.get(j);
\r
1308 if (oTag.equalsIgnoreCase(nTag)) {
\r
1309 oldTagList.remove(j);
\r
1310 newTagList.remove(i);
\r
1316 if (oldTagList.size() != 0 || newTagList.size() != 0) {
\r
1317 currentTags.clear();
\r
1318 for (int i = 0; i < newTagArray.length; i++)
\r
1319 if (!newTagArray[i].trim().equals(""))
\r
1320 currentTags.add(newTagArray[i].trim());
\r
1322 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1327 // Tab button was pressed
\r
1328 public void tabPressed() {
\r
1329 if (!insideList) {
\r
1330 String script_start = new String(
\r
1331 "document.execCommand('insertHtml', false, ' ');");
\r
1332 browser.page().mainFrame().evaluateJavaScript(script_start);
\r
1337 public void backtabPressed() {
\r
1342 public void setInsideList() {
\r
1343 insideList = true;
\r
1346 // The title has been edited
\r
1347 @SuppressWarnings("unused")
\r
1348 private void titleEdited() {
\r
1349 // If we don't have a good note, or if the current title
\r
1350 // matches the old title then we don't need to do anything
\r
1351 if (currentNote == null)
\r
1353 if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))
\r
1356 // If we have a real change, we need to save it.
\r
1357 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text());
\r
1358 currentNote.setTitle(titleLabel.text());
\r
1359 saveNoteTitle = titleLabel.text();
\r
1363 // Set the list of note tags
\r
1364 public void setAllTags(List<Tag> l) {
\r
1366 tagEdit.setTagList(l);
\r
1369 // Setter for the current tags
\r
1370 public void setCurrentTags(List<String> s) {
\r
1374 // Save the list of notebooks
\r
1375 public void setNotebookList(List<Notebook> n) {
\r
1377 loadNotebookList();
\r
1380 // Load the notebook list and select the current notebook
\r
1381 private void loadNotebookList() {
\r
1382 if (notebookBox.count() != 0)
\r
1383 notebookBox.clear();
\r
1384 if (notebookList == null)
\r
1387 for (int i = 0; i < notebookList.size(); i++) {
\r
1388 notebookBox.addItem(notebookList.get(i).getName());
\r
1389 if (currentNote != null) {
\r
1390 if (currentNote.getNotebookGuid().equals(
\r
1391 notebookList.get(i).getGuid())) {
\r
1392 notebookBox.setCurrentIndex(i);
\r
1398 // Get the contents of the editor
\r
1399 public String getContent() {
\r
1400 return browser.page().currentFrame().toHtml();
\r
1403 // The note contents have changed
\r
1404 public void contentChanged() {
\r
1405 String content = getContent();
\r
1407 noteSignal.noteChanged.emit(currentNote.getGuid(), content);
\r
1410 // noteSignal.noteChanged.emit(currentNote.getGuid(), unicode);
\r
1413 // The notebook selection has changed
\r
1414 @SuppressWarnings("unused")
\r
1415 private void notebookChanged() {
\r
1416 boolean changed = false;
\r
1417 String n = notebookBox.currentText();
\r
1418 for (int i = 0; i < notebookList.size(); i++) {
\r
1419 if (n.equals(notebookList.get(i).getName())) {
\r
1420 if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {
\r
1421 currentNote.setNotebookGuid(notebookList.get(i).getGuid());
\r
1424 i = notebookList.size();
\r
1428 // If the notebook changed, signal the update
\r
1430 noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote
\r
1431 .getNotebookGuid());
\r
1434 // Check the note title
\r
1435 private void checkNoteTitle() {
\r
1436 String text = browser.page().currentFrame().toPlainText();
\r
1437 if (saveNoteTitle.trim().equals("")) {
\r
1438 int newLine = text.indexOf("\n");
\r
1439 if (newLine > 0) {
\r
1440 text = text.substring(0, newLine);
\r
1441 if (text.trim().equals(""))
\r
1442 text = "Untitled Note";
\r
1443 titleLabel.setText(text);
\r
1445 if (text.length() > 20)
\r
1446 titleLabel.setText(text.substring(0, 20));
\r
1448 if (text.trim().equals(""))
\r
1449 titleLabel.setText("Untitled Note");
\r
1451 titleLabel.setText(text);
\r
1454 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel
\r
1459 // Return the note contents so we can email them
\r
1460 public String getContentsToEmail() {
\r
1461 return browser.page().currentFrame().toPlainText().trim();
\r
1463 * int body = browser.page().currentFrame().toHtml().indexOf("<body>");
\r
1464 * String temp = browser.page().currentFrame().toHtml(); if (body == -1)
\r
1465 * temp = "<html><body><b>Test</b></body></html>"; else temp =
\r
1466 * "<html>"+temp.substring(body); return temp; // return
\r
1467 * urlEncode(browser.page().currentFrame().toHtml());
\r
1471 // Insert an image into the editor
\r
1472 private void insertImage(QMimeData mime) {
\r
1473 logger.log(logger.EXTREME, "Entering insertImage");
\r
1474 QImage img = (QImage) mime.imageData();
\r
1475 String script_start = new String(
\r
1476 "document.execCommand('insertHTML', false, '");
\r
1477 String script_end = new String("');");
\r
1479 long now = new Date().getTime();
\r
1480 String path = Global.getDirectoryPath() + "res/"
\r
1481 + (new Long(now).toString()) + ".jpg";
\r
1483 // This block is just a hack to make sure we wait at least 1ms so we
\r
1485 // have collisions on image names
\r
1486 long i = new Date().getTime();
\r
1488 i = new Date().getTime();
\r
1490 // Open the file & write the data
\r
1491 QFile tfile = new QFile(path);
\r
1492 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1496 Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);
\r
1497 if (newRes == null)
\r
1499 currentNote.getResources().add(newRes);
\r
1501 // do the actual insert into the note
\r
1502 StringBuffer buffer = new StringBuffer(100);
\r
1503 buffer.append("<img src=\"");
\r
1504 buffer.append(tfile.fileName());
\r
1505 buffer.append("\" en-tag=en-media type=\"image/jpeg\""
\r
1506 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1507 +" guid=\"" +newRes.getGuid() +"\""
\r
1508 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1510 browser.page().mainFrame().evaluateJavaScript(
\r
1511 script_start + buffer + script_end);
\r
1516 // Handle URLs that are trying to be pasted
\r
1517 public void handleUrls(QMimeData mime) {
\r
1518 logger.log(logger.EXTREME, "Starting handleUrls");
\r
1519 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1521 List<QUrl> urlList = mime.urls();
\r
1522 String url = new String();
\r
1523 String script_start = new String(
\r
1524 "document.execCommand('createLink', false, '");
\r
1525 String script_end = new String("');");
\r
1527 for (int i = 0; i < urlList.size(); i++) {
\r
1528 url = urlList.get(i).toString();
\r
1529 // Find out what type of file we have
\r
1530 String mimeType = fileNameMap.getContentTypeFor(url);
\r
1532 // If null returned, we need to guess at the file type
\r
1533 if (mimeType == null)
\r
1534 mimeType = "application/"
\r
1535 + url.substring(url.lastIndexOf(".") + 1);
\r
1537 // Check if we have an image or some other type of file
\r
1538 if (url.substring(0, 5).equalsIgnoreCase("file:")
\r
1539 && mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1540 handleLocalImageURLPaste(mime, mimeType);
\r
1543 String[] type = mimeType.split("/");
\r
1544 boolean valid = validAttachment(type[1]);
\r
1545 boolean smallEnough = checkFileAttachmentSize(url);
\r
1546 if (smallEnough && valid
\r
1547 && url.substring(0, 5).equalsIgnoreCase("file:")
\r
1548 && !mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1549 handleLocalAttachment(mime, mimeType);
\r
1552 browser.page().mainFrame().evaluateJavaScript(
\r
1553 script_start + url + script_end);
\r
1558 // If a URL being pasted is an image URL, then attach the image
\r
1559 private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {
\r
1560 List<QUrl> urlList = mime.urls();
\r
1561 String url = new String();
\r
1562 String script_start_image = new String(
\r
1563 "document.execCommand('insertHtml', false, '");
\r
1564 String script_end = new String("');");
\r
1565 StringBuffer buffer;
\r
1567 // Copy the image over into the resource directory and create a new resource
\r
1568 // record for each url pasted
\r
1569 for (int i = 0; i < urlList.size(); i++) {
\r
1570 url = urlList.get(i).toString();
\r
1572 Resource newRes = createResource(url, i, mimeType, false);
\r
1573 if (newRes == null)
\r
1575 currentNote.getResources().add(newRes);
\r
1576 buffer = new StringBuffer(100);
\r
1578 // Open the file & write the data
\r
1579 String fileName = Global.getDirectoryPath()+"res/"+newRes.getGuid();
\r
1580 QFile tfile = new QFile(fileName);
\r
1581 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1582 tfile.write(newRes.getData().getBody());
\r
1584 fileName = fileName.replace('\\', '/');
\r
1585 buffer.append(script_start_image);
\r
1586 buffer.append("<img src=\"" +fileName);
\r
1587 // if (mimeType.equalsIgnoreCase("image/jpg"))
\r
1588 // mimeType = "image/jpeg";
\r
1589 buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""
\r
1590 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1591 +" guid=\"" +newRes.getGuid() +"\""
\r
1592 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1594 buffer.append(script_end);
\r
1595 browser.page().mainFrame().evaluateJavaScript(buffer.toString());
\r
1601 // If a URL being pasted is a local file URL, then attach the file
\r
1602 private void handleLocalAttachment(QMimeData mime, String mimeType) {
\r
1603 logger.log(logger.EXTREME, "Attaching local file");
\r
1604 List<QUrl> urlList = mime.urls();
\r
1605 String script_start = new String(
\r
1606 "document.execCommand('insertHtml', false, '");
\r
1607 String script_end = new String("');");
\r
1608 StringBuffer buffer;
\r
1610 for (int i = 0; i < urlList.size(); i++) {
\r
1611 buffer = new StringBuffer(100);
\r
1612 String url = urlList.get(i).toString();
\r
1614 // Start building the HTML
\r
1615 String[] type = mimeType.split("/");
\r
1616 String icon = findIcon(type[1]);
\r
1617 if (icon.equals("attachment.png"))
\r
1618 icon = findIcon(type[0]);
\r
1619 if (icon.equals("attachment.png"))
\r
1620 icon = findIcon(url.substring(url.lastIndexOf(".")+1));
\r
1621 String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));
\r
1623 logger.log(logger.EXTREME, "Creating resource ");
\r
1624 Resource newRes = createResource(url, i, mimeType, true);
\r
1625 if (newRes == null)
\r
1627 logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());
\r
1628 currentNote.getResources().add(newRes);
\r
1630 String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();
\r
1631 // If we have a PDF, we need to setup the preview.
\r
1632 if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {
\r
1633 logger.log(logger.EXTREME, "Setting up PDF preview");
\r
1634 if (newRes.getAttributes() != null &&
\r
1635 newRes.getAttributes().getFileName() != null &&
\r
1636 !newRes.getAttributes().getFileName().trim().equals(""))
\r
1637 fileName = newRes.getGuid()+Global.attachmentNameDelimeter+
\r
1638 newRes.getAttributes().getFileName();
\r
1640 fileName = newRes.getGuid()+".pdf";
\r
1641 QFile file = new QFile(Global.getDirectoryPath() +"res/"+fileName);
\r
1642 QFile.OpenMode mode = new QFile.OpenMode();
\r
1643 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
1645 QDataStream out = new QDataStream(file);
\r
1646 // Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);
\r
1647 QByteArray binData = new QByteArray(newRes.getData().getBody());
\r
1648 // resBinary = null;
\r
1649 out.writeBytes(binData.toByteArray());
\r
1652 PDFPreview pdfPreview = new PDFPreview();
\r
1653 if (pdfPreview.setupPreview(Global.currentDir+"res/"+fileName, "pdf",0));
\r
1654 imageURL = file.fileName() + ".png";
\r
1657 logger.log(logger.EXTREME, "Generating link tags");
\r
1658 buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");
\r
1659 buffer.append(" onContextMenu=\"window.jambi.imageContextMenu('" +Global.getDirectoryPath() +"res/"+fileName +"');\" ");
\r
1660 buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");
\r
1661 buffer.append("<img src=\"" + imageURL + "\" title=\"" +newRes.getAttributes().getFileName());
\r
1662 buffer.append("\"></img>");
\r
1663 buffer.append("</a>");
\r
1664 browser.page().mainFrame().evaluateJavaScript(
\r
1665 script_start + buffer.toString() + script_end);
\r
1669 private Resource createResource(String url, int sequence, String mime, boolean attachment) {
\r
1670 logger.log(logger.EXTREME, "Inside create resource");
\r
1671 QFile resourceFile;
\r
1672 url = new QUrl(url).toLocalFile();
\r
1673 url = url.replace("/", File.separator);
\r
1674 resourceFile = new QFile(url);
\r
1675 resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));
\r
1676 byte[] fileData = resourceFile.readAll().toByteArray();
\r
1677 resourceFile.close();
\r
1678 if (fileData.length == 0)
\r
1682 md = MessageDigest.getInstance("MD5");
\r
1683 md.update(fileData);
\r
1684 byte[] hash = md.digest();
\r
1686 Resource r = new Resource();
\r
1687 Calendar time = new GregorianCalendar();
\r
1688 long prevTime = time.getTimeInMillis();
\r
1689 while (prevTime == time.getTimeInMillis()) {
\r
1690 time = new GregorianCalendar();
\r
1692 r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());
\r
1693 r.setNoteGuid(currentNote.getGuid());
\r
1695 r.setActive(true);
\r
1696 r.setUpdateSequenceNum(0);
\r
1697 r.setWidth((short) 0);
\r
1698 r.setHeight((short) 0);
\r
1699 r.setDuration((short) 0);
\r
1701 Data d = new Data();
\r
1702 d.setBody(fileData);
\r
1703 d.setBodyIsSet(true);
\r
1704 d.setBodyHash(hash);
\r
1705 d.setBodyHashIsSet(true);
\r
1707 d.setSize(fileData.length);
\r
1709 int fileNamePos = url.lastIndexOf(File.separator);
\r
1710 if (fileNamePos == -1)
\r
1711 fileNamePos = url.lastIndexOf("/");
\r
1712 String fileName = url.substring(fileNamePos+1);
\r
1713 ResourceAttributes a = new ResourceAttributes();
\r
1715 a.setAltitudeIsSet(false);
\r
1716 a.setLongitude(0);
\r
1717 a.setLongitudeIsSet(false);
\r
1719 a.setLatitudeIsSet(false);
\r
1720 a.setCameraMake("");
\r
1721 a.setCameraMakeIsSet(false);
\r
1722 a.setCameraModel("");
\r
1723 a.setCameraModelIsSet(false);
\r
1724 a.setAttachment(attachment);
\r
1725 a.setAttachmentIsSet(true);
\r
1726 a.setClientWillIndex(false);
\r
1727 a.setClientWillIndexIsSet(true);
\r
1728 a.setRecoType("");
\r
1729 a.setRecoTypeIsSet(false);
\r
1730 a.setSourceURL(url);
\r
1731 a.setSourceURLIsSet(true);
\r
1732 a.setTimestamp(0);
\r
1733 a.setTimestampIsSet(false);
\r
1734 a.setFileName(fileName);
\r
1735 a.setFileNameIsSet(true);
\r
1736 r.setAttributes(a);
\r
1738 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
1740 } catch (NoSuchAlgorithmException e1) {
\r
1741 e1.printStackTrace();
\r
1747 // find the appropriate icon for an attachment
\r
1748 private String findIcon(String appl) {
\r
1749 appl = appl.toLowerCase();
\r
1750 File f = Global.getFileManager().getImageDirFile(appl + ".png");
\r
1752 return appl+".png";
\r
1753 return "attachment.png";
\r
1756 // Check if the account supports this type of attachment
\r
1757 private boolean validAttachment(String type) {
\r
1758 if (Global.isPremium())
\r
1760 if (type.equalsIgnoreCase("JPG"))
\r
1762 if (type.equalsIgnoreCase("PNG"))
\r
1764 if (type.equalsIgnoreCase("GIF"))
\r
1766 if (type.equalsIgnoreCase("MP3"))
\r
1768 if (type.equalsIgnoreCase("WAV"))
\r
1770 if (type.equalsIgnoreCase("AMR"))
\r
1772 if (type.equalsIgnoreCase("PDF"))
\r
1774 String error = "Non-premium accounts can only attach JPG, PNG, GIF, MP3, WAV, AMR, or PDF files.";
\r
1775 QMessageBox.information(this, "Non-Premium Account", error);
\r
1780 // Check the file attachment to be sure it isn't over 25 mb
\r
1781 private boolean checkFileAttachmentSize(String url) {
\r
1782 String fileName = url.substring(8);
\r
1783 QFile resourceFile = new QFile(fileName);
\r
1784 resourceFile.open(new QIODevice.OpenMode(
\r
1785 QIODevice.OpenModeFlag.ReadOnly));
\r
1786 long size = resourceFile.size();
\r
1787 resourceFile.close();
\r
1788 size = size / 1024 / 1024;
\r
1789 if (size < 50 && Global.isPremium())
\r
1794 String error = "A file attachment may not exceed 25MB.";
\r
1795 QMessageBox.information(this, "Attachment Size", error);
\r
1800 @SuppressWarnings("unused")
\r
1801 private void createdChanged() {
\r
1802 QDateTime dt = new QDateTime();
\r
1803 dt.setDate(createdDate.date());
\r
1804 dt.setTime(createdTime.time());
\r
1805 noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);
\r
1809 @SuppressWarnings("unused")
\r
1810 private void alteredChanged() {
\r
1811 QDateTime dt = new QDateTime();
\r
1812 dt.setDate(alteredDate.date());
\r
1813 dt.setTime(alteredTime.time());
\r
1814 noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);
\r
1817 @SuppressWarnings("unused")
\r
1818 private void subjectDateTimeChanged() {
\r
1819 QDateTime dt = new QDateTime();
\r
1820 dt.setDate(subjectDate.date());
\r
1821 dt.setTime(subjectTime.time());
\r
1822 noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);
\r
1826 @SuppressWarnings("unused")
\r
1827 private void sourceUrlChanged() {
\r
1828 noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());
\r
1831 @SuppressWarnings("unused")
\r
1832 private void authorChanged() {
\r
1833 noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());
\r
1836 // ************************************************************
\r
1837 // * User chose to save an attachment. Pares out the request *
\r
1838 // * into a guid & file. Save the result. *
\r
1839 // ************************************************************
\r
1840 public void downloadAttachment(QNetworkRequest request) {
\r
1842 QFileDialog fd = new QFileDialog(this);
\r
1843 fd.setFileMode(FileMode.AnyFile);
\r
1844 fd.setConfirmOverwrite(true);
\r
1845 fd.setWindowTitle("Save File");
\r
1846 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
1847 fd.setDirectory(System.getProperty("user.home"));
\r
1848 String name = request.url().toString();
\r
1850 int pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
1852 guid = name.substring(0, pos).replace("nnres://", "");
\r
1853 name = name.substring(pos +Global.attachmentNameDelimeter.length());
\r
1854 fd.selectFile(name);
\r
1855 pos = name.lastIndexOf('.');
\r
1857 String mimeType = "(*." + name.substring(pos + 1)
\r
1858 + ");; All Files (*)";
\r
1859 fd.setFilter(tr(mimeType));
\r
1864 guid = guid.replace("nnres://", "").replace(Global.currentDir.replace("\\","/")+"res/", "");
\r
1865 pos = guid.lastIndexOf('.');
\r
1867 guid = guid.substring(0,pos);
\r
1868 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
1869 name = name.replace('\\', '/');
\r
1870 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
1871 QFile saveFile = new QFile(fd.selectedFiles().get(0));
\r
1872 QFile.OpenMode mode = new QFile.OpenMode();
\r
1873 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
1874 saveFile.open(mode);
\r
1875 QDataStream saveOut = new QDataStream(saveFile);
\r
1876 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
1877 saveOut.writeBytes(binData.toByteArray());
\r
1884 // ************************************************************
\r
1885 // * User chose to save an attachment. Pares out the request *
\r
1886 // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!
\r
1887 // ************************************************************
\r
1888 public void downloadImage(QNetworkRequest request) {
\r
1889 QFileDialog fd = new QFileDialog(this);
\r
1890 fd.setFileMode(FileMode.AnyFile);
\r
1891 fd.setConfirmOverwrite(true);
\r
1892 fd.setWindowTitle("Save File");
\r
1893 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
1894 fd.setDirectory(System.getProperty("user.home"));
\r
1895 String name = request.url().toString();
\r
1896 name = name.replace("nnres://", "");
\r
1897 String dPath = Global.getDirectoryPath() + "res/";
\r
1898 dPath = dPath.replace('\\', '/');
\r
1899 name = name.replace(dPath, "");
\r
1900 int pos = name.lastIndexOf('.');
\r
1901 String guid = name;
\r
1903 String mimeType = "(*." + name.substring(pos + 1)
\r
1904 + ");; All Files (*)";
\r
1905 fd.setFilter(tr(mimeType));
\r
1906 guid = guid.substring(0,pos);
\r
1908 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
1910 guid = name.substring(0, pos);
\r
1911 fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));
\r
1913 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
1914 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
1915 String fileName = fd.selectedFiles().get(0);
\r
1916 QFile saveFile = new QFile(fileName);
\r
1917 QFile.OpenMode mode = new QFile.OpenMode();
\r
1918 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
1919 saveFile.open(mode);
\r
1920 QDataStream saveOut = new QDataStream(saveFile);
\r
1921 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
1922 saveOut.writeBytes(binData.toByteArray());
\r
1928 // *************************************************************
\r
1929 // * decrypt any hidden text. We could do an XML parse, but
\r
1930 // * it is quicker here just to scan for an <img tag & do the fix
\r
1931 // * the manual way
\r
1932 // *************************************************************
\r
1933 private void removeEncryption(String id, String plainText, boolean permanent, String slot) {
\r
1935 plainText = " <en-crypt-temp slot=\""+slot +"\">" +plainText+"</en-crypt-temp> ";
\r
1938 String html = browser.page().mainFrame().toHtml();
\r
1939 String text = html;
\r
1940 int imagePos = html.indexOf("<img");
\r
1942 for ( ;imagePos>0; ) {
\r
1943 // Find the end tag
\r
1944 endPos = text.indexOf(">", imagePos);
\r
1945 String tag = text.substring(imagePos-1,endPos);
\r
1946 if (tag.indexOf("id=\""+id+"\"") > -1) {
\r
1947 text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);
\r
1949 browser.setContent(new QByteArray(text));
\r
1952 imagePos = text.indexOf("<img", imagePos+1);
\r
1957 //****************************************************************
\r
1958 //* Focus shortcuts
\r
1959 //****************************************************************
\r
1960 @SuppressWarnings("unused")
\r
1961 private void focusTitle() {
\r
1962 titleLabel.setFocus();
\r
1964 @SuppressWarnings("unused")
\r
1965 private void focusTag() {
\r
1966 tagEdit.setFocus();
\r
1968 @SuppressWarnings("unused")
\r
1969 private void focusNote() {
\r
1970 browser.setFocus();
\r
1972 @SuppressWarnings("unused")
\r
1973 private void focusAuthor() {
\r
1974 authorLabel.setFocus();
\r
1976 @SuppressWarnings("unused")
\r
1977 private void focusUrl() {
\r
1978 urlLabel.setFocus();
\r
1982 //*****************************************************************
\r
1983 //* Set the document background color
\r
1984 //*****************************************************************
\r
1985 public void setBackgroundColor(String color) {
\r
1986 String js = "function changeBackground(color) {"
\r
1987 +"document.body.style.background = color;"
\r
1989 +"changeBackground('" +color+"');";
\r
1990 browser.page().mainFrame().evaluateJavaScript(js);
\r
1995 //****************************************************************
\r
1996 //* MicroFocus changed
\r
1997 //****************************************************************
\r
1998 private void microFocusChanged() {
\r
2000 boldButton.setDown(false);
\r
2001 italicButton.setDown(false);
\r
2002 underlineButton.setDown(false);
\r
2003 browser.openAction.setEnabled(false);
\r
2004 browser.downloadAttachment.setEnabled(false);
\r
2005 browser.downloadImage.setEnabled(false);
\r
2006 browser.rotateImageLeft.setEnabled(false);
\r
2007 browser.rotateImageRight.setEnabled(false);
\r
2008 browser.insertTableAction.setEnabled(true);
\r
2009 browser.insertTableRowAction.setEnabled(false);
\r
2010 browser.deleteTableRowAction.setEnabled(false);
\r
2011 browser.insertLinkAction.setText("Insert Hyperlink");
\r
2012 currentHyperlink ="";
\r
2013 insideList = false;
\r
2014 forceTextPaste = false;
\r
2016 String js = new String( "function getCursorPos() {"
\r
2018 +"if (window.getSelection) {"
\r
2019 +" var selObj = window.getSelection();"
\r
2020 +" var selRange = selObj.getRangeAt(0);"
\r
2021 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2022 +" while(workingNode != null) { "
\r
2023 // +" window.jambi.printNode(workingNode.nodeName);"
\r
2024 +" if (workingNode.nodeName=='EN-CRYPT-TEMP') window.jambi.forceTextPaste();"
\r
2025 +" if (workingNode.nodeName=='B') window.jambi.boldActive();"
\r
2026 +" if (workingNode.nodeName=='I') window.jambi.italicActive();"
\r
2027 +" if (workingNode.nodeName=='U') window.jambi.underlineActive();"
\r
2028 +" if (workingNode.nodeName=='UL') window.jambi.setInsideList();"
\r
2029 +" if (workingNode.nodeName=='OL') window.jambi.setInsideList();"
\r
2030 +" if (workingNode.nodeName=='LI') window.jambi.setInsideList();"
\r
2031 +" if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"
\r
2032 +" 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
2033 +" if (workingNode.nodeName=='SPAN') {"
\r
2034 +" if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"
\r
2036 +" workingNode = workingNode.parentNode;"
\r
2039 +"} getCursorPos();");
\r
2040 browser.page().mainFrame().evaluateJavaScript(js);
\r
2043 public void printNode(String n) {
\r
2044 System.out.println("Node Vaule: " +n);
\r
2048 //****************************************************************
\r
2049 //* Insert a table row
\r
2050 //****************************************************************
\r
2051 public void insertTableRow() {
\r
2053 String js = new String( "function insertTableRow() {"
\r
2054 +" var selObj = window.getSelection();"
\r
2055 +" var selRange = selObj.getRangeAt(0);"
\r
2056 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2057 +" var cellCount = 0;"
\r
2058 +" while(workingNode != null) { "
\r
2059 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2060 +" row = document.createElement('TR');"
\r
2061 +" var nodes = workingNode.getElementsByTagName('td');"
\r
2062 +" for (j=0; j<nodes.length; j=j+1) {"
\r
2063 +" cell = document.createElement('TD');"
\r
2064 +" cell.innerHTML=' ';"
\r
2065 +" row.appendChild(cell);"
\r
2067 +" workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"
\r
2070 +" workingNode = workingNode.parentNode;"
\r
2072 +"} insertTableRow();");
\r
2073 browser.page().mainFrame().evaluateJavaScript(js);
\r
2076 //****************************************************************
\r
2077 //* Insert a table row
\r
2078 //****************************************************************
\r
2079 public void deleteTableRow() {
\r
2081 String js = new String( "function deleteTableRow() {"
\r
2082 +" var selObj = window.getSelection();"
\r
2083 +" var selRange = selObj.getRangeAt(0);"
\r
2084 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2085 +" var cellCount = 0;"
\r
2086 +" while(workingNode != null) { "
\r
2087 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2088 +" workingNode.parentNode.removeChild(workingNode);"
\r
2091 +" workingNode = workingNode.parentNode;"
\r
2093 +"} deleteTableRow();");
\r
2094 browser.page().mainFrame().evaluateJavaScript(js);
\r
2097 public void setInsideTable() {
\r
2098 browser.insertTableRowAction.setEnabled(true);
\r
2099 browser.deleteTableRowAction.setEnabled(true);
\r
2100 browser.insertTableAction.setEnabled(false);
\r
2101 browser.encryptAction.setEnabled(false);
\r
2104 public void setInsideLink(String link) {
\r
2105 browser.insertLinkAction.setText("Edit Hyperlink");
\r
2106 currentHyperlink = link;
\r
2109 public void italicActive() {
\r
2110 italicButton.setDown(true);
\r
2112 public void boldActive() {
\r
2113 boldButton.setDown(true);
\r
2115 public void underlineActive() {
\r
2116 underlineButton.setDown(true);
\r
2118 public void forceTextPaste() {
\r
2119 forceTextPaste = true;
\r
2121 public void imageContextMenu(String f) {
\r
2122 browser.downloadImage.setEnabled(true);
\r
2123 browser.rotateImageRight.setEnabled(true);
\r
2124 browser.rotateImageLeft.setEnabled(true);
\r
2125 browser.openAction.setEnabled(true);
\r
2128 public void rotateImageRight() {
\r
2129 QWebSettings.setMaximumPagesInCache(0);
\r
2130 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2131 QImage image = new QImage(selectedFile);
\r
2132 QMatrix matrix = new QMatrix();
\r
2133 matrix.rotate( 90.0 );
\r
2134 image = image.transformed(matrix);
\r
2135 image.save(selectedFile);
\r
2136 QWebSettings.setMaximumPagesInCache(0);
\r
2137 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2138 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2141 // resourceSignal.contentChanged.emit(selectedFile);
\r
2144 public void rotateImageLeft() {
\r
2145 QImage image = new QImage(selectedFile);
\r
2146 QMatrix matrix = new QMatrix();
\r
2147 matrix.rotate( -90.0 );
\r
2148 image = image.transformed(matrix);
\r
2149 image.save(selectedFile);
\r
2150 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2153 // resourceSignal.contentChanged.emit(selectedFile);
\r
2155 public void resourceContextMenu(String f) {
\r
2156 browser.downloadAttachment.setEnabled(true);
\r
2157 browser.openAction.setEnabled(true);
\r
2162 //****************************************************************
\r
2163 //* Apply CSS style to specified word
\r
2164 //****************************************************************
\r
2165 /* public void applyStyleToWords(String word, String style) {
\r
2166 QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");
\r
2167 script.open(OpenModeFlag.ReadOnly);
\r
2168 String s = script.readAll().toString();
\r
2169 String js = new String(s +" findit('"+word+"', '"+style+"');");
\r
2170 browser.page().mainFrame().evaluateJavaScript(js);
\r
2171 System.out.println(getContent());
\r
2174 //****************************************************************
\r
2175 //* Someone tried to paste a resource between notes, so we need *
\r
2176 //* to do some special handling. *
\r
2177 //****************************************************************
\r
2178 private String fixInternotePaste(String text) {
\r
2179 logger.log(logger.EXTREME, "Fixing internote paste");
\r
2180 String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");
\r
2181 return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");
\r
2183 private String fixInternotePasteSearch(String text, String type, String locTag) {
\r
2185 // First, let's fix the images.
\r
2186 int startPos = text.indexOf(type);
\r
2188 for (; startPos>=0;) {
\r
2189 endPos = text.indexOf(">", startPos+1);
\r
2190 String segment = text.substring(startPos, endPos);
\r
2191 if (segment.indexOf("en-tag") > -1) {
\r
2192 String newSegment = segment;
\r
2194 int guidStartPos = segment.indexOf("guid=\"");
\r
2195 int guidEndPos = segment.indexOf("\"", guidStartPos+7);
\r
2196 String guid = segment.substring(guidStartPos+6,guidEndPos);
\r
2198 Calendar currentTime = new GregorianCalendar();
\r
2199 Long l = new Long(currentTime.getTimeInMillis());
\r
2200 long prevTime = l;
\r
2201 while (l==prevTime) {
\r
2202 currentTime = new GregorianCalendar();
\r
2203 l= new Long(currentTime.getTimeInMillis());
\r
2206 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2209 String randint = new String(Long.toString(l));
\r
2210 String extension = null;
\r
2211 if (r.getMime()!= null) {
\r
2212 extension = r.getMime().toLowerCase();
\r
2213 if (extension.indexOf("/")>-1)
\r
2214 extension = extension.substring(extension.indexOf("/")+1);
\r
2216 String newFile = randint;
\r
2217 if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")
\r
2218 if (!locTag.startsWith("src"))
\r
2219 newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();
\r
2220 r.setNoteGuid(currentNote.getGuid());
\r
2222 r.setGuid(randint);
\r
2223 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
2224 QFile f = new QFile(Global.getDirectoryPath() +"res/" +newFile);
\r
2225 QByteArray bin = new QByteArray(r.getData().getBody());
\r
2226 f.open(QFile.OpenModeFlag.WriteOnly);
\r
2229 newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);
\r
2230 currentNote.getResources().add(r);
\r
2232 int startSrcPos = newSegment.indexOf(locTag);
\r
2233 int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);
\r
2235 if (locTag.startsWith("src")) {
\r
2236 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2237 newSegment = newSegment.replace(source, Global.getDirectoryPath().replace("\\", "/")+"res/"+newFile);
\r
2239 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2240 newSegment = newSegment.replace(source, newFile);
\r
2243 text = text.substring(0,startPos) + newSegment + text.substring(endPos);
\r
2245 startPos = text.indexOf(type, startPos+1);
\r
2251 public void nextPage(String file) {
\r
2252 logger.log(logger.EXTREME, "Starting nextPage()");
\r
2254 Integer pageNumber;
\r
2255 if (previewPageList.containsKey(file))
\r
2256 pageNumber = previewPageList.get(file)+1;
\r
2259 previewPageList.remove(file);
\r
2260 previewPageList.put(file, pageNumber);
\r
2261 PDFPreview pdfPreview = new PDFPreview();
\r
2262 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2263 if (goodPreview) {
\r
2265 // String html = getContent();
\r
2266 QWebSettings.setMaximumPagesInCache(0);
\r
2267 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2268 // browser.setContent(new QByteArray());
\r
2269 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2271 // browser.setContent(new QByteArray(html));
\r
2272 // browser.triggerPageAction(WebAction.Reload);
\r
2273 // pdfMouseOver(selectedFile);
\r
2277 public void previousPage(String file) {
\r
2278 logger.log(logger.EXTREME, "Starting previousPage()");
\r
2280 Integer pageNumber;
\r
2281 if (previewPageList.containsKey(file))
\r
2282 pageNumber = previewPageList.get(file)-1;
\r
2285 previewPageList.remove(file);
\r
2286 previewPageList.put(file, pageNumber);
\r
2287 PDFPreview pdfPreview = new PDFPreview();
\r
2288 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2289 if (goodPreview) {
\r
2291 // String html = getContent();
\r
2292 QWebSettings.setMaximumPagesInCache(0);
\r
2293 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2294 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2296 // browser.setContent(new QByteArray(html));
\r
2297 // browser.triggerPageAction(WebAction.Reload);
\r
2301 /* public void pdfMouseOver(String name) {
\r
2303 if (previewPageList.containsKey(selectedFile))
\r
2304 pageNumber = previewPageList.get(selectedFile)+1;
\r
2308 if (pageNumber <= 1)
\r
2309 browser.previousPageAction.setEnabled(false);
\r
2311 browser.previousPageAction.setEnabled(true);
\r
2313 PDFPreview pdf = new PDFPreview();
\r
2314 int totalPages = pdf.getPageCount(name);
\r
2315 if (previewPageList.containsKey(selectedFile))
\r
2316 pageNumber = previewPageList.get(selectedFile)+1;
\r
2319 if (totalPages > pageNumber)
\r
2320 browser.nextPageAction.setEnabled(true);
\r
2322 browser.nextPageAction.setEnabled(false);
\r
2326 public void pdfMouseOut() {
\r
2327 // browser.nextPageAction.setVisible(false);
\r
2328 // browser.previousPageAction.setVisible(false);
\r