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
97 public class BrowserWindow extends QWidget {
\r
99 public final QLineEdit titleLabel;
\r
100 private final QLineEdit urlText;
\r
101 private final QLabel authorLabel;
\r
102 private final QLineEdit authorText;
\r
103 public final TagLineEdit tagEdit;
\r
104 public final QLabel tagLabel;
\r
105 private final QLabel urlLabel;
\r
106 private final QLabel alteredLabel;
\r
107 private final QDateEdit alteredDate;
\r
108 private final QTimeEdit alteredTime;
\r
109 private final QDateEdit createdDate;
\r
110 private final QTimeEdit createdTime;
\r
111 private final QLabel subjectLabel;
\r
112 private final QDateEdit subjectDate;
\r
113 private final QTimeEdit subjectTime;
\r
114 public final QComboBox notebookBox;
\r
115 private final QLabel notebookLabel;
\r
116 private final QLabel createdLabel;
\r
117 public final QComboBox fontSize;
\r
118 private boolean extendedOn;
\r
119 public boolean buttonsVisible;
\r
120 private final String iconPath = new String("classpath:cx/fbn/nevernote/icons/");
\r
121 private final ContentView browser;
\r
122 private List<Tag> allTags;
\r
123 private List<String> currentTags;
\r
124 public NoteSignal noteSignal;
\r
125 private List<Notebook> notebookList;
\r
126 private Note currentNote;
\r
127 private String saveNoteTitle;
\r
128 private String saveTagList;
\r
129 private boolean insideList;
\r
130 // private String selectedText;
\r
131 private final DatabaseConnection conn;
\r
132 private final QCalendarWidget createdCalendarWidget;
\r
133 private final QCalendarWidget alteredCalendarWidget;
\r
134 private final QCalendarWidget subjectCalendarWidget;
\r
136 public final QPushButton undoButton;
\r
137 public final QPushButton redoButton;
\r
138 public final QPushButton cutButton;
\r
139 public final QPushButton copyButton;
\r
140 public final QPushButton pasteButton;
\r
141 public final QPushButton boldButton;
\r
142 public final QPushButton underlineButton;
\r
143 public final QPushButton italicButton;
\r
144 public final Signal0 focusLost;
\r
145 public final NoteResourceSignal resourceSignal;
\r
147 public QPushButton rightAlignButton;
\r
148 public QPushButton leftAlignButton;
\r
149 public QPushButton centerAlignButton;
\r
151 public final QPushButton strikethroughButton;
\r
152 public final QPushButton hlineButton;
\r
153 public final QPushButton indentButton;
\r
154 public final QPushButton outdentButton;
\r
155 public final QPushButton bulletListButton;
\r
156 public final QPushButton numberListButton;
\r
158 public final QShortcut focusTitleShortcut;
\r
159 public final QShortcut focusTagShortcut;
\r
160 public final QShortcut focusNoteShortcut;
\r
161 public final QShortcut focusUrlShortcut;
\r
162 public final QShortcut focusAuthorShortcut;
\r
164 public final QComboBox fontList;
\r
165 public final QPushButton fontColor;
\r
166 private final ColorMenu fontColorMenu;
\r
167 public final QPushButton fontHilight;
\r
168 // public final ColorComboBox fontHilight;
\r
169 private final ColorMenu fontHilightColorMenu;
\r
170 public final QFileSystemWatcher fileWatcher;
\r
171 public int cursorPosition;
\r
172 private boolean forceTextPaste = false;
\r
173 private String selectedFile;
\r
174 private String currentHyperlink;
\r
175 public boolean keepPDFNavigationHidden;
\r
176 private final ApplicationLogger logger;
\r
178 private final HashMap<String,Integer> previewPageList;
\r
181 public BrowserWindow(DatabaseConnection c) {
\r
182 logger = new ApplicationLogger("browser.log");
\r
183 logger.log(logger.HIGH, "Setting up browser");
\r
185 fileWatcher = new QFileSystemWatcher();
\r
186 // fileWatcher.fileChanged.connect(this, "fileChanged(String)");
\r
187 noteSignal = new NoteSignal();
\r
188 titleLabel = new QLineEdit();
\r
189 titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX);
\r
190 urlText = new QLineEdit();
\r
191 authorText = new QLineEdit();
\r
192 urlLabel = new QLabel();
\r
193 authorLabel = new QLabel();
\r
196 focusLost = new Signal0();
\r
198 tagEdit = new TagLineEdit(allTags);
\r
199 tagLabel = new QLabel("Tags:");
\r
200 tagEdit.focusLost.connect(this, "modifyTagsTyping()");
\r
202 createdCalendarWidget = new QCalendarWidget();
\r
203 createdDate = new QDateEdit();
\r
204 createdDate.setDisplayFormat(Global.getDateFormat());
\r
205 createdDate.setCalendarPopup(true);
\r
206 createdDate.setCalendarWidget(createdCalendarWidget);
\r
207 createdTime = new QTimeEdit();
\r
208 createdDate.dateChanged.connect(this, "createdChanged()");
\r
209 createdTime.timeChanged.connect(this, "createdChanged()");
\r
211 alteredCalendarWidget = new QCalendarWidget();
\r
212 alteredDate = new QDateEdit();
\r
213 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
214 alteredDate.setCalendarPopup(true);
\r
215 alteredDate.setCalendarWidget(alteredCalendarWidget);
\r
216 alteredTime = new QTimeEdit();
\r
217 alteredLabel = new QLabel("Altered:");
\r
218 alteredDate.dateChanged.connect(this, "alteredChanged()");
\r
219 alteredTime.timeChanged.connect(this, "alteredChanged()");
\r
221 subjectCalendarWidget = new QCalendarWidget();
\r
222 subjectDate = new QDateEdit();
\r
223 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
224 subjectDate.setCalendarPopup(true);
\r
225 subjectDate.setCalendarWidget(subjectCalendarWidget);
\r
226 subjectTime = new QTimeEdit();
\r
227 subjectLabel = new QLabel("Subject Date:");
\r
228 subjectDate.dateChanged.connect(this, "subjectDateTimeChanged()");
\r
229 subjectTime.timeChanged.connect(this, "subjectDateTimeChanged()");
\r
230 authorText.textChanged.connect(this, "authorChanged()");
\r
231 urlText.textChanged.connect(this, "sourceUrlChanged()");
\r
233 notebookBox = new QComboBox();
\r
234 notebookLabel = new QLabel("Notebook");
\r
235 createdLabel = new QLabel("Created:");
\r
236 // selectedText = new String();
\r
238 urlLabel.setVisible(false);
\r
239 urlText.setVisible(false);
\r
240 authorLabel.setVisible(false);
\r
241 authorText.setVisible(false);
\r
242 createdDate.setVisible(false);
\r
243 alteredLabel.setVisible(false);
\r
244 //notebookBox.setVisible(false);
\r
245 notebookLabel.setVisible(false);
\r
246 createdLabel.setVisible(false);
\r
247 createdTime.setVisible(false);
\r
248 alteredDate.setVisible(false);
\r
249 alteredTime.setVisible(false);
\r
250 subjectLabel.setVisible(false);
\r
251 subjectDate.setVisible(false);
\r
252 subjectTime.setVisible(false);
\r
253 extendedOn = false;
\r
254 buttonsVisible = true;
\r
255 setAcceptDrops(true);
\r
257 browser = new ContentView(this);
\r
258 browser.page().setLinkDelegationPolicy(
\r
259 QWebPage.LinkDelegationPolicy.DelegateAllLinks);
\r
260 browser.linkClicked.connect(this, "linkClicked(QUrl)");
\r
261 currentHyperlink = "";
\r
263 QVBoxLayout v = new QVBoxLayout();
\r
264 QFormLayout notebookLayout = new QFormLayout();
\r
265 QGridLayout dateLayout = new QGridLayout();
\r
266 titleLabel.setReadOnly(false);
\r
267 titleLabel.editingFinished.connect(this, "titleEdited()");
\r
268 browser.page().contentsChanged.connect(this, "contentChanged()");
\r
269 browser.page().selectionChanged.connect(this, "selectionChanged()");
\r
270 browser.page().mainFrame().javaScriptWindowObjectCleared.connect(this,
\r
271 "exposeToJavascript()");
\r
273 notebookBox.activated.connect(this, "notebookChanged()");
\r
274 resourceSignal = new NoteResourceSignal();
\r
276 QHBoxLayout tagLayout = new QHBoxLayout();
\r
277 v.addWidget(titleLabel, 0);
\r
278 notebookLayout.addRow(notebookLabel, notebookBox);
\r
279 tagLayout.addLayout(notebookLayout, 0);
\r
280 tagLayout.stretch(4);
\r
281 tagLayout.addWidget(tagLabel, 0);
\r
282 tagLayout.addWidget(tagEdit, 1);
\r
283 v.addLayout(tagLayout);
\r
285 QHBoxLayout urlLayout = new QHBoxLayout();
\r
286 urlLayout.addWidget(urlLabel, 0);
\r
287 urlLayout.addWidget(urlText, 0);
\r
288 v.addLayout(urlLayout);
\r
290 QHBoxLayout authorLayout = new QHBoxLayout();
\r
291 authorLayout.addWidget(authorLabel, 0);
\r
292 authorLayout.addWidget(authorText, 0);
\r
293 v.addLayout(authorLayout);
\r
295 dateLayout.addWidget(createdLabel, 0, 0);
\r
296 dateLayout.addWidget(createdDate, 0, 1);
\r
297 dateLayout.addWidget(createdTime, 0, 2);
\r
298 dateLayout.setColumnStretch(9, 100);
\r
299 dateLayout.addWidget(alteredLabel, 0, 3);
\r
300 dateLayout.addWidget(alteredDate, 0, 4);
\r
301 dateLayout.addWidget(alteredTime, 0, 5);
\r
302 dateLayout.addWidget(subjectLabel, 0, 6);
\r
303 dateLayout.addWidget(subjectDate, 0, 7);
\r
304 dateLayout.addWidget(subjectTime, 0, 8);
\r
305 v.addLayout(dateLayout, 0);
\r
307 undoButton = newEditorButton("undo", "Undo Change");
\r
308 redoButton = newEditorButton("redo", "Redo Change");
\r
309 cutButton = newEditorButton("cut", "Cut");
\r
310 copyButton = newEditorButton("copy", "Copy");
\r
311 pasteButton = newEditorButton("paste", "Paste");
\r
312 boldButton = newEditorButton("bold", "Bold");
\r
313 underlineButton = newEditorButton("underline", "Underline");
\r
314 italicButton = newEditorButton("italic", "Italic");
\r
316 rightAlignButton = newEditorButton("justifyRight", "Right Align");
\r
317 leftAlignButton = newEditorButton("justifyLeft", "Left Align");
\r
318 centerAlignButton = newEditorButton("justifyCenter", "Center Align");
\r
320 strikethroughButton = newEditorButton("strikethrough", "Strikethrough");
\r
321 hlineButton = newEditorButton("hline", "Insert Horizontal Line");
\r
322 indentButton = newEditorButton("indent", "Shift Right");
\r
323 outdentButton = newEditorButton("outdent", "Shift Left");
\r
324 bulletListButton = newEditorButton("bulletList", "Bullet List");
\r
325 numberListButton = newEditorButton("numberList", "Number List");
\r
328 QHBoxLayout buttonLayout;
\r
329 buttonLayout = new QHBoxLayout();
\r
330 buttonLayout.setSpacing(0);
\r
331 v.addLayout(buttonLayout);
\r
333 buttonLayout.addWidget(undoButton);
\r
334 buttonLayout.addWidget(redoButton);
\r
336 buttonLayout.addWidget(newSeparator(), 0);
\r
337 buttonLayout.addWidget(cutButton);
\r
338 buttonLayout.addWidget(copyButton);
\r
339 buttonLayout.addWidget(pasteButton);
\r
341 buttonLayout.addWidget(newSeparator(), 0);
\r
342 buttonLayout.addWidget(boldButton);
\r
343 buttonLayout.addWidget(italicButton);
\r
344 buttonLayout.addWidget(underlineButton);
\r
345 buttonLayout.addWidget(strikethroughButton);
\r
347 buttonLayout.addWidget(newSeparator(), 0);
\r
348 buttonLayout.addWidget(leftAlignButton);
\r
349 buttonLayout.addWidget(centerAlignButton);
\r
350 buttonLayout.addWidget(rightAlignButton);
\r
352 buttonLayout.addWidget(newSeparator(), 0);
\r
353 buttonLayout.addWidget(hlineButton);
\r
355 buttonLayout.addWidget(indentButton);
\r
356 buttonLayout.addWidget(outdentButton);
\r
357 buttonLayout.addWidget(bulletListButton);
\r
358 buttonLayout.addWidget(numberListButton);
\r
360 // Setup the font & font size combo boxes
\r
361 buttonLayout.addWidget(newSeparator(), 0);
\r
362 fontList = new QComboBox();
\r
363 fontSize = new QComboBox();
\r
364 fontList.setToolTip("Font");
\r
365 fontSize.setToolTip("Font Size");
\r
366 fontList.activated.connect(this, "fontChanged(String)");
\r
367 fontSize.activated.connect(this, "fontSizeChanged(String)");
\r
368 buttonLayout.addWidget(fontList, 0);
\r
369 buttonLayout.addWidget(fontSize, 0);
\r
370 QFontDatabase fonts = new QFontDatabase();
\r
371 List<String> fontFamilies = fonts.families();
\r
372 for (int i = 0; i < fontFamilies.size(); i++) {
\r
373 fontList.addItem(fontFamilies.get(i));
\r
375 loadFontSize(fontFamilies.get(i));
\r
379 buttonLayout.addWidget(newSeparator(), 0);
\r
380 fontColor = newEditorButton("fontColor", "Font Color");
\r
381 fontColorMenu = new ColorMenu(this);
\r
382 fontColor.setMenu(fontColorMenu.getMenu());
\r
383 fontColorMenu.getMenu().triggered.connect(this, "fontColorClicked()");
\r
384 buttonLayout.addWidget(fontColor);
\r
385 fontHilight = newEditorButton("fontHilight", "Font Hilight Color");
\r
386 fontHilightColorMenu = new ColorMenu(this);
\r
387 fontHilight.setMenu(fontHilightColorMenu.getMenu());
\r
388 fontHilightColorMenu.getMenu().triggered.connect(this, "fontHilightClicked()");
\r
389 buttonLayout.addWidget(fontHilight);
\r
391 buttonLayout.addWidget(new QLabel(), 1);
\r
392 v.addWidget(browser, 1);
\r
393 // v.addLayout(buttonLayout,0);
\r
396 browser.downloadAttachmentRequested.connect(this,
\r
397 "downloadAttachment(QNetworkRequest)");
\r
398 browser.downloadImageRequested.connect(this,
\r
399 "downloadImage(QNetworkRequest)");
\r
400 setTabOrder(notebookBox, tagEdit);
\r
401 setTabOrder(tagEdit, browser);
\r
403 focusNoteShortcut = new QShortcut(this);
\r
404 setupShortcut(focusNoteShortcut, "Focus_Note");
\r
405 focusNoteShortcut.activated.connect(this, "focusNote()");
\r
406 focusTitleShortcut = new QShortcut(this);
\r
407 setupShortcut(focusTitleShortcut, "Focus_Title");
\r
408 focusTitleShortcut.activated.connect(this, "focusTitle()");
\r
409 focusTagShortcut = new QShortcut(this);
\r
410 setupShortcut(focusTagShortcut, "Focus_Tag");
\r
411 focusTagShortcut.activated.connect(this, "focusTag()");
\r
412 focusAuthorShortcut = new QShortcut(this);
\r
413 setupShortcut(focusAuthorShortcut, "Focus_Author");
\r
414 focusAuthorShortcut.activated.connect(this, "focusAuthor()");
\r
415 focusUrlShortcut = new QShortcut(this);
\r
416 setupShortcut(focusUrlShortcut, "Focus_Url");
\r
417 focusUrlShortcut.activated.connect(this, "focusUrl()");
\r
419 browser.page().mainFrame().setTextSizeMultiplier(Global.getTextSizeMultiplier());
\r
420 browser.page().mainFrame().setZoomFactor(Global.getZoomFactor());
\r
422 previewPageList = new HashMap<String,Integer>();
\r
424 browser.page().microFocusChanged.connect(this, "microFocusChanged()");
\r
425 logger.log(logger.HIGH, "Browser setup complete");
\r
429 private void setupShortcut(QShortcut action, String text) {
\r
430 if (!Global.shortcutKeys.containsAction(text))
\r
432 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
\r
438 // Getter for the QWebView
\r
439 public QWebView getBrowser() {
\r
443 // Block signals while loading data or things are flagged as dirty by
\r
445 public void loadingData(boolean val) {
\r
446 logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val);
\r
447 notebookBox.blockSignals(val);
\r
448 browser.page().blockSignals(val);
\r
449 browser.page().mainFrame().blockSignals(val);
\r
450 titleLabel.blockSignals(val);
\r
451 alteredDate.blockSignals(val);
\r
452 alteredTime.blockSignals(val);
\r
453 createdTime.blockSignals(val);
\r
454 createdDate.blockSignals(val);
\r
455 subjectDate.blockSignals(val);
\r
456 subjectTime.blockSignals(val);
\r
457 urlText.blockSignals(val);
\r
458 authorText.blockSignals(val);
\r
460 exposeToJavascript();
\r
461 logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val);
\r
465 public void setReadOnly(boolean v) {
\r
467 titleLabel.setEnabled(!v);
\r
468 notebookBox.setEnabled(!v);
\r
469 tagEdit.setEnabled(!v);
\r
470 authorLabel.setEnabled(!v);
\r
471 urlText.setEnabled(!v);
\r
472 createdDate.setEnabled(!v);
\r
473 subjectDate.setEnabled(!v);
\r
474 alteredDate.setEnabled(!v);
\r
475 getBrowser().setEnabled(true);
\r
478 // expose this class to Javascript on the web page
\r
479 private void exposeToJavascript() {
\r
480 browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this);
\r
483 // Custom event queue
\r
485 public boolean event(QEvent e) {
\r
486 if (e.type().equals(QEvent.Type.FocusOut)) {
\r
487 logger.log(logger.EXTREME, "Focus lost");
\r
490 return super.event(e);
\r
493 // clear out browser
\r
494 public void clear() {
\r
495 logger.log(logger.EXTREME, "Entering BrowserWindow.clear()");
\r
497 browser.setContent(new QByteArray());
\r
498 tagEdit.setText("");
\r
499 urlLabel.setText("Source URL:");
\r
500 titleLabel.setText("");
\r
501 logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()");
\r
504 // get/set current note
\r
505 public void setNote(Note n) {
\r
509 saveNoteTitle = n.getTitle();
\r
513 public Note getNote() {
\r
514 return currentNote;
\r
517 // New Editor Button
\r
518 private QPushButton newEditorButton(String name, String toolTip) {
\r
519 QPushButton button = new QPushButton();
\r
520 QIcon icon = new QIcon(iconPath + name + ".gif");
\r
521 button.setIcon(icon);
\r
522 button.setToolTip(toolTip);
\r
523 button.clicked.connect(this, name + "Clicked()");
\r
528 private QLabel newSeparator() {
\r
529 return new QLabel(" ");
\r
532 // Set the title in the window
\r
533 public void setTitle(String t) {
\r
534 titleLabel.setText(t);
\r
539 // Return the current text title
\r
540 public String getTitle() {
\r
541 return titleLabel.text();
\r
544 // Set the tag name string
\r
545 public void setTag(String t) {
\r
547 tagEdit.setText(t);
\r
550 // Set the source URL
\r
551 public void setUrl(String t) {
\r
552 urlLabel.setText("Source URL:\t");
\r
553 urlText.setText(t);
\r
556 public void setAuthor(String t) {
\r
557 authorLabel.setText("Author:\t");
\r
558 authorText.setText(t);
\r
561 // Set the creation date
\r
562 public void setCreation(long date) {
\r
563 QDateTime dt = new QDateTime();
\r
564 dt.setTime_t((int) (date / 1000));
\r
565 createdDate.setDateTime(dt);
\r
566 createdTime.setDateTime(dt);
\r
567 createdDate.setDisplayFormat(Global.getDateFormat());
\r
568 createdTime.setDisplayFormat(Global.getTimeFormat());
\r
571 // Set the creation date
\r
572 public void setAltered(long date) {
\r
573 QDateTime dt = new QDateTime();
\r
574 dt.setTime_t((int) (date / 1000));
\r
575 alteredDate.setDateTime(dt);
\r
576 alteredTime.setDateTime(dt);
\r
577 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
578 alteredTime.setDisplayFormat(Global.getTimeFormat());
\r
581 // Set the subject date
\r
582 public void setSubjectDate(long date) {
\r
583 QDateTime dt = new QDateTime();
\r
584 dt.setTime_t((int) (date / 1000));
\r
585 subjectDate.setDateTime(dt);
\r
586 subjectTime.setDateTime(dt);
\r
587 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
588 subjectTime.setDisplayFormat(Global.getTimeFormat());
\r
591 // Toggle the extended attribute information
\r
592 public void toggleInformation() {
\r
594 extendedOn = false;
\r
598 urlLabel.setVisible(extendedOn);
\r
599 urlText.setVisible(extendedOn);
\r
600 authorText.setVisible(extendedOn);
\r
601 authorLabel.setVisible(extendedOn);
\r
602 createdDate.setVisible(extendedOn);
\r
603 createdTime.setVisible(extendedOn);
\r
604 createdLabel.setVisible(extendedOn);
\r
605 alteredLabel.setVisible(extendedOn);
\r
606 alteredDate.setVisible(extendedOn);
\r
607 alteredTime.setVisible(extendedOn);
\r
608 //notebookBox.setVisible(extendedOn);
\r
609 notebookLabel.setVisible(extendedOn);
\r
610 subjectLabel.setVisible(extendedOn);
\r
611 subjectDate.setVisible(extendedOn);
\r
612 subjectTime.setVisible(extendedOn);
\r
615 public void hideButtons() {
\r
617 buttonsVisible = false;
\r
619 undoButton.setVisible(false);
\r
620 redoButton.setVisible(false);
\r
621 cutButton.setVisible(false);
\r
622 copyButton.setVisible(false);
\r
623 pasteButton.setVisible(false);
\r
624 boldButton.setVisible(false);
\r
625 underlineButton.setVisible(false);
\r
626 italicButton.setVisible(false);
\r
628 rightAlignButton.setVisible(false);
\r
629 leftAlignButton.setVisible(false);
\r
630 centerAlignButton.setVisible(false);
\r
632 strikethroughButton.setVisible(false);
\r
633 hlineButton.setVisible(false);
\r
634 indentButton.setVisible(false);
\r
635 outdentButton.setVisible(false);
\r
636 bulletListButton.setVisible(false);
\r
637 numberListButton.setVisible(false);
\r
639 fontList.setVisible(false);
\r
640 fontSize.setVisible(false);
\r
641 fontColor.setVisible(false);
\r
642 fontHilight.setVisible(false);
\r
647 // Is the extended view on?
\r
648 public boolean isExtended() {
\r
652 // Listener for when a link is clicked
\r
653 @SuppressWarnings("unused")
\r
654 private void openFile() {
\r
655 logger.log(logger.EXTREME, "Starting openFile()");
\r
656 File fileHandle = new File(selectedFile);
\r
657 URI fileURL = fileHandle.toURI();
\r
658 String localURL = fileURL.toString();
\r
659 QUrl url = new QUrl(localURL);
\r
660 QFile file = new QFile(selectedFile);
\r
662 logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName());
\r
663 fileWatcher.addPath(file.fileName());
\r
665 if (!QDesktopServices.openUrl(url)) {
\r
666 logger.log(logger.LOW, "Error opening file :" +url);
\r
671 // Listener for when a link is clicked
\r
672 @SuppressWarnings("unused")
\r
673 private void linkClicked(QUrl url) {
\r
674 logger.log(logger.EXTREME, "URL Clicked: " +url.toString());
\r
675 if (url.toString().substring(0,8).equals("nnres://")) {
\r
676 logger.log(logger.EXTREME, "URL is NN resource");
\r
677 if (url.toString().endsWith("/vnd.evernote.ink")) {
\r
678 logger.log(logger.EXTREME, "Unable to open ink note");
\r
679 QMessageBox.information(this, "Unable Open", "This is an ink note.\n"+
\r
680 "Ink notes are not supported since Evernote has not\n published any specifications on them\n" +
\r
681 "and I'm too lazy to figure them out by myself.");
\r
684 String fullName = url.toString().substring(8);
\r
685 int index = fullName.indexOf(".");
\r
689 type = fullName.substring(index+1);
\r
690 guid = fullName.substring(0,index);
\r
692 index = guid.indexOf(Global.attachmentNameDelimeter);
\r
694 guid = guid.substring(0,index);
\r
696 List<Resource> resList = currentNote.getResources();
\r
697 Resource res = null;
\r
698 for (int i=0; i<resList.size(); i++) {
\r
699 if (resList.get(i).getGuid().equals(guid)) {
\r
700 res = resList.get(i);
\r
705 String resGuid = Global.resourceMap.get(guid);
\r
706 if (resGuid != null)
\r
707 res = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, true);
\r
711 if (res.getAttributes() != null &&
\r
712 res.getAttributes().getFileName() != null &&
\r
713 !res.getAttributes().getFileName().trim().equals(""))
\r
714 fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();
\r
716 fileName = res.getGuid()+"."+type;
\r
717 QFile file = new QFile(Global.getDirectoryPath() +"res/"+fileName);
\r
718 QFile.OpenMode mode = new QFile.OpenMode();
\r
719 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
720 boolean openResult = file.open(mode);
\r
721 logger.log(logger.EXTREME, "File opened:" +openResult);
\r
722 QDataStream out = new QDataStream(file);
\r
723 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);
\r
724 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
726 logger.log(logger.EXTREME, "Writing resource");
\r
727 out.writeBytes(binData.toByteArray());
\r
730 String whichOS = System.getProperty("os.name");
\r
731 if (whichOS.contains("Windows"))
\r
732 url.setUrl("file:///"+file.fileName());
\r
734 url.setUrl("file://"+file.fileName());
\r
735 // fileWatcher.removePath(file.fileName());
\r
736 logger.log(logger.EXTREME, "Adding file watcher " +file.fileName());
\r
737 fileWatcher.addPath(file.fileName());
\r
739 // If we can't open it, then prompt the user to save it.
\r
740 if (!QDesktopServices.openUrl(url)) {
\r
741 logger.log(logger.EXTREME, "We can't handle this. Where do we put it?");
\r
742 QFileDialog dialog = new QFileDialog();
\r
744 if (dialog.exec()!=0) {
\r
745 List<String> fileNames = dialog.selectedFiles(); //gets all selected filenames
\r
746 if (fileNames.size() == 0)
\r
748 String sf = fileNames.get(0);
\r
749 QFile saveFile = new QFile(sf);
\r
750 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
751 saveFile.open(mode);
\r
752 QDataStream saveOut = new QDataStream(saveFile);
\r
753 saveOut.writeBytes(binData.toByteArray());
\r
761 logger.log(logger.EXTREME, "Launching URL");
\r
762 QDesktopServices.openUrl(url);
\r
765 // Listener for when BOLD is clicked
\r
766 @SuppressWarnings("unused")
\r
767 private void undoClicked() {
\r
768 browser.page().triggerAction(WebAction.Undo);
\r
769 browser.setFocus();
\r
772 // Listener for when BOLD is clicked
\r
773 @SuppressWarnings("unused")
\r
774 private void redoClicked() {
\r
775 browser.page().triggerAction(WebAction.Redo);
\r
776 browser.setFocus();
\r
779 // Listener for when BOLD is clicked
\r
780 @SuppressWarnings("unused")
\r
781 private void boldClicked() {
\r
782 browser.page().triggerAction(WebAction.ToggleBold);
\r
783 microFocusChanged();
\r
784 browser.setFocus();
\r
787 // Listener for when Italics is clicked
\r
788 @SuppressWarnings("unused")
\r
789 private void italicClicked() {
\r
790 browser.page().triggerAction(WebAction.ToggleItalic);
\r
791 microFocusChanged();
\r
792 browser.setFocus();
\r
795 // Listener for when UNDERLINE is clicked
\r
796 @SuppressWarnings("unused")
\r
797 private void underlineClicked() {
\r
798 browser.page().triggerAction(WebAction.ToggleUnderline);
\r
799 microFocusChanged();
\r
800 browser.setFocus();
\r
803 // Listener for when Strikethrough is clicked
\r
804 @SuppressWarnings("unused")
\r
805 private void strikethroughClicked() {
\r
806 browser.page().mainFrame().evaluateJavaScript(
\r
807 "document.execCommand('strikeThrough', false, '');");
\r
808 browser.setFocus();
\r
811 // Listener for when cut is clicked
\r
812 @SuppressWarnings("unused")
\r
813 private void cutClicked() {
\r
814 browser.page().triggerAction(WebAction.Cut);
\r
815 browser.setFocus();
\r
818 // Listener when COPY is clicked
\r
819 @SuppressWarnings("unused")
\r
820 private void copyClicked() {
\r
821 browser.page().triggerAction(WebAction.Copy);
\r
822 browser.setFocus();
\r
825 // Listener when PASTE is clicked
\r
826 void pasteClicked() {
\r
827 logger.log(logger.EXTREME, "Paste Clicked");
\r
828 if (forceTextPaste) {
\r
829 pasteWithoutFormattingClicked();
\r
832 QClipboard clipboard = QApplication.clipboard();
\r
833 QMimeData mime = clipboard.mimeData();
\r
835 // String x = mime.html();
\r
837 if (mime.hasImage()) {
\r
838 logger.log(logger.EXTREME, "Image paste found");
\r
840 browser.setFocus();
\r
844 if (mime.hasUrls()) {
\r
845 logger.log(logger.EXTREME, "URL paste found");
\r
847 browser.setFocus();
\r
851 String text = mime.html();
\r
852 if (text.contains("en-tag") && mime.hasHtml()) {
\r
853 logger.log(logger.EXTREME, "Intra-note paste found");
\r
854 text = fixInternotePaste(text);
\r
855 mime.setHtml(text);
\r
856 clipboard.setMimeData(mime);
\r
859 logger.log(logger.EXTREME, "Final paste choice encountered");
\r
860 browser.page().triggerAction(WebAction.Paste);
\r
861 browser.setFocus();
\r
865 // Paste text without formatting
\r
866 private void pasteWithoutFormattingClicked() {
\r
867 logger.log(logger.EXTREME, "Paste without format clipped");
\r
868 QClipboard clipboard = QApplication.clipboard();
\r
869 QMimeData mime = clipboard.mimeData();
\r
870 if (!mime.hasText())
\r
872 String text = mime.text();
\r
873 clipboard.setText(text);
\r
874 browser.page().triggerAction(WebAction.Paste);
\r
875 QApplication.clipboard().setMimeData(mime);
\r
876 browser.setFocus();
\r
880 // insert date/time
\r
881 @SuppressWarnings("unused")
\r
882 private void insertDateTime() {
\r
883 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
\r
884 String dateTimeFormat = new String(fmt);
\r
885 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
\r
886 Calendar cal = Calendar.getInstance();
\r
888 browser.page().mainFrame().evaluateJavaScript(
\r
889 "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");
\r
891 browser.setFocus();
\r
895 // Listener when Left is clicked
\r
896 @SuppressWarnings("unused")
\r
897 private void justifyLeftClicked() {
\r
898 browser.page().mainFrame().evaluateJavaScript(
\r
899 "document.execCommand('JustifyLeft', false, '');");
\r
900 browser.setFocus();
\r
903 // Listener when Center is clicked
\r
904 @SuppressWarnings("unused")
\r
905 private void justifyCenterClicked() {
\r
906 browser.page().mainFrame().evaluateJavaScript(
\r
907 "document.execCommand('JustifyCenter', false, '');");
\r
908 browser.setFocus();
\r
911 // Listener when Left is clicked
\r
912 @SuppressWarnings("unused")
\r
913 private void justifyRightClicked() {
\r
914 browser.page().mainFrame().evaluateJavaScript(
\r
915 "document.execCommand('JustifyRight', false, '');");
\r
916 browser.setFocus();
\r
919 // Listener when HLINE is clicked
\r
920 @SuppressWarnings("unused")
\r
921 private void hlineClicked() {
\r
922 browser.page().mainFrame().evaluateJavaScript(
\r
923 "document.execCommand('insertHorizontalRule', false, '');");
\r
924 browser.setFocus();
\r
927 // Listener when outdent is clicked
\r
928 private void outdentClicked() {
\r
929 browser.page().mainFrame().evaluateJavaScript(
\r
930 "document.execCommand('outdent', false, '');");
\r
931 browser.setFocus();
\r
934 // Listener when a bullet list is clicked
\r
935 @SuppressWarnings("unused")
\r
936 private void bulletListClicked() {
\r
937 browser.page().mainFrame().evaluateJavaScript(
\r
938 "document.execCommand('InsertUnorderedList', false, '');");
\r
939 browser.setFocus();
\r
942 // Listener when a bullet list is clicked
\r
943 @SuppressWarnings("unused")
\r
944 private void numberListClicked() {
\r
945 browser.page().mainFrame().evaluateJavaScript(
\r
946 "document.execCommand('InsertOrderedList', false, '');");
\r
947 browser.setFocus();
\r
950 // Listener when indent is clicked
\r
951 private void indentClicked() {
\r
952 browser.page().mainFrame().evaluateJavaScript(
\r
953 "document.execCommand('indent', false, '');");
\r
954 browser.setFocus();
\r
957 // Listener when the font name is changed
\r
958 @SuppressWarnings("unused")
\r
959 private void fontChanged(String font) {
\r
960 browser.page().mainFrame().evaluateJavaScript(
\r
961 "document.execCommand('fontName',false,'" + font + "');");
\r
962 browser.setFocus();
\r
965 // Listener when a font size is changed
\r
966 @SuppressWarnings("unused")
\r
967 private void fontSizeChanged(String font) {
\r
968 String text = browser.selectedText();
\r
969 if (text.trim().equalsIgnoreCase(""))
\r
972 String selectedText = browser.selectedText();
\r
973 String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";
\r
974 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
975 browser.page().mainFrame().evaluateJavaScript(script);
\r
976 /* browser.page().mainFrame().evaluateJavaScript(
\r
977 "document.execCommand('fontSize',false,'"
\r
980 browser.setFocus();
\r
983 // Load the font combo box based upon the font selected
\r
984 private void loadFontSize(String name) {
\r
985 QFontDatabase db = new QFontDatabase();
\r
987 List<Integer> points = db.pointSizes(name);
\r
988 for (int i=0; i<points.size(); i++) {
\r
989 fontSize.addItem(points.get(i).toString());
\r
992 fontSize.addItem("x-small");
\r
993 fontSize.addItem("small");
\r
994 fontSize.addItem("medium");
\r
995 fontSize.addItem("large");
\r
996 fontSize.addItem("x-large");
\r
997 fontSize.addItem("xx-large");
\r
998 fontSize.addItem("xxx-large");
\r
1002 // Listener when a font size is changed
\r
1003 @SuppressWarnings("unused")
\r
1004 private void fontColorClicked() {
\r
1005 // QColorDialog dialog = new QColorDialog();
\r
1006 // QColor color = QColorDialog.getColor();
\r
1007 QColor color = fontColorMenu.getColor();
\r
1008 if (color.isValid())
\r
1009 browser.page().mainFrame().evaluateJavaScript(
\r
1010 "document.execCommand('foreColor',false,'" + color.name()
\r
1012 browser.setFocus();
\r
1015 // Listener for when a background color change is requested
\r
1016 @SuppressWarnings("unused")
\r
1017 private void fontHilightClicked() {
\r
1018 // QColorDialog dialog = new QColorDialog();
\r
1019 // QColor color = QColorDialog.getColor();
\r
1020 QColor color = fontHilightColorMenu.getColor();
\r
1021 if (color.isValid())
\r
1022 browser.page().mainFrame().evaluateJavaScript(
\r
1023 "document.execCommand('backColor',false,'" + color.name()
\r
1025 browser.setFocus();
\r
1028 // Listener for when a background color change is requested
\r
1029 @SuppressWarnings("unused")
\r
1030 private void superscriptClicked() {
\r
1031 browser.page().mainFrame().evaluateJavaScript(
\r
1032 "document.execCommand('superscript');");
\r
1033 browser.setFocus();
\r
1036 // Listener for when a background color change is requested
\r
1037 @SuppressWarnings("unused")
\r
1038 private void subscriptClicked() {
\r
1039 browser.page().mainFrame().evaluateJavaScript(
\r
1040 "document.execCommand('subscript');");
\r
1041 browser.setFocus();
\r
1043 // Insert a to-do checkbox
\r
1044 @SuppressWarnings("unused")
\r
1045 private void todoClicked() {
\r
1046 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1047 String script_start = new String(
\r
1048 "document.execCommand('insertHtml', false, '");
\r
1049 String script_end = new String("');");
\r
1050 String todo = new String(
\r
1051 "<input TYPE=\"CHECKBOX\" value=\"false\" onClick=\"value=checked; window.jambi.contentChanged(); \" />");
\r
1052 browser.page().mainFrame().evaluateJavaScript(
\r
1053 script_start + todo + script_end);
\r
1054 browser.setFocus();
\r
1057 // Encrypt the selected text
\r
1058 @SuppressWarnings("unused")
\r
1059 private void encryptText() {
\r
1060 String text = browser.selectedText();
\r
1061 if (text.trim().equalsIgnoreCase(""))
\r
1064 EnCryptDialog dialog = new EnCryptDialog();
\r
1066 if (!dialog.okPressed()) {
\r
1070 EnCrypt crypt = new EnCrypt();
\r
1071 String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);
\r
1073 if (encrypted.trim().equals("")) {
\r
1074 QMessageBox.information(this, "Error", "Error Encrypting String");
\r
1077 StringBuffer imgPath = new StringBuffer(Global.getDirectoryPath());
\r
1078 for (int i = 0; i < imgPath.length(); i++)
\r
1079 if (imgPath.charAt(i) == '\\')
\r
1080 imgPath.setCharAt(i, '/');
\r
1081 StringBuffer buffer = new StringBuffer(encrypted.length() + 100);
\r
1082 buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""
\r
1083 + dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");
\r
1084 buffer.append("contentEditable=\"false\" alt=\"");
\r
1085 buffer.append(encrypted);
\r
1086 buffer.append("\" src=\"" + imgPath.toString()
\r
1087 + "images/encrypt.png\" ");
\r
1088 Global.cryptCounter++;
\r
1089 buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");
\r
1090 buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");
\r
1091 buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString()
\r
1092 +"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&apos;")+"\\');\"");
\r
1093 buffer.append("style=\"display:block\" />");
\r
1095 String script_start = new String(
\r
1096 "document.execCommand('insertHtml', false, '");
\r
1097 String script_end = new String("');");
\r
1098 browser.page().mainFrame().evaluateJavaScript(
\r
1099 script_start + buffer.toString() + script_end);
\r
1103 // Insert a hyperlink
\r
1104 public void insertLink() {
\r
1105 logger.log(logger.EXTREME, "Inserting link");
\r
1106 String text = browser.selectedText();
\r
1107 if (text.trim().equalsIgnoreCase(""))
\r
1110 InsertLinkDialog dialog = new InsertLinkDialog();
\r
1111 if (currentHyperlink != null && currentHyperlink != "") {
\r
1112 dialog.setUrl(currentHyperlink);
\r
1115 if (!dialog.okPressed()) {
\r
1116 logger.log(logger.EXTREME, "Insert link canceled");
\r
1119 if (browser.insertLinkAction.text().equalsIgnoreCase("Insert Hyperlink")) {
\r
1120 String selectedText = browser.selectedText();
\r
1121 logger.log(logger.EXTREME, "Inserting link on text "+selectedText);
\r
1122 logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim());
\r
1123 String url = "<a href=\"" +dialog.getUrl().trim()+"\" >"+selectedText +"</a>";
\r
1124 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1125 browser.page().mainFrame().evaluateJavaScript(script);
\r
1128 String js = new String( "function getCursorPos() {"
\r
1130 +"if (window.getSelection) {"
\r
1131 +" var selObj = window.getSelection();"
\r
1132 +" var selRange = selObj.getRangeAt(0);"
\r
1133 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1134 +" while(workingNode != null) { "
\r
1135 +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');"
\r
1136 +" workingNode = workingNode.parentNode;"
\r
1139 +"} getCursorPos();");
\r
1140 browser.page().mainFrame().evaluateJavaScript(js);
\r
1147 public void insertTable() {
\r
1148 TableDialog dialog = new TableDialog();
\r
1150 if (!dialog.okPressed()) {
\r
1154 int cols = dialog.getCols();
\r
1155 int rows = dialog.getRows();
\r
1156 int width = dialog.getWidth();
\r
1157 boolean percent = dialog.isPercent();
\r
1159 String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();
\r
1161 newHTML = newHTML +"%";
\r
1162 newHTML = newHTML + "\"><tbody>";
\r
1164 for (int i=0; i<rows; i++) {
\r
1165 newHTML = newHTML +"<tr>";
\r
1166 for (int j=0; j<cols; j++) {
\r
1167 newHTML = newHTML +"<td> </td>";
\r
1169 newHTML = newHTML +"</tr>";
\r
1171 newHTML = newHTML+"</tbody></table>";
\r
1173 String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";
\r
1174 browser.page().mainFrame().evaluateJavaScript(script);
\r
1178 // Text content changed
\r
1179 @SuppressWarnings("unused")
\r
1180 private void selectionChanged() {
\r
1181 browser.encryptAction.setEnabled(true);
\r
1182 browser.insertLinkAction.setEnabled(true);
\r
1183 String scriptStart = "var selection_text = (window.getSelection()).toString();"
\r
1184 + "var range = (window.getSelection()).getRangeAt(0);"
\r
1185 + "var parent_html = range.commonAncestorContainer.innerHTML;"
\r
1186 + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"
\r
1187 + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"
\r
1188 + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"
\r
1189 + "var start = parent_html.indexOf(first_text);"
\r
1190 + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"
\r
1191 + "var value = parent_html.substring(start,end);"
\r
1192 + "window.jambi.saveSelectedText(value);" ;
\r
1193 browser.page().mainFrame().evaluateJavaScript(scriptStart);
\r
1197 public void saveSelectedText(String text) {
\r
1198 boolean enabled = true;
\r
1199 if (text.trim().length() == 0)
\r
1201 if (text.indexOf("en-tag=\"en-crypt\"") >= 0)
\r
1203 if (text.indexOf("<img en-tag=\"en-media\"") >= 0)
\r
1205 if (text.indexOf("<a en-tag=\"en-media\"") >= 0)
\r
1207 if (text.indexOf("<input ") >= 0)
\r
1210 browser.encryptAction.setEnabled(enabled);
\r
1211 browser.insertLinkAction.setEnabled(enabled);
\r
1212 // selectedText = text;
\r
1215 // Decrypt clicked text
\r
1216 public void decryptText(String id, String text, String hint) {
\r
1217 EnCrypt crypt = new EnCrypt();
\r
1218 String plainText = null;
\r
1219 Calendar currentTime = new GregorianCalendar();
\r
1220 Long l = new Long(currentTime.getTimeInMillis());
\r
1221 String slot = new String(Long.toString(l));
\r
1223 // First, try to decrypt with any keys we already have
\r
1224 for (int i=0; i<Global.passwordRemember.size(); i++) {
\r
1225 plainText = crypt.decrypt(text, Global.passwordRemember.get(i), 64);
\r
1226 if (plainText != null) {
\r
1227 slot = new String(Long.toString(l));
\r
1228 Global.passwordSafe.put(slot, Global.passwordRemember.get(i));
\r
1229 removeEncryption(id, plainText, false, slot);
\r
1235 EnDecryptDialog dialog = new EnDecryptDialog();
\r
1236 dialog.setHint(hint);
\r
1237 while (plainText == null || !dialog.okPressed()) {
\r
1239 if (!dialog.okPressed()) {
\r
1242 plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);
\r
1243 if (plainText == null) {
\r
1244 QMessageBox.warning(this, "Incorrect Password", "The password entered is not correct");
\r
1247 Global.passwordSafe.put(slot, dialog.getPassword());
\r
1248 removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);
\r
1249 if (dialog.rememberPassword())
\r
1250 Global.passwordRemember.add(dialog.getPassword());
\r
1254 // Get the editor tag line
\r
1255 public TagLineEdit getTagLine() {
\r
1259 // Modify a note's tags
\r
1260 @SuppressWarnings("unused")
\r
1261 private void modifyTags() {
\r
1262 TagAssign tagWindow = new TagAssign(allTags, currentTags);
\r
1264 if (tagWindow.okClicked()) {
\r
1265 currentTags.clear();
\r
1266 StringBuffer tagDisplay = new StringBuffer();
\r
1268 List<QListWidgetItem> newTags = tagWindow.getTagList()
\r
1270 for (int i = 0; i < newTags.size(); i++) {
\r
1271 currentTags.add(newTags.get(i).text());
\r
1272 tagDisplay.append(newTags.get(i).text());
\r
1273 if (i < newTags.size() - 1) {
\r
1274 tagDisplay.append(Global.tagDelimeter + " ");
\r
1277 tagEdit.setText(tagDisplay.toString());
\r
1278 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1282 // Tag line has been modified by typing text
\r
1283 @SuppressWarnings("unused")
\r
1284 private void modifyTagsTyping() {
\r
1286 String newTags = tagEdit.text();
\r
1287 List<String> test = tagEdit.tagCompleter.getTagList();
\r
1288 if (newTags.equalsIgnoreCase(saveTagList))
\r
1291 // We know something has changed...
\r
1292 String oldTagArray[] = saveTagList.split(Global.tagDelimeter);
\r
1293 String newTagArray[] = newTags.split(Global.tagDelimeter);
\r
1295 List<String> newTagList = new ArrayList<String>();
\r
1296 List<String> oldTagList = new ArrayList<String>();
\r
1298 for (int i = 0; i < oldTagArray.length; i++)
\r
1299 if (!oldTagArray[i].trim().equals(""))
\r
1300 oldTagList.add(oldTagArray[i]);
\r
1301 for (int i = 0; i < newTagArray.length; i++)
\r
1302 if (!newTagArray[i].trim().equals(""))
\r
1303 newTagList.add(newTagArray[i]);
\r
1305 // We now have lists of the new & old. Remove duplicates. If all
\r
1306 // are removed from both then nothing has really changed
\r
1307 for (int i = newTagList.size() - 1; i >= 0; i--) {
\r
1308 String nTag = newTagList.get(i);
\r
1309 for (int j = oldTagList.size() - 1; j >= 0; j--) {
\r
1310 String oTag = oldTagList.get(j);
\r
1311 if (oTag.equalsIgnoreCase(nTag)) {
\r
1312 oldTagList.remove(j);
\r
1313 newTagList.remove(i);
\r
1319 if (oldTagList.size() != 0 || newTagList.size() != 0) {
\r
1320 currentTags.clear();
\r
1321 for (int i = 0; i < newTagArray.length; i++)
\r
1322 if (!newTagArray[i].trim().equals(""))
\r
1323 currentTags.add(newTagArray[i].trim());
\r
1325 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1330 // Tab button was pressed
\r
1331 public void tabPressed() {
\r
1332 if (!insideList) {
\r
1333 String script_start = new String(
\r
1334 "document.execCommand('insertHtml', false, ' ');");
\r
1335 browser.page().mainFrame().evaluateJavaScript(script_start);
\r
1340 public void backtabPressed() {
\r
1345 public void setInsideList() {
\r
1346 insideList = true;
\r
1349 // The title has been edited
\r
1350 @SuppressWarnings("unused")
\r
1351 private void titleEdited() {
\r
1352 // If we don't have a good note, or if the current title
\r
1353 // matches the old title then we don't need to do anything
\r
1354 if (currentNote == null)
\r
1356 if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))
\r
1359 // If we have a real change, we need to save it.
\r
1360 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text());
\r
1361 currentNote.setTitle(titleLabel.text());
\r
1362 saveNoteTitle = titleLabel.text();
\r
1366 // Set the list of note tags
\r
1367 public void setAllTags(List<Tag> l) {
\r
1369 tagEdit.setTagList(l);
\r
1372 // Setter for the current tags
\r
1373 public void setCurrentTags(List<String> s) {
\r
1377 // Save the list of notebooks
\r
1378 public void setNotebookList(List<Notebook> n) {
\r
1380 loadNotebookList();
\r
1383 // Load the notebook list and select the current notebook
\r
1384 private void loadNotebookList() {
\r
1385 if (notebookBox.count() != 0)
\r
1386 notebookBox.clear();
\r
1387 if (notebookList == null)
\r
1390 for (int i = 0; i < notebookList.size(); i++) {
\r
1391 notebookBox.addItem(notebookList.get(i).getName());
\r
1392 if (currentNote != null) {
\r
1393 if (currentNote.getNotebookGuid().equals(
\r
1394 notebookList.get(i).getGuid())) {
\r
1395 notebookBox.setCurrentIndex(i);
\r
1401 // Get the contents of the editor
\r
1402 public String getContent() {
\r
1403 return browser.page().currentFrame().toHtml();
\r
1406 // The note contents have changed
\r
1407 public void contentChanged() {
\r
1408 String content = getContent();
\r
1410 noteSignal.noteChanged.emit(currentNote.getGuid(), content);
\r
1413 // noteSignal.noteChanged.emit(currentNote.getGuid(), unicode);
\r
1416 // The notebook selection has changed
\r
1417 @SuppressWarnings("unused")
\r
1418 private void notebookChanged() {
\r
1419 boolean changed = false;
\r
1420 String n = notebookBox.currentText();
\r
1421 for (int i = 0; i < notebookList.size(); i++) {
\r
1422 if (n.equals(notebookList.get(i).getName())) {
\r
1423 if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {
\r
1424 currentNote.setNotebookGuid(notebookList.get(i).getGuid());
\r
1427 i = notebookList.size();
\r
1431 // If the notebook changed, signal the update
\r
1433 noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote
\r
1434 .getNotebookGuid());
\r
1437 // Check the note title
\r
1438 private void checkNoteTitle() {
\r
1439 String text = browser.page().currentFrame().toPlainText();
\r
1440 if (saveNoteTitle.trim().equals("")) {
\r
1441 int newLine = text.indexOf("\n");
\r
1442 if (newLine > 0) {
\r
1443 text = text.substring(0, newLine);
\r
1444 if (text.trim().equals(""))
\r
1445 text = "Untitled Note";
\r
1446 titleLabel.setText(text);
\r
1448 if (text.length() > 20)
\r
1449 titleLabel.setText(text.substring(0, 20));
\r
1451 if (text.trim().equals(""))
\r
1452 titleLabel.setText("Untitled Note");
\r
1454 titleLabel.setText(text);
\r
1457 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel
\r
1462 // Return the note contents so we can email them
\r
1463 public String getContentsToEmail() {
\r
1464 return browser.page().currentFrame().toPlainText().trim();
\r
1466 * int body = browser.page().currentFrame().toHtml().indexOf("<body>");
\r
1467 * String temp = browser.page().currentFrame().toHtml(); if (body == -1)
\r
1468 * temp = "<html><body><b>Test</b></body></html>"; else temp =
\r
1469 * "<html>"+temp.substring(body); return temp; // return
\r
1470 * urlEncode(browser.page().currentFrame().toHtml());
\r
1474 // Insert an image into the editor
\r
1475 private void insertImage(QMimeData mime) {
\r
1476 logger.log(logger.EXTREME, "Entering insertImage");
\r
1477 QImage img = (QImage) mime.imageData();
\r
1478 String script_start = new String(
\r
1479 "document.execCommand('insertHTML', false, '");
\r
1480 String script_end = new String("');");
\r
1482 long now = new Date().getTime();
\r
1483 String path = Global.getDirectoryPath() + "res/"
\r
1484 + (new Long(now).toString()) + ".jpg";
\r
1486 // This block is just a hack to make sure we wait at least 1ms so we
\r
1488 // have collisions on image names
\r
1489 long i = new Date().getTime();
\r
1491 i = new Date().getTime();
\r
1493 // Open the file & write the data
\r
1494 QFile tfile = new QFile(path);
\r
1495 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1499 Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);
\r
1500 if (newRes == null)
\r
1502 currentNote.getResources().add(newRes);
\r
1504 // do the actual insert into the note
\r
1505 StringBuffer buffer = new StringBuffer(100);
\r
1506 buffer.append("<img src=\"");
\r
1507 buffer.append(tfile.fileName());
\r
1508 buffer.append("\" en-tag=en-media type=\"image/jpeg\""
\r
1509 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1510 +" guid=\"" +newRes.getGuid() +"\""
\r
1511 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1513 browser.page().mainFrame().evaluateJavaScript(
\r
1514 script_start + buffer + script_end);
\r
1519 // Handle URLs that are trying to be pasted
\r
1520 public void handleUrls(QMimeData mime) {
\r
1521 logger.log(logger.EXTREME, "Starting handleUrls");
\r
1522 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1524 List<QUrl> urlList = mime.urls();
\r
1525 String url = new String();
\r
1526 String script_start = new String(
\r
1527 "document.execCommand('createLink', false, '");
\r
1528 String script_end = new String("');");
\r
1530 for (int i = 0; i < urlList.size(); i++) {
\r
1531 url = urlList.get(i).toString();
\r
1532 // Find out what type of file we have
\r
1533 String mimeType = fileNameMap.getContentTypeFor(url);
\r
1535 // If null returned, we need to guess at the file type
\r
1536 if (mimeType == null)
\r
1537 mimeType = "application/"
\r
1538 + url.substring(url.lastIndexOf(".") + 1);
\r
1540 // Check if we have an image or some other type of file
\r
1541 if (url.substring(0, 5).equalsIgnoreCase("file:")
\r
1542 && mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1543 handleLocalImageURLPaste(mime, mimeType);
\r
1546 String[] type = mimeType.split("/");
\r
1547 boolean valid = validAttachment(type[1]);
\r
1548 boolean smallEnough = checkFileAttachmentSize(url);
\r
1549 if (smallEnough && valid
\r
1550 && url.substring(0, 5).equalsIgnoreCase("file:")
\r
1551 && !mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1552 handleLocalAttachment(mime, mimeType);
\r
1555 browser.page().mainFrame().evaluateJavaScript(
\r
1556 script_start + url + script_end);
\r
1561 // If a URL being pasted is an image URL, then attach the image
\r
1562 private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {
\r
1563 List<QUrl> urlList = mime.urls();
\r
1564 String url = new String();
\r
1565 String script_start_image = new String(
\r
1566 "document.execCommand('insertHtml', false, '");
\r
1567 String script_end = new String("');");
\r
1568 StringBuffer buffer;
\r
1570 // Copy the image over into the resource directory and create a new resource
\r
1571 // record for each url pasted
\r
1572 for (int i = 0; i < urlList.size(); i++) {
\r
1573 url = urlList.get(i).toString();
\r
1575 Resource newRes = createResource(url, i, mimeType, false);
\r
1576 if (newRes == null)
\r
1578 currentNote.getResources().add(newRes);
\r
1579 buffer = new StringBuffer(100);
\r
1581 // Open the file & write the data
\r
1582 String fileName = Global.getDirectoryPath()+"res/"+newRes.getGuid();
\r
1583 QFile tfile = new QFile(fileName);
\r
1584 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1585 tfile.write(newRes.getData().getBody());
\r
1587 fileName = fileName.replace('\\', '/');
\r
1588 buffer.append(script_start_image);
\r
1589 buffer.append("<img src=\"" +fileName);
\r
1590 // if (mimeType.equalsIgnoreCase("image/jpg"))
\r
1591 // mimeType = "image/jpeg";
\r
1592 buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""
\r
1593 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1594 +" guid=\"" +newRes.getGuid() +"\""
\r
1595 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1597 buffer.append(script_end);
\r
1598 browser.page().mainFrame().evaluateJavaScript(buffer.toString());
\r
1604 // If a URL being pasted is a local file URL, then attach the file
\r
1605 private void handleLocalAttachment(QMimeData mime, String mimeType) {
\r
1606 logger.log(logger.EXTREME, "Attaching local file");
\r
1607 List<QUrl> urlList = mime.urls();
\r
1608 String script_start = new String(
\r
1609 "document.execCommand('insertHtml', false, '");
\r
1610 String script_end = new String("');");
\r
1611 StringBuffer buffer;
\r
1613 for (int i = 0; i < urlList.size(); i++) {
\r
1614 buffer = new StringBuffer(100);
\r
1615 String url = urlList.get(i).toString();
\r
1617 // Start building the HTML
\r
1618 String[] type = mimeType.split("/");
\r
1619 String icon = findIcon(type[1]);
\r
1620 if (icon.equals("attachment.png"))
\r
1621 icon = findIcon(type[0]);
\r
1622 if (icon.equals("attachment.png"))
\r
1623 icon = findIcon(url.substring(url.lastIndexOf(".")+1));
\r
1624 StringBuffer imageBuffer = new StringBuffer();
\r
1625 String whichOS = System.getProperty("os.name");
\r
1626 if (whichOS.contains("Windows"))
\r
1627 imageBuffer.append("file:///" + Global.getDirectoryPath()
\r
1628 + "images/" + icon);
\r
1630 imageBuffer.append("file://" + Global.getDirectoryPath()
\r
1631 + "images/" + icon);
\r
1632 // Fix stupid Windows file separation characters
\r
1633 if (whichOS.contains("Windows")) {
\r
1634 for (int z = imageBuffer.indexOf("\\"); z > 0; z = imageBuffer
\r
1636 int w = imageBuffer.indexOf("\\");
\r
1637 imageBuffer.replace(w, w + 1, "/");
\r
1641 logger.log(logger.EXTREME, "Creating resource ");
\r
1642 Resource newRes = createResource(url, i, mimeType, true);
\r
1643 if (newRes == null)
\r
1645 logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());
\r
1646 currentNote.getResources().add(newRes);
\r
1648 String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();
\r
1649 // If we have a PDF, we need to setup the preview.
\r
1650 if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {
\r
1651 logger.log(logger.EXTREME, "Setting up PDF preview");
\r
1652 if (newRes.getAttributes() != null &&
\r
1653 newRes.getAttributes().getFileName() != null &&
\r
1654 !newRes.getAttributes().getFileName().trim().equals(""))
\r
1655 fileName = newRes.getGuid()+Global.attachmentNameDelimeter+
\r
1656 newRes.getAttributes().getFileName();
\r
1658 fileName = newRes.getGuid()+".pdf";
\r
1659 QFile file = new QFile(Global.getDirectoryPath() +"res/"+fileName);
\r
1660 QFile.OpenMode mode = new QFile.OpenMode();
\r
1661 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
1663 QDataStream out = new QDataStream(file);
\r
1664 // Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);
\r
1665 QByteArray binData = new QByteArray(newRes.getData().getBody());
\r
1666 // resBinary = null;
\r
1667 out.writeBytes(binData.toByteArray());
\r
1670 PDFPreview pdfPreview = new PDFPreview();
\r
1671 if (pdfPreview.setupPreview(Global.currentDir+"res/"+fileName, "pdf",0));
\r
1672 imageBuffer = new StringBuffer(file.fileName()+".png");
\r
1675 logger.log(logger.EXTREME, "Generating link tags");
\r
1676 buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");
\r
1677 buffer.append(" onContextMenu=\"window.jambi.imageContextMenu('" +Global.getDirectoryPath() +"res/"+fileName +"');\" ");
\r
1678 buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");
\r
1679 buffer.append("<img src=\"" + imageBuffer.toString()+"\" title=\"" +newRes.getAttributes().getFileName());
\r
1680 buffer.append("\"></img>");
\r
1681 buffer.append("</a>");
\r
1682 browser.page().mainFrame().evaluateJavaScript(
\r
1683 script_start + buffer.toString() + script_end);
\r
1687 private Resource createResource(String url, int sequence, String mime, boolean attachment) {
\r
1688 logger.log(logger.EXTREME, "Inside create resource");
\r
1689 QFile resourceFile;
\r
1690 url = new QUrl(url).toLocalFile();
\r
1691 url = url.replace("/", File.separator);
\r
1692 resourceFile = new QFile(url);
\r
1693 resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));
\r
1694 byte[] fileData = resourceFile.readAll().toByteArray();
\r
1695 resourceFile.close();
\r
1696 if (fileData.length == 0)
\r
1700 md = MessageDigest.getInstance("MD5");
\r
1701 md.update(fileData);
\r
1702 byte[] hash = md.digest();
\r
1704 Resource r = new Resource();
\r
1705 Calendar time = new GregorianCalendar();
\r
1706 long prevTime = time.getTimeInMillis();
\r
1707 while (prevTime == time.getTimeInMillis()) {
\r
1708 time = new GregorianCalendar();
\r
1710 r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());
\r
1711 r.setNoteGuid(currentNote.getGuid());
\r
1713 r.setActive(true);
\r
1714 r.setUpdateSequenceNum(0);
\r
1715 r.setWidth((short) 0);
\r
1716 r.setHeight((short) 0);
\r
1717 r.setDuration((short) 0);
\r
1719 Data d = new Data();
\r
1720 d.setBody(fileData);
\r
1721 d.setBodyIsSet(true);
\r
1722 d.setBodyHash(hash);
\r
1723 d.setBodyHashIsSet(true);
\r
1725 d.setSize(fileData.length);
\r
1727 int fileNamePos = url.lastIndexOf(File.separator);
\r
1728 if (fileNamePos == -1)
\r
1729 fileNamePos = url.lastIndexOf("/");
\r
1730 String fileName = url.substring(fileNamePos+1);
\r
1731 ResourceAttributes a = new ResourceAttributes();
\r
1733 a.setAltitudeIsSet(false);
\r
1734 a.setLongitude(0);
\r
1735 a.setLongitudeIsSet(false);
\r
1737 a.setLatitudeIsSet(false);
\r
1738 a.setCameraMake("");
\r
1739 a.setCameraMakeIsSet(false);
\r
1740 a.setCameraModel("");
\r
1741 a.setCameraModelIsSet(false);
\r
1742 a.setAttachment(attachment);
\r
1743 a.setAttachmentIsSet(true);
\r
1744 a.setClientWillIndex(false);
\r
1745 a.setClientWillIndexIsSet(true);
\r
1746 a.setRecoType("");
\r
1747 a.setRecoTypeIsSet(false);
\r
1748 a.setSourceURL(url);
\r
1749 a.setSourceURLIsSet(true);
\r
1750 a.setTimestamp(0);
\r
1751 a.setTimestampIsSet(false);
\r
1752 a.setFileName(fileName);
\r
1753 a.setFileNameIsSet(true);
\r
1754 r.setAttributes(a);
\r
1756 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
1758 } catch (NoSuchAlgorithmException e1) {
\r
1759 e1.printStackTrace();
\r
1765 // find the appropriate icon for an attachment
\r
1766 private String findIcon(String appl) {
\r
1767 appl = appl.toLowerCase();
\r
1768 File f = new File(Global.getDirectoryPath()+"images"+File.separator +appl +".png");
\r
1770 return appl+".png";
\r
1771 return "attachment.png";
\r
1774 // Check if the account supports this type of attachment
\r
1775 private boolean validAttachment(String type) {
\r
1776 if (Global.isPremium())
\r
1778 if (type.equalsIgnoreCase("JPG"))
\r
1780 if (type.equalsIgnoreCase("PNG"))
\r
1782 if (type.equalsIgnoreCase("GIF"))
\r
1784 if (type.equalsIgnoreCase("MP3"))
\r
1786 if (type.equalsIgnoreCase("WAV"))
\r
1788 if (type.equalsIgnoreCase("AMR"))
\r
1790 if (type.equalsIgnoreCase("PDF"))
\r
1792 String error = "Non-premium accounts can only attach JPG, PNG, GIF, MP3, WAV, AMR, or PDF files.";
\r
1793 QMessageBox.information(this, "Non-Premium Account", error);
\r
1798 // Check the file attachment to be sure it isn't over 25 mb
\r
1799 private boolean checkFileAttachmentSize(String url) {
\r
1800 String fileName = url.substring(8);
\r
1801 QFile resourceFile = new QFile(fileName);
\r
1802 resourceFile.open(new QIODevice.OpenMode(
\r
1803 QIODevice.OpenModeFlag.ReadOnly));
\r
1804 long size = resourceFile.size();
\r
1805 resourceFile.close();
\r
1806 size = size / 1024 / 1024;
\r
1807 if (size < 50 && Global.isPremium())
\r
1812 String error = "A file attachment may not exceed 25MB.";
\r
1813 QMessageBox.information(this, "Attachment Size", error);
\r
1818 @SuppressWarnings("unused")
\r
1819 private void createdChanged() {
\r
1820 QDateTime dt = new QDateTime();
\r
1821 dt.setDate(createdDate.date());
\r
1822 dt.setTime(createdTime.time());
\r
1823 noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);
\r
1827 @SuppressWarnings("unused")
\r
1828 private void alteredChanged() {
\r
1829 QDateTime dt = new QDateTime();
\r
1830 dt.setDate(alteredDate.date());
\r
1831 dt.setTime(alteredTime.time());
\r
1832 noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);
\r
1835 @SuppressWarnings("unused")
\r
1836 private void subjectDateTimeChanged() {
\r
1837 QDateTime dt = new QDateTime();
\r
1838 dt.setDate(subjectDate.date());
\r
1839 dt.setTime(subjectTime.time());
\r
1840 noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);
\r
1844 @SuppressWarnings("unused")
\r
1845 private void sourceUrlChanged() {
\r
1846 noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());
\r
1849 @SuppressWarnings("unused")
\r
1850 private void authorChanged() {
\r
1851 noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());
\r
1854 // ************************************************************
\r
1855 // * User chose to save an attachment. Pares out the request *
\r
1856 // * into a guid & file. Save the result. *
\r
1857 // ************************************************************
\r
1858 public void downloadAttachment(QNetworkRequest request) {
\r
1860 QFileDialog fd = new QFileDialog(this);
\r
1861 fd.setFileMode(FileMode.AnyFile);
\r
1862 fd.setConfirmOverwrite(true);
\r
1863 fd.setWindowTitle("Save File");
\r
1864 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
1865 fd.setDirectory(System.getProperty("user.home"));
\r
1866 String name = request.url().toString();
\r
1868 int pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
1870 guid = name.substring(0, pos).replace("nnres://", "");
\r
1871 name = name.substring(pos +Global.attachmentNameDelimeter.length());
\r
1872 fd.selectFile(name);
\r
1873 pos = name.lastIndexOf('.');
\r
1875 String mimeType = "(*." + name.substring(pos + 1)
\r
1876 + ");; All Files (*)";
\r
1877 fd.setFilter(tr(mimeType));
\r
1882 guid = guid.replace("nnres://", "").replace(Global.currentDir.replace("\\","/")+"res/", "");
\r
1883 pos = guid.lastIndexOf('.');
\r
1885 guid = guid.substring(0,pos);
\r
1886 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
1887 name = name.replace('\\', '/');
\r
1888 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
1889 QFile saveFile = new QFile(fd.selectedFiles().get(0));
\r
1890 QFile.OpenMode mode = new QFile.OpenMode();
\r
1891 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
1892 saveFile.open(mode);
\r
1893 QDataStream saveOut = new QDataStream(saveFile);
\r
1894 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
1895 saveOut.writeBytes(binData.toByteArray());
\r
1902 // ************************************************************
\r
1903 // * User chose to save an attachment. Pares out the request *
\r
1904 // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!
\r
1905 // ************************************************************
\r
1906 public void downloadImage(QNetworkRequest request) {
\r
1907 QFileDialog fd = new QFileDialog(this);
\r
1908 fd.setFileMode(FileMode.AnyFile);
\r
1909 fd.setConfirmOverwrite(true);
\r
1910 fd.setWindowTitle("Save File");
\r
1911 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
1912 fd.setDirectory(System.getProperty("user.home"));
\r
1913 String name = request.url().toString();
\r
1914 name = name.replace("nnres://", "");
\r
1915 String dPath = Global.getDirectoryPath() + "res/";
\r
1916 dPath = dPath.replace('\\', '/');
\r
1917 name = name.replace(dPath, "");
\r
1918 int pos = name.lastIndexOf('.');
\r
1919 String guid = name;
\r
1921 String mimeType = "(*." + name.substring(pos + 1)
\r
1922 + ");; All Files (*)";
\r
1923 fd.setFilter(tr(mimeType));
\r
1924 guid = guid.substring(0,pos);
\r
1926 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
1928 guid = name.substring(0, pos);
\r
1929 fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));
\r
1931 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
1932 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
1933 String fileName = fd.selectedFiles().get(0);
\r
1934 QFile saveFile = new QFile(fileName);
\r
1935 QFile.OpenMode mode = new QFile.OpenMode();
\r
1936 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
1937 saveFile.open(mode);
\r
1938 QDataStream saveOut = new QDataStream(saveFile);
\r
1939 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
1940 saveOut.writeBytes(binData.toByteArray());
\r
1946 // *************************************************************
\r
1947 // * decrypt any hidden text. We could do an XML parse, but
\r
1948 // * it is quicker here just to scan for an <img tag & do the fix
\r
1949 // * the manual way
\r
1950 // *************************************************************
\r
1951 private void removeEncryption(String id, String plainText, boolean permanent, String slot) {
\r
1953 plainText = " <en-crypt-temp slot=\""+slot +"\">" +plainText+"</en-crypt-temp> ";
\r
1956 String html = browser.page().mainFrame().toHtml();
\r
1957 String text = html;
\r
1958 int imagePos = html.indexOf("<img");
\r
1960 for ( ;imagePos>0; ) {
\r
1961 // Find the end tag
\r
1962 endPos = text.indexOf(">", imagePos);
\r
1963 String tag = text.substring(imagePos-1,endPos);
\r
1964 if (tag.indexOf("id=\""+id+"\"") > -1) {
\r
1965 text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);
\r
1967 browser.setContent(new QByteArray(text));
\r
1970 imagePos = text.indexOf("<img", imagePos+1);
\r
1975 //****************************************************************
\r
1976 //* Focus shortcuts
\r
1977 //****************************************************************
\r
1978 @SuppressWarnings("unused")
\r
1979 private void focusTitle() {
\r
1980 titleLabel.setFocus();
\r
1982 @SuppressWarnings("unused")
\r
1983 private void focusTag() {
\r
1984 tagEdit.setFocus();
\r
1986 @SuppressWarnings("unused")
\r
1987 private void focusNote() {
\r
1988 browser.setFocus();
\r
1990 @SuppressWarnings("unused")
\r
1991 private void focusAuthor() {
\r
1992 authorLabel.setFocus();
\r
1994 @SuppressWarnings("unused")
\r
1995 private void focusUrl() {
\r
1996 urlLabel.setFocus();
\r
2000 //*****************************************************************
\r
2001 //* Set the document background color
\r
2002 //*****************************************************************
\r
2003 public void setBackgroundColor(String color) {
\r
2004 String js = "function changeBackground(color) {"
\r
2005 +"document.body.style.background = color;"
\r
2007 +"changeBackground('" +color+"');";
\r
2008 browser.page().mainFrame().evaluateJavaScript(js);
\r
2013 //****************************************************************
\r
2014 //* MicroFocus changed
\r
2015 //****************************************************************
\r
2016 private void microFocusChanged() {
\r
2018 boldButton.setDown(false);
\r
2019 italicButton.setDown(false);
\r
2020 underlineButton.setDown(false);
\r
2021 browser.openAction.setEnabled(false);
\r
2022 browser.downloadAttachment.setEnabled(false);
\r
2023 browser.downloadImage.setEnabled(false);
\r
2024 browser.rotateImageLeft.setEnabled(false);
\r
2025 browser.rotateImageRight.setEnabled(false);
\r
2026 browser.insertTableAction.setEnabled(true);
\r
2027 browser.insertTableRowAction.setEnabled(false);
\r
2028 browser.deleteTableRowAction.setEnabled(false);
\r
2029 browser.insertLinkAction.setText("Insert Hyperlink");
\r
2030 currentHyperlink ="";
\r
2031 insideList = false;
\r
2032 forceTextPaste = false;
\r
2034 String js = new String( "function getCursorPos() {"
\r
2036 +"if (window.getSelection) {"
\r
2037 +" var selObj = window.getSelection();"
\r
2038 +" var selRange = selObj.getRangeAt(0);"
\r
2039 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2040 +" while(workingNode != null) { "
\r
2041 // +" window.jambi.printNode(workingNode.nodeName);"
\r
2042 +" if (workingNode.nodeName=='EN-CRYPT-TEMP') window.jambi.forceTextPaste();"
\r
2043 +" if (workingNode.nodeName=='B') window.jambi.boldActive();"
\r
2044 +" if (workingNode.nodeName=='I') window.jambi.italicActive();"
\r
2045 +" if (workingNode.nodeName=='U') window.jambi.underlineActive();"
\r
2046 +" if (workingNode.nodeName=='UL') window.jambi.setInsideList();"
\r
2047 +" if (workingNode.nodeName=='OL') window.jambi.setInsideList();"
\r
2048 +" if (workingNode.nodeName=='LI') window.jambi.setInsideList();"
\r
2049 +" if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"
\r
2050 +" 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
2051 +" if (workingNode.nodeName=='SPAN') {"
\r
2052 +" if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"
\r
2054 +" workingNode = workingNode.parentNode;"
\r
2057 +"} getCursorPos();");
\r
2058 browser.page().mainFrame().evaluateJavaScript(js);
\r
2061 public void printNode(String n) {
\r
2062 System.out.println("Node Vaule: " +n);
\r
2066 //****************************************************************
\r
2067 //* Insert a table row
\r
2068 //****************************************************************
\r
2069 public void insertTableRow() {
\r
2071 String js = new String( "function insertTableRow() {"
\r
2072 +" var selObj = window.getSelection();"
\r
2073 +" var selRange = selObj.getRangeAt(0);"
\r
2074 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2075 +" var cellCount = 0;"
\r
2076 +" while(workingNode != null) { "
\r
2077 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2078 +" row = document.createElement('TR');"
\r
2079 +" var nodes = workingNode.getElementsByTagName('td');"
\r
2080 +" for (j=0; j<nodes.length; j=j+1) {"
\r
2081 +" cell = document.createElement('TD');"
\r
2082 +" cell.innerHTML=' ';"
\r
2083 +" row.appendChild(cell);"
\r
2085 +" workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"
\r
2088 +" workingNode = workingNode.parentNode;"
\r
2090 +"} insertTableRow();");
\r
2091 browser.page().mainFrame().evaluateJavaScript(js);
\r
2094 //****************************************************************
\r
2095 //* Insert a table row
\r
2096 //****************************************************************
\r
2097 public void deleteTableRow() {
\r
2099 String js = new String( "function deleteTableRow() {"
\r
2100 +" var selObj = window.getSelection();"
\r
2101 +" var selRange = selObj.getRangeAt(0);"
\r
2102 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2103 +" var cellCount = 0;"
\r
2104 +" while(workingNode != null) { "
\r
2105 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2106 +" workingNode.parentNode.removeChild(workingNode);"
\r
2109 +" workingNode = workingNode.parentNode;"
\r
2111 +"} deleteTableRow();");
\r
2112 browser.page().mainFrame().evaluateJavaScript(js);
\r
2115 public void setInsideTable() {
\r
2116 browser.insertTableRowAction.setEnabled(true);
\r
2117 browser.deleteTableRowAction.setEnabled(true);
\r
2118 browser.insertTableAction.setEnabled(false);
\r
2119 browser.encryptAction.setEnabled(false);
\r
2122 public void setInsideLink(String link) {
\r
2123 browser.insertLinkAction.setText("Edit Hyperlink");
\r
2124 currentHyperlink = link;
\r
2127 public void italicActive() {
\r
2128 italicButton.setDown(true);
\r
2130 public void boldActive() {
\r
2131 boldButton.setDown(true);
\r
2133 public void underlineActive() {
\r
2134 underlineButton.setDown(true);
\r
2136 public void forceTextPaste() {
\r
2137 forceTextPaste = true;
\r
2139 public void imageContextMenu(String f) {
\r
2140 browser.downloadImage.setEnabled(true);
\r
2141 browser.rotateImageRight.setEnabled(true);
\r
2142 browser.rotateImageLeft.setEnabled(true);
\r
2143 browser.openAction.setEnabled(true);
\r
2146 public void rotateImageRight() {
\r
2147 QWebSettings.setMaximumPagesInCache(0);
\r
2148 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2149 QImage image = new QImage(selectedFile);
\r
2150 QMatrix matrix = new QMatrix();
\r
2151 matrix.rotate( 90.0 );
\r
2152 image = image.transformed(matrix);
\r
2153 image.save(selectedFile);
\r
2154 QWebSettings.setMaximumPagesInCache(0);
\r
2155 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2156 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2159 // resourceSignal.contentChanged.emit(selectedFile);
\r
2162 public void rotateImageLeft() {
\r
2163 QImage image = new QImage(selectedFile);
\r
2164 QMatrix matrix = new QMatrix();
\r
2165 matrix.rotate( -90.0 );
\r
2166 image = image.transformed(matrix);
\r
2167 image.save(selectedFile);
\r
2168 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2171 // resourceSignal.contentChanged.emit(selectedFile);
\r
2173 public void resourceContextMenu(String f) {
\r
2174 browser.downloadAttachment.setEnabled(true);
\r
2175 browser.openAction.setEnabled(true);
\r
2180 //****************************************************************
\r
2181 //* Apply CSS style to specified word
\r
2182 //****************************************************************
\r
2183 /* public void applyStyleToWords(String word, String style) {
\r
2184 QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");
\r
2185 script.open(OpenModeFlag.ReadOnly);
\r
2186 String s = script.readAll().toString();
\r
2187 String js = new String(s +" findit('"+word+"', '"+style+"');");
\r
2188 browser.page().mainFrame().evaluateJavaScript(js);
\r
2189 System.out.println(getContent());
\r
2192 //****************************************************************
\r
2193 //* Someone tried to paste a resource between notes, so we need *
\r
2194 //* to do some special handling. *
\r
2195 //****************************************************************
\r
2196 private String fixInternotePaste(String text) {
\r
2197 logger.log(logger.EXTREME, "Fixing internote paste");
\r
2198 String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");
\r
2199 return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");
\r
2201 private String fixInternotePasteSearch(String text, String type, String locTag) {
\r
2203 // First, let's fix the images.
\r
2204 int startPos = text.indexOf(type);
\r
2206 for (; startPos>=0;) {
\r
2207 endPos = text.indexOf(">", startPos+1);
\r
2208 String segment = text.substring(startPos, endPos);
\r
2209 if (segment.indexOf("en-tag") > -1) {
\r
2210 String newSegment = segment;
\r
2212 int guidStartPos = segment.indexOf("guid=\"");
\r
2213 int guidEndPos = segment.indexOf("\"", guidStartPos+7);
\r
2214 String guid = segment.substring(guidStartPos+6,guidEndPos);
\r
2216 Calendar currentTime = new GregorianCalendar();
\r
2217 Long l = new Long(currentTime.getTimeInMillis());
\r
2218 long prevTime = l;
\r
2219 while (l==prevTime) {
\r
2220 currentTime = new GregorianCalendar();
\r
2221 l= new Long(currentTime.getTimeInMillis());
\r
2224 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2227 String randint = new String(Long.toString(l));
\r
2228 String extension = null;
\r
2229 if (r.getMime()!= null) {
\r
2230 extension = r.getMime().toLowerCase();
\r
2231 if (extension.indexOf("/")>-1)
\r
2232 extension = extension.substring(extension.indexOf("/")+1);
\r
2234 String newFile = randint;
\r
2235 if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")
\r
2236 if (!locTag.startsWith("src"))
\r
2237 newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();
\r
2238 r.setNoteGuid(currentNote.getGuid());
\r
2240 r.setGuid(randint);
\r
2241 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
2242 QFile f = new QFile(Global.getDirectoryPath() +"res/" +newFile);
\r
2243 QByteArray bin = new QByteArray(r.getData().getBody());
\r
2244 f.open(QFile.OpenModeFlag.WriteOnly);
\r
2247 newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);
\r
2248 currentNote.getResources().add(r);
\r
2250 int startSrcPos = newSegment.indexOf(locTag);
\r
2251 int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);
\r
2253 if (locTag.startsWith("src")) {
\r
2254 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2255 newSegment = newSegment.replace(source, Global.getDirectoryPath().replace("\\", "/")+"res/"+newFile);
\r
2257 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2258 newSegment = newSegment.replace(source, newFile);
\r
2261 text = text.substring(0,startPos) + newSegment + text.substring(endPos);
\r
2263 startPos = text.indexOf(type, startPos+1);
\r
2269 public void nextPage(String file) {
\r
2270 logger.log(logger.EXTREME, "Starting nextPage()");
\r
2272 Integer pageNumber;
\r
2273 if (previewPageList.containsKey(file))
\r
2274 pageNumber = previewPageList.get(file)+1;
\r
2277 previewPageList.remove(file);
\r
2278 previewPageList.put(file, pageNumber);
\r
2279 PDFPreview pdfPreview = new PDFPreview();
\r
2280 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2281 if (goodPreview) {
\r
2283 // String html = getContent();
\r
2284 QWebSettings.setMaximumPagesInCache(0);
\r
2285 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2286 // browser.setContent(new QByteArray());
\r
2287 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2289 // browser.setContent(new QByteArray(html));
\r
2290 // browser.triggerPageAction(WebAction.Reload);
\r
2291 // pdfMouseOver(selectedFile);
\r
2295 public void previousPage(String file) {
\r
2296 logger.log(logger.EXTREME, "Starting previousPage()");
\r
2298 Integer pageNumber;
\r
2299 if (previewPageList.containsKey(file))
\r
2300 pageNumber = previewPageList.get(file)-1;
\r
2303 previewPageList.remove(file);
\r
2304 previewPageList.put(file, pageNumber);
\r
2305 PDFPreview pdfPreview = new PDFPreview();
\r
2306 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2307 if (goodPreview) {
\r
2309 // String html = getContent();
\r
2310 QWebSettings.setMaximumPagesInCache(0);
\r
2311 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2312 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2314 // browser.setContent(new QByteArray(html));
\r
2315 // browser.triggerPageAction(WebAction.Reload);
\r
2319 /* public void pdfMouseOver(String name) {
\r
2321 if (previewPageList.containsKey(selectedFile))
\r
2322 pageNumber = previewPageList.get(selectedFile)+1;
\r
2326 if (pageNumber <= 1)
\r
2327 browser.previousPageAction.setEnabled(false);
\r
2329 browser.previousPageAction.setEnabled(true);
\r
2331 PDFPreview pdf = new PDFPreview();
\r
2332 int totalPages = pdf.getPageCount(name);
\r
2333 if (previewPageList.containsKey(selectedFile))
\r
2334 pageNumber = previewPageList.get(selectedFile)+1;
\r
2337 if (totalPages > pageNumber)
\r
2338 browser.nextPageAction.setEnabled(true);
\r
2340 browser.nextPageAction.setEnabled(false);
\r
2344 public void pdfMouseOut() {
\r
2345 // browser.nextPageAction.setVisible(false);
\r
2346 // browser.previousPageAction.setVisible(false);
\r