OSDN Git Service

37e143a2e162efdb64d7aeb9f0ff5a16cd50d387
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / gui / BrowserWindow.java
1 /*\r
2  * This file is part of NeverNote \r
3  * Copyright 2009 Randy Baumgarte\r
4  * \r
5  * This file may be licensed under the terms of of the\r
6  * GNU General Public License Version 2 (the ``GPL'').\r
7  *\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
12  *\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
17  *\r
18  */\r
19 \r
20 package cx.fbn.nevernote.gui;\r
21 \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.Collections;\r
32 import java.util.Date;\r
33 import java.util.GregorianCalendar;\r
34 import java.util.HashMap;\r
35 import java.util.List;\r
36 \r
37 import com.evernote.edam.limits.Constants;\r
38 import com.evernote.edam.type.Data;\r
39 import com.evernote.edam.type.Note;\r
40 import com.evernote.edam.type.Notebook;\r
41 import com.evernote.edam.type.Resource;\r
42 import com.evernote.edam.type.ResourceAttributes;\r
43 import com.evernote.edam.type.Tag;\r
44 import com.trolltech.qt.core.QByteArray;\r
45 import com.trolltech.qt.core.QDataStream;\r
46 import com.trolltech.qt.core.QDateTime;\r
47 import com.trolltech.qt.core.QEvent;\r
48 import com.trolltech.qt.core.QFile;\r
49 import com.trolltech.qt.core.QFileSystemWatcher;\r
50 import com.trolltech.qt.core.QIODevice;\r
51 import com.trolltech.qt.core.QMimeData;\r
52 import com.trolltech.qt.core.QUrl;\r
53 import com.trolltech.qt.gui.QApplication;\r
54 import com.trolltech.qt.gui.QCalendarWidget;\r
55 import com.trolltech.qt.gui.QClipboard;\r
56 import com.trolltech.qt.gui.QColor;\r
57 import com.trolltech.qt.gui.QComboBox;\r
58 import com.trolltech.qt.gui.QDateEdit;\r
59 import com.trolltech.qt.gui.QDesktopServices;\r
60 import com.trolltech.qt.gui.QFileDialog;\r
61 import com.trolltech.qt.gui.QFileDialog.AcceptMode;\r
62 import com.trolltech.qt.gui.QFileDialog.FileMode;\r
63 import com.trolltech.qt.gui.QFontDatabase;\r
64 import com.trolltech.qt.gui.QFormLayout;\r
65 import com.trolltech.qt.gui.QGridLayout;\r
66 import com.trolltech.qt.gui.QHBoxLayout;\r
67 import com.trolltech.qt.gui.QIcon;\r
68 import com.trolltech.qt.gui.QImage;\r
69 import com.trolltech.qt.gui.QKeySequence;\r
70 import com.trolltech.qt.gui.QLabel;\r
71 import com.trolltech.qt.gui.QLineEdit;\r
72 import com.trolltech.qt.gui.QListWidgetItem;\r
73 import com.trolltech.qt.gui.QMatrix;\r
74 import com.trolltech.qt.gui.QMessageBox;\r
75 import com.trolltech.qt.gui.QPushButton;\r
76 import com.trolltech.qt.gui.QShortcut;\r
77 import com.trolltech.qt.gui.QTimeEdit;\r
78 import com.trolltech.qt.gui.QVBoxLayout;\r
79 import com.trolltech.qt.gui.QWidget;\r
80 import com.trolltech.qt.network.QNetworkRequest;\r
81 import com.trolltech.qt.webkit.QWebPage;\r
82 import com.trolltech.qt.webkit.QWebPage.WebAction;\r
83 import com.trolltech.qt.webkit.QWebSettings;\r
84 import com.trolltech.qt.webkit.QWebView;\r
85 \r
86 import cx.fbn.nevernote.Global;\r
87 import cx.fbn.nevernote.dialog.EnCryptDialog;\r
88 import cx.fbn.nevernote.dialog.EnDecryptDialog;\r
89 import cx.fbn.nevernote.dialog.GeoDialog;\r
90 import cx.fbn.nevernote.dialog.InsertLinkDialog;\r
91 import cx.fbn.nevernote.dialog.TableDialog;\r
92 import cx.fbn.nevernote.dialog.TagAssign;\r
93 import cx.fbn.nevernote.evernote.EnCrypt;\r
94 import cx.fbn.nevernote.signals.NoteResourceSignal;\r
95 import cx.fbn.nevernote.signals.NoteSignal;\r
96 import cx.fbn.nevernote.sql.DatabaseConnection;\r
97 import cx.fbn.nevernote.utilities.ApplicationLogger;\r
98 import cx.fbn.nevernote.utilities.FileUtils;\r
99 \r
100 public class BrowserWindow extends QWidget {\r
101 \r
102         public final QLineEdit titleLabel;\r
103         private final QLineEdit urlText;\r
104         private final QLabel authorLabel;\r
105         private final QLineEdit authorText;\r
106         private final QComboBox geoBox;\r
107         public final TagLineEdit tagEdit;\r
108         public final QLabel tagLabel;\r
109         private final QPushButton urlLabel;\r
110         private final QLabel alteredLabel;\r
111         private final QDateEdit alteredDate;\r
112         private final QTimeEdit alteredTime;\r
113         private final QDateEdit createdDate;\r
114         private final QTimeEdit createdTime;\r
115         private final QLabel subjectLabel;\r
116         private final QDateEdit subjectDate;\r
117         private final QTimeEdit subjectTime;\r
118         public final QComboBox notebookBox;\r
119         private final QLabel notebookLabel;\r
120         private final QLabel createdLabel;\r
121         public final QComboBox fontSize;\r
122         private boolean extendedOn;\r
123         public boolean buttonsVisible;\r
124         private final String iconPath = new String("classpath:cx/fbn/nevernote/icons/");\r
125         private final ContentView browser;\r
126         private List<Tag> allTags;\r
127         private List<String> currentTags;\r
128         public NoteSignal noteSignal;\r
129         private List<Notebook> notebookList;\r
130         private Note currentNote;\r
131         private String saveNoteTitle;\r
132         private String saveTagList;\r
133         private boolean insideList;\r
134 //      private String selectedText;\r
135         private final DatabaseConnection conn;\r
136         private final QCalendarWidget createdCalendarWidget;\r
137         private final QCalendarWidget alteredCalendarWidget;\r
138         private final QCalendarWidget subjectCalendarWidget;\r
139 \r
140         public final QPushButton undoButton;\r
141         public final QPushButton redoButton;\r
142         public final QPushButton cutButton;\r
143         public final QPushButton copyButton;\r
144         public final QPushButton pasteButton;\r
145         public final QPushButton boldButton;\r
146         public final QPushButton underlineButton;\r
147         public final QPushButton italicButton;\r
148         public final Signal0 focusLost;\r
149         public final NoteResourceSignal resourceSignal;\r
150 \r
151         public QPushButton rightAlignButton;\r
152         public QPushButton leftAlignButton;\r
153         public QPushButton centerAlignButton;\r
154 \r
155         public final QPushButton strikethroughButton;\r
156         public final QPushButton hlineButton;\r
157         public final QPushButton indentButton;\r
158         public final QPushButton outdentButton;\r
159         public final QPushButton bulletListButton;\r
160         public final QPushButton numberListButton;\r
161 \r
162         public final QShortcut focusTitleShortcut;\r
163         public final QShortcut focusTagShortcut;\r
164         public final QShortcut focusNoteShortcut;\r
165         public final QShortcut focusUrlShortcut;\r
166         public final QShortcut focusAuthorShortcut;\r
167         \r
168         public final QComboBox fontList;\r
169         public final QPushButton fontColor;\r
170         private final ColorMenu fontColorMenu;\r
171         public final QPushButton fontHilight;\r
172 //      public final ColorComboBox fontHilight;\r
173         private final ColorMenu fontHilightColorMenu;\r
174         public final QFileSystemWatcher fileWatcher;\r
175         public int cursorPosition;\r
176         private boolean forceTextPaste = false;\r
177         private String selectedFile;\r
178         private String currentHyperlink;\r
179         public boolean keepPDFNavigationHidden;\r
180         private final ApplicationLogger logger;\r
181         \r
182         private final HashMap<String,Integer> previewPageList; \r
183         \r
184         \r
185         public BrowserWindow(DatabaseConnection c) {\r
186                 logger = new ApplicationLogger("browser.log");\r
187                 logger.log(logger.HIGH, "Setting up browser");\r
188                 \r
189                 fileWatcher = new QFileSystemWatcher();\r
190 //              fileWatcher.fileChanged.connect(this, "fileChanged(String)");\r
191                 noteSignal = new NoteSignal();\r
192                 titleLabel = new QLineEdit();\r
193                 titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX);\r
194                 urlText = new QLineEdit();\r
195                 authorText = new QLineEdit();\r
196                 geoBox = new QComboBox();\r
197                 urlLabel = new QPushButton();\r
198                 urlLabel.clicked.connect(this, "sourceUrlClicked()");\r
199                 authorLabel = new QLabel();\r
200                 conn = c;\r
201                 \r
202                 focusLost = new Signal0();\r
203 \r
204                 tagEdit = new TagLineEdit(allTags);\r
205                 tagLabel = new QLabel("Tags:");\r
206                 tagEdit.focusLost.connect(this, "modifyTagsTyping()");\r
207 \r
208                 createdCalendarWidget = new QCalendarWidget();\r
209                 createdDate = new QDateEdit();\r
210                 createdDate.setDisplayFormat(Global.getDateFormat());\r
211                 createdDate.setCalendarPopup(true);\r
212                 createdDate.setCalendarWidget(createdCalendarWidget);\r
213                 createdTime = new QTimeEdit();\r
214                 createdDate.dateChanged.connect(this, "createdChanged()");\r
215                 createdTime.timeChanged.connect(this, "createdChanged()");\r
216 \r
217                 alteredCalendarWidget = new QCalendarWidget();\r
218                 alteredDate = new QDateEdit();\r
219                 alteredDate.setDisplayFormat(Global.getDateFormat());\r
220                 alteredDate.setCalendarPopup(true);\r
221                 alteredDate.setCalendarWidget(alteredCalendarWidget);\r
222                 alteredTime = new QTimeEdit();\r
223                 alteredLabel = new QLabel("Altered:");\r
224                 alteredDate.dateChanged.connect(this, "alteredChanged()");\r
225                 alteredTime.timeChanged.connect(this, "alteredChanged()");\r
226 \r
227                 subjectCalendarWidget = new QCalendarWidget();\r
228                 subjectDate = new QDateEdit();\r
229                 subjectDate.setDisplayFormat(Global.getDateFormat());\r
230                 subjectDate.setCalendarPopup(true);\r
231                 subjectDate.setCalendarWidget(subjectCalendarWidget);\r
232                 subjectTime = new QTimeEdit();\r
233                 subjectLabel = new QLabel(tr("Subject Date:"));\r
234                 subjectDate.dateChanged.connect(this, "subjectDateTimeChanged()");\r
235                 subjectTime.timeChanged.connect(this, "subjectDateTimeChanged()");\r
236                 authorText.textChanged.connect(this, "authorChanged()");\r
237                 urlText.textChanged.connect(this, "sourceUrlChanged()");\r
238 \r
239                 notebookBox = new QComboBox();\r
240                 notebookLabel = new QLabel(tr("Notebook"));\r
241                 createdLabel = new QLabel(tr("Created:"));\r
242                 // selectedText = new String();\r
243 \r
244                 urlLabel.setVisible(false);\r
245                 urlText.setVisible(false);\r
246                 authorLabel.setVisible(false);\r
247                 \r
248                 geoBox.setVisible(false);\r
249                 geoBox.addItem(new QIcon(iconPath+"globe.png"), "");\r
250                 geoBox.addItem(new String(tr("Set")));\r
251                 geoBox.addItem(new String(tr("Clear")));\r
252                 geoBox.addItem(new String(tr("View On Map")));\r
253                 geoBox.activated.connect(this, "geoBoxChanged()");\r
254                 \r
255                 authorText.setVisible(false);\r
256                 createdDate.setVisible(false);\r
257                 alteredLabel.setVisible(false);\r
258                 //notebookBox.setVisible(false);\r
259                 notebookLabel.setVisible(false);\r
260                 createdLabel.setVisible(false);\r
261                 createdTime.setVisible(false);\r
262                 alteredDate.setVisible(false);\r
263                 alteredTime.setVisible(false);\r
264                 subjectLabel.setVisible(false);\r
265                 subjectDate.setVisible(false);\r
266                 subjectTime.setVisible(false);\r
267                 extendedOn = false;\r
268                 buttonsVisible = true;\r
269                 setAcceptDrops(true);\r
270 \r
271                 browser = new ContentView(this);\r
272                 browser.page().setLinkDelegationPolicy(\r
273                                 QWebPage.LinkDelegationPolicy.DelegateAllLinks);\r
274                 browser.linkClicked.connect(this, "linkClicked(QUrl)");\r
275                 currentHyperlink = "";\r
276                 \r
277                 QVBoxLayout v = new QVBoxLayout();\r
278                 QFormLayout notebookLayout = new QFormLayout();\r
279                 QGridLayout dateLayout = new QGridLayout();\r
280                 titleLabel.setReadOnly(false);\r
281                 titleLabel.editingFinished.connect(this, "titleEdited()");\r
282                 browser.page().contentsChanged.connect(this, "contentChanged()");\r
283                 browser.page().selectionChanged.connect(this, "selectionChanged()");\r
284                 browser.page().mainFrame().javaScriptWindowObjectCleared.connect(this,\r
285                                 "exposeToJavascript()");\r
286 \r
287                 notebookBox.activated.connect(this, "notebookChanged()");\r
288                 resourceSignal = new NoteResourceSignal();\r
289                 \r
290                 QHBoxLayout tagLayout = new QHBoxLayout();\r
291                 v.addWidget(titleLabel, 0);\r
292                 notebookLayout.addRow(notebookLabel, notebookBox);\r
293                 tagLayout.addLayout(notebookLayout, 0);\r
294                 tagLayout.stretch(4);\r
295                 tagLayout.addWidget(tagLabel, 0);\r
296                 tagLayout.addWidget(tagEdit, 1);\r
297                 v.addLayout(tagLayout);\r
298 \r
299                 QHBoxLayout urlLayout = new QHBoxLayout();\r
300                 urlLayout.addWidget(urlLabel, 0);\r
301                 urlLayout.addWidget(urlText, 0);\r
302                 v.addLayout(urlLayout);\r
303 \r
304                 QHBoxLayout authorLayout = new QHBoxLayout();\r
305                 authorLayout.addWidget(authorLabel, 0);\r
306                 authorLayout.addWidget(authorText, 0);\r
307                 authorLayout.addWidget(geoBox);\r
308                 v.addLayout(authorLayout);\r
309 \r
310                 dateLayout.addWidget(createdLabel, 0, 0);\r
311                 dateLayout.addWidget(createdDate, 0, 1);\r
312                 dateLayout.addWidget(createdTime, 0, 2);\r
313                 dateLayout.setColumnStretch(9, 100);\r
314                 dateLayout.addWidget(alteredLabel, 0, 3);\r
315                 dateLayout.addWidget(alteredDate, 0, 4);\r
316                 dateLayout.addWidget(alteredTime, 0, 5);\r
317                 dateLayout.addWidget(subjectLabel, 0, 6);\r
318                 dateLayout.addWidget(subjectDate, 0, 7);\r
319                 dateLayout.addWidget(subjectTime, 0, 8);\r
320                 v.addLayout(dateLayout, 0);\r
321 \r
322                 undoButton = newEditorButton("undo", tr("Undo Change"));\r
323                 redoButton = newEditorButton("redo", tr("Redo Change"));\r
324                 cutButton = newEditorButton("cut", tr("Cut"));\r
325                 copyButton = newEditorButton("copy", tr("Copy"));\r
326                 pasteButton = newEditorButton("paste", tr("Paste"));\r
327                 boldButton = newEditorButton("bold", tr("Bold"));\r
328                 underlineButton = newEditorButton("underline", tr("Underline"));\r
329                 italicButton = newEditorButton("italic", tr("Italic"));\r
330 \r
331                 rightAlignButton = newEditorButton("justifyRight", tr("Right Align"));\r
332                 leftAlignButton = newEditorButton("justifyLeft", tr("Left Align"));\r
333                 centerAlignButton = newEditorButton("justifyCenter", tr("Center Align"));\r
334 \r
335                 strikethroughButton = newEditorButton("strikethrough", tr("Strikethrough"));\r
336                 hlineButton = newEditorButton("hline", tr("Insert Horizontal Line"));\r
337                 indentButton = newEditorButton("indent", tr("Shift Right"));\r
338                 outdentButton = newEditorButton("outdent", tr("Shift Left"));\r
339                 bulletListButton = newEditorButton("bulletList", tr("Bullet List"));\r
340                 numberListButton = newEditorButton("numberList", tr("Number List"));\r
341 \r
342 \r
343                 QHBoxLayout buttonLayout;\r
344                 buttonLayout = new QHBoxLayout();\r
345                 buttonLayout.setSpacing(0);\r
346                 v.addLayout(buttonLayout);\r
347                 \r
348                 buttonLayout.addWidget(undoButton);\r
349                 buttonLayout.addWidget(redoButton);\r
350 \r
351                 buttonLayout.addWidget(newSeparator(), 0);\r
352                 buttonLayout.addWidget(cutButton);\r
353                 buttonLayout.addWidget(copyButton);\r
354                 buttonLayout.addWidget(pasteButton);\r
355 \r
356                 buttonLayout.addWidget(newSeparator(), 0);\r
357                 buttonLayout.addWidget(boldButton);\r
358                 buttonLayout.addWidget(italicButton);\r
359                 buttonLayout.addWidget(underlineButton);\r
360                 buttonLayout.addWidget(strikethroughButton);\r
361                 \r
362                 buttonLayout.addWidget(newSeparator(), 0);\r
363                 buttonLayout.addWidget(leftAlignButton);\r
364                 buttonLayout.addWidget(centerAlignButton);\r
365                 buttonLayout.addWidget(rightAlignButton);\r
366 \r
367                 buttonLayout.addWidget(newSeparator(), 0);\r
368                 buttonLayout.addWidget(hlineButton);\r
369 \r
370                 buttonLayout.addWidget(indentButton);\r
371                 buttonLayout.addWidget(outdentButton);\r
372                 buttonLayout.addWidget(bulletListButton);\r
373                 buttonLayout.addWidget(numberListButton);\r
374 \r
375                 // Setup the font & font size combo boxes\r
376                 buttonLayout.addWidget(newSeparator(), 0);\r
377                 fontList = new QComboBox();\r
378                 fontSize = new QComboBox();\r
379                 fontList.setToolTip("Font");\r
380                 fontSize.setToolTip("Font Size");\r
381                 fontList.activated.connect(this, "fontChanged(String)");\r
382                 fontSize.activated.connect(this, "fontSizeChanged(String)");\r
383                 buttonLayout.addWidget(fontList, 0);\r
384                 buttonLayout.addWidget(fontSize, 0);\r
385                 QFontDatabase fonts = new QFontDatabase();\r
386                 List<String> fontFamilies = fonts.families();\r
387                 for (int i = 0; i < fontFamilies.size(); i++) {\r
388                         fontList.addItem(fontFamilies.get(i));\r
389                         if (i == 0) {\r
390                                 loadFontSize(fontFamilies.get(i));\r
391                         }\r
392                 }\r
393 \r
394                 buttonLayout.addWidget(newSeparator(), 0);\r
395                 fontColor = newEditorButton("fontColor", tr("Font Color"));\r
396                 fontColorMenu = new ColorMenu(this);\r
397                 fontColor.setMenu(fontColorMenu.getMenu());\r
398                 fontColorMenu.getMenu().triggered.connect(this, "fontColorClicked()");\r
399                 buttonLayout.addWidget(fontColor);\r
400                 fontHilight = newEditorButton("fontHilight", tr("Font Hilight Color"));\r
401                 fontHilightColorMenu = new ColorMenu(this);\r
402                 fontHilight.setMenu(fontHilightColorMenu.getMenu());\r
403                 fontHilightColorMenu.getMenu().triggered.connect(this, "fontHilightClicked()");\r
404                 buttonLayout.addWidget(fontHilight);\r
405 \r
406                 buttonLayout.addWidget(new QLabel(), 1);\r
407                 v.addWidget(browser, 1);\r
408 //              v.addLayout(buttonLayout,0);\r
409                 setLayout(v);\r
410 \r
411                 browser.downloadAttachmentRequested.connect(this,\r
412                                 "downloadAttachment(QNetworkRequest)");\r
413                 browser.downloadImageRequested.connect(this,\r
414                                 "downloadImage(QNetworkRequest)");\r
415                 setTabOrder(notebookBox, tagEdit);\r
416                 setTabOrder(tagEdit, browser);\r
417                 \r
418                 focusNoteShortcut = new QShortcut(this);\r
419                 setupShortcut(focusNoteShortcut, "Focus_Note");\r
420                 focusNoteShortcut.activated.connect(this, "focusNote()");\r
421                 focusTitleShortcut = new QShortcut(this);\r
422                 setupShortcut(focusTitleShortcut, "Focus_Title");\r
423                 focusTitleShortcut.activated.connect(this, "focusTitle()");\r
424                 focusTagShortcut = new QShortcut(this);\r
425                 setupShortcut(focusTagShortcut, "Focus_Tag");\r
426                 focusTagShortcut.activated.connect(this, "focusTag()");\r
427                 focusAuthorShortcut = new QShortcut(this);\r
428                 setupShortcut(focusAuthorShortcut, "Focus_Author");\r
429                 focusAuthorShortcut.activated.connect(this, "focusAuthor()");\r
430                 focusUrlShortcut = new QShortcut(this);\r
431                 setupShortcut(focusUrlShortcut, "Focus_Url");\r
432                 focusUrlShortcut.activated.connect(this, "focusUrl()");\r
433                 \r
434                 browser.page().mainFrame().setTextSizeMultiplier(Global.getTextSizeMultiplier());\r
435                 browser.page().mainFrame().setZoomFactor(Global.getZoomFactor());\r
436                 \r
437                  previewPageList = new HashMap<String,Integer>();\r
438                 \r
439                 browser.page().microFocusChanged.connect(this, "microFocusChanged()");\r
440                 logger.log(logger.HIGH, "Browser setup complete");\r
441         }\r
442 \r
443         \r
444         private void setupShortcut(QShortcut action, String text) {\r
445                 if (!Global.shortcutKeys.containsAction(text))\r
446                         return;\r
447                 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));\r
448         }\r
449         \r
450         \r
451 \r
452         \r
453         // Getter for the QWebView\r
454         public QWebView getBrowser() {\r
455                 return browser;\r
456         }\r
457 \r
458         // Block signals while loading data or things are flagged as dirty by\r
459         // mistake\r
460         public void loadingData(boolean val) {\r
461                 logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val);\r
462                 notebookBox.blockSignals(val);\r
463                 browser.page().blockSignals(val);\r
464                 browser.page().mainFrame().blockSignals(val);\r
465                 titleLabel.blockSignals(val);\r
466                 alteredDate.blockSignals(val);\r
467                 alteredTime.blockSignals(val);\r
468                 createdTime.blockSignals(val);\r
469                 createdDate.blockSignals(val);\r
470                 subjectDate.blockSignals(val);\r
471                 subjectTime.blockSignals(val);\r
472                 urlText.blockSignals(val);\r
473                 authorText.blockSignals(val);\r
474                 if (!val)\r
475                         exposeToJavascript();\r
476                 logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val);\r
477         }\r
478 \r
479         // Enable/disable\r
480         public void setReadOnly(boolean v) {\r
481                 setEnabled(true);\r
482                 titleLabel.setEnabled(!v);\r
483                 notebookBox.setEnabled(!v);\r
484                 tagEdit.setEnabled(!v);\r
485                 authorLabel.setEnabled(!v);\r
486                 geoBox.setEnabled(!v);\r
487                 urlText.setEnabled(!v);\r
488                 createdDate.setEnabled(!v);\r
489                 subjectDate.setEnabled(!v);\r
490                 alteredDate.setEnabled(!v);\r
491                 getBrowser().setEnabled(true);\r
492         }\r
493         \r
494         // expose this class to Javascript on the web page\r
495         private void exposeToJavascript() {\r
496                 browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this);\r
497         }\r
498 \r
499         // Custom event queue\r
500         @Override\r
501         public boolean event(QEvent e) {\r
502                 if (e.type().equals(QEvent.Type.FocusOut)) {\r
503                         logger.log(logger.EXTREME, "Focus lost");\r
504                         focusLost.emit();\r
505                 }\r
506                 return super.event(e);\r
507         }\r
508 \r
509         // clear out browser\r
510         public void clear() {\r
511                 logger.log(logger.EXTREME, "Entering BrowserWindow.clear()");\r
512                 setNote(null);\r
513                 browser.setContent(new QByteArray());\r
514                 tagEdit.setText("");\r
515                 tagEdit.tagCompleter.reset();\r
516                 urlLabel.setText(tr("Source URL:"));\r
517                 titleLabel.setText("");\r
518                 logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()");\r
519         }\r
520 \r
521         // get/set current note\r
522         public void setNote(Note n) {\r
523                 currentNote = n;\r
524                 if (n == null)\r
525                         n = new Note();\r
526                 saveNoteTitle = n.getTitle();\r
527 \r
528         }\r
529 \r
530         public Note getNote() {\r
531                 return currentNote;\r
532         }\r
533 \r
534         // New Editor Button\r
535         private QPushButton newEditorButton(String name, String toolTip) {\r
536                 QPushButton button = new QPushButton();\r
537                 QIcon icon = new QIcon(iconPath + name + ".gif");\r
538                 button.setIcon(icon);\r
539                 button.setToolTip(toolTip);\r
540                 button.clicked.connect(this, name + "Clicked()");\r
541                 return button;\r
542         }\r
543 \r
544         // New Separator\r
545         private QLabel newSeparator() {\r
546                 return new QLabel("   ");\r
547         }\r
548 \r
549         // Set the title in the window\r
550         public void setTitle(String t) {\r
551                 titleLabel.setText(t);\r
552                 saveNoteTitle = t;\r
553                 checkNoteTitle();\r
554         }\r
555 \r
556         // Return the current text title\r
557         public String getTitle() {\r
558                 return titleLabel.text();\r
559         }\r
560 \r
561         // Set the tag name string\r
562         public void setTag(String t) {\r
563                 saveTagList = t;\r
564                 tagEdit.setText(t);\r
565                 tagEdit.tagCompleter.reset();\r
566         }\r
567 \r
568         // Set the source URL\r
569         public void setUrl(String t) {\r
570                 urlLabel.setText(tr("Source URL:\t"));\r
571                 urlText.setText(t);\r
572         }\r
573 \r
574         // The user want's to launch a web browser on the source of the URL\r
575         public void sourceUrlClicked() {\r
576                 // Make sure we have a valid URL\r
577                 if (urlText.text().trim().equals(""))\r
578                         return;\r
579                 \r
580                 String url = urlText.text();\r
581                 if (!url.toLowerCase().startsWith(tr("http://")))\r
582                         url = tr("http://") +url;\r
583                 \r
584         if (!QDesktopServices.openUrl(new QUrl(url))) {\r
585                 logger.log(logger.LOW, "Error opening file :" +url);\r
586         }\r
587         }\r
588         \r
589         public void setAuthor(String t) {\r
590                 authorLabel.setText(tr("Author:\t"));\r
591                 authorText.setText(t);\r
592         }\r
593 \r
594         // Set the creation date\r
595         public void setCreation(long date) {\r
596                 QDateTime dt = new QDateTime();\r
597                 dt.setTime_t((int) (date / 1000));\r
598                 createdDate.setDateTime(dt);\r
599                 createdTime.setDateTime(dt);\r
600                 createdDate.setDisplayFormat(Global.getDateFormat());\r
601                 createdTime.setDisplayFormat(Global.getTimeFormat());\r
602         }\r
603 \r
604         // Set the creation date\r
605         public void setAltered(long date) {\r
606                 QDateTime dt = new QDateTime();\r
607                 dt.setTime_t((int) (date / 1000));\r
608                 alteredDate.setDateTime(dt);\r
609                 alteredTime.setDateTime(dt);\r
610                 alteredDate.setDisplayFormat(Global.getDateFormat());\r
611                 alteredTime.setDisplayFormat(Global.getTimeFormat());\r
612         }\r
613 \r
614         // Set the subject date\r
615         public void setSubjectDate(long date) {\r
616                 QDateTime dt = new QDateTime();\r
617                 dt.setTime_t((int) (date / 1000));\r
618                 subjectDate.setDateTime(dt);\r
619                 subjectTime.setDateTime(dt);\r
620                 subjectDate.setDisplayFormat(Global.getDateFormat());\r
621                 subjectTime.setDisplayFormat(Global.getTimeFormat());\r
622         }\r
623 \r
624         // Toggle the extended attribute information\r
625         public void toggleInformation() {\r
626                 if (extendedOn) {\r
627                         extendedOn = false;\r
628                 } else {\r
629                         extendedOn = true;\r
630                 }\r
631                 urlLabel.setVisible(extendedOn);\r
632                 urlText.setVisible(extendedOn);\r
633                 authorText.setVisible(extendedOn);\r
634                 geoBox.setVisible(extendedOn);\r
635                 authorLabel.setVisible(extendedOn);\r
636                 createdDate.setVisible(extendedOn);\r
637                 createdTime.setVisible(extendedOn);\r
638                 createdLabel.setVisible(extendedOn);\r
639                 alteredLabel.setVisible(extendedOn);\r
640                 alteredDate.setVisible(extendedOn);\r
641                 alteredTime.setVisible(extendedOn);\r
642                 //notebookBox.setVisible(extendedOn);\r
643                 notebookLabel.setVisible(extendedOn);\r
644                 subjectLabel.setVisible(extendedOn);\r
645                 subjectDate.setVisible(extendedOn);\r
646                 subjectTime.setVisible(extendedOn);\r
647         }\r
648 \r
649         public void hideButtons() {\r
650 \r
651                 buttonsVisible = false;\r
652                 \r
653                 undoButton.setVisible(false);\r
654                 redoButton.setVisible(false);\r
655                 cutButton.setVisible(false);\r
656                 copyButton.setVisible(false);\r
657                 pasteButton.setVisible(false);\r
658                 boldButton.setVisible(false);\r
659                 underlineButton.setVisible(false);\r
660                 italicButton.setVisible(false);\r
661 \r
662                 rightAlignButton.setVisible(false);\r
663                 leftAlignButton.setVisible(false);\r
664                 centerAlignButton.setVisible(false);\r
665 \r
666                 strikethroughButton.setVisible(false);\r
667                 hlineButton.setVisible(false);\r
668                 indentButton.setVisible(false);\r
669                 outdentButton.setVisible(false);\r
670                 bulletListButton.setVisible(false);\r
671                 numberListButton.setVisible(false);\r
672 \r
673                 fontList.setVisible(false);\r
674                 fontSize.setVisible(false);\r
675                 fontColor.setVisible(false);\r
676                 fontHilight.setVisible(false);\r
677 \r
678         }\r
679 \r
680 \r
681         // Is the extended view on?\r
682         public boolean isExtended() {\r
683                 return extendedOn;\r
684         }\r
685 \r
686         // Listener for when a link is clicked\r
687         @SuppressWarnings("unused")\r
688         private void openFile() {\r
689                 logger.log(logger.EXTREME, "Starting openFile()");\r
690                 File fileHandle = new File(selectedFile);\r
691                 URI fileURL = fileHandle.toURI();\r
692                 String localURL = fileURL.toString();\r
693                 QUrl url = new QUrl(localURL);\r
694                 QFile file = new QFile(selectedFile);\r
695                 \r
696                 logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName());\r
697                 fileWatcher.addPath(file.fileName());\r
698         \r
699         if (!QDesktopServices.openUrl(url)) {\r
700                 logger.log(logger.LOW, "Error opening file :" +url);\r
701         }\r
702         }\r
703         \r
704         \r
705         // Listener for when a link is clicked\r
706         @SuppressWarnings("unused")\r
707         private void linkClicked(QUrl url) {\r
708                 logger.log(logger.EXTREME, "URL Clicked: " +url.toString());\r
709                 if (url.toString().substring(0,8).equals("nnres://")) {\r
710                         logger.log(logger.EXTREME, "URL is NN resource");\r
711                         if (url.toString().endsWith("/vnd.evernote.ink")) {\r
712                                 logger.log(logger.EXTREME, "Unable to open ink note");\r
713                                 QMessageBox.information(this, tr("Unable Open"), tr("This is an ink note.\n"+\r
714                                         "Ink notes are not supported since Evernote has not\n published any specifications on them\n" +\r
715                                         "and I'm too lazy to figure them out by myself."));\r
716                                 return;\r
717                         }\r
718                         String fullName = url.toString().substring(8);\r
719                         int index = fullName.indexOf(".");\r
720                         String guid = "";\r
721                         String type = "";\r
722                         if (index >-1) {\r
723                                 type = fullName.substring(index+1);\r
724                                 guid = fullName.substring(0,index);\r
725                         }\r
726                         index = guid.indexOf(Global.attachmentNameDelimeter);\r
727                         if (index > -1) {\r
728                                 guid = guid.substring(0,index);\r
729                         }\r
730                         List<Resource> resList = currentNote.getResources();\r
731                         Resource res = null;\r
732                         for (int i=0; i<resList.size(); i++) {\r
733                                 if (resList.get(i).getGuid().equals(guid)) {\r
734                                         res = resList.get(i);\r
735                                         i=resList.size();\r
736                                 }\r
737                         }\r
738                         if (res == null) {\r
739                                 String resGuid = Global.resourceMap.get(guid);\r
740                                 if (resGuid != null) \r
741                                         res = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, true);\r
742                         }\r
743                         if (res != null) {\r
744                                 String fileName;\r
745                                 if (res.getAttributes() != null && \r
746                                                 res.getAttributes().getFileName() != null && \r
747                                                 !res.getAttributes().getFileName().trim().equals(""))\r
748                                         fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();\r
749                                 else\r
750                                         fileName = res.getGuid()+"."+type;\r
751                                 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));\r
752                         QFile.OpenMode mode = new QFile.OpenMode();\r
753                         mode.set(QFile.OpenModeFlag.WriteOnly);\r
754                         boolean openResult = file.open(mode);\r
755                                 logger.log(logger.EXTREME, "File opened:" +openResult);\r
756                         QDataStream out = new QDataStream(file);\r
757                         Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);\r
758                                 QByteArray binData = new QByteArray(resBinary.getData().getBody());\r
759                                 resBinary = null;\r
760                                 logger.log(logger.EXTREME, "Writing resource");\r
761                         out.writeBytes(binData.toByteArray());\r
762                         file.close();\r
763                                 \r
764                         String whichOS = System.getProperty("os.name");\r
765                                 if (whichOS.contains("Windows")) \r
766                                 url.setUrl("file:///"+file.fileName());\r
767                         else\r
768                                 url.setUrl("file://"+file.fileName());\r
769                  //       fileWatcher.removePath(file.fileName());\r
770                                 logger.log(logger.EXTREME, "Adding file watcher " +file.fileName());\r
771                                 fileWatcher.addPath(file.fileName());\r
772                         \r
773                         // If we can't open it, then prompt the user to save it.\r
774                         if (!QDesktopServices.openUrl(url)) {\r
775                                         logger.log(logger.EXTREME, "We can't handle this.  Where do we put it?");\r
776                                 QFileDialog dialog = new QFileDialog();\r
777                                 dialog.show();\r
778                                 if (dialog.exec()!=0) {\r
779                                         List<String> fileNames = dialog.selectedFiles(); //gets all selected filenames\r
780                                         if (fileNames.size() == 0) \r
781                                                 return;\r
782                                         String sf = fileNames.get(0);\r
783                                         QFile saveFile = new QFile(sf);\r
784                                         mode.set(QFile.OpenModeFlag.WriteOnly);\r
785                                         saveFile.open(mode);\r
786                                         QDataStream saveOut = new QDataStream(saveFile);\r
787                                         saveOut.writeBytes(binData.toByteArray());\r
788                                         saveFile.close();\r
789                                         return;\r
790                                 }\r
791                                 }\r
792                         }\r
793                         return;\r
794                 }\r
795                 logger.log(logger.EXTREME, "Launching URL");\r
796                 QDesktopServices.openUrl(url);\r
797         }\r
798 \r
799         // Listener for when BOLD is clicked\r
800         @SuppressWarnings("unused")\r
801         private void undoClicked() {\r
802                 browser.page().triggerAction(WebAction.Undo);\r
803                 browser.setFocus();\r
804         }\r
805 \r
806         // Listener for when BOLD is clicked\r
807         @SuppressWarnings("unused")\r
808         private void redoClicked() {\r
809                 browser.page().triggerAction(WebAction.Redo);\r
810                 browser.setFocus();\r
811         }\r
812 \r
813         // Listener for when BOLD is clicked\r
814         @SuppressWarnings("unused")\r
815         private void boldClicked() {\r
816                 browser.page().triggerAction(WebAction.ToggleBold);\r
817                 microFocusChanged();\r
818                 browser.setFocus();\r
819         }\r
820 \r
821         // Listener for when Italics is clicked\r
822         @SuppressWarnings("unused")\r
823         private void italicClicked() {\r
824                 browser.page().triggerAction(WebAction.ToggleItalic);\r
825                 microFocusChanged();\r
826                 browser.setFocus();\r
827         }\r
828 \r
829         // Listener for when UNDERLINE is clicked\r
830         @SuppressWarnings("unused")\r
831         private void underlineClicked() {\r
832                 browser.page().triggerAction(WebAction.ToggleUnderline);\r
833                 microFocusChanged();\r
834                 browser.setFocus();\r
835         }\r
836 \r
837         // Listener for when Strikethrough is clicked\r
838         @SuppressWarnings("unused")\r
839         private void strikethroughClicked() {\r
840                 browser.page().mainFrame().evaluateJavaScript(\r
841                                 "document.execCommand('strikeThrough', false, '');");\r
842                 browser.setFocus();\r
843         }\r
844 \r
845         // Listener for when cut is clicked\r
846         @SuppressWarnings("unused")\r
847         private void cutClicked() {\r
848                 browser.page().triggerAction(WebAction.Cut);\r
849                 browser.setFocus();\r
850         }\r
851 \r
852         // Listener when COPY is clicked\r
853         @SuppressWarnings("unused")\r
854         private void copyClicked() {\r
855                 browser.page().triggerAction(WebAction.Copy);\r
856                 browser.setFocus();\r
857         }\r
858 \r
859         // Listener when PASTE is clicked\r
860         void pasteClicked() {\r
861                 logger.log(logger.EXTREME, "Paste Clicked");\r
862                 if (forceTextPaste) {\r
863                         pasteWithoutFormattingClicked();\r
864                         return;\r
865                 }\r
866                 QClipboard clipboard = QApplication.clipboard();\r
867                 QMimeData mime = clipboard.mimeData();\r
868                 \r
869 //               String x = mime.html();\r
870 \r
871                 if (mime.hasImage()) {\r
872                         logger.log(logger.EXTREME, "Image paste found");\r
873                         insertImage(mime);\r
874                         browser.setFocus();\r
875                         return;\r
876                 }\r
877 \r
878                 if (mime.hasUrls()) {\r
879                         logger.log(logger.EXTREME, "URL paste found");\r
880                         handleUrls(mime);\r
881                         browser.setFocus();\r
882                         return;\r
883                 }\r
884                 \r
885                 String text = mime.html();\r
886                 if (text.contains("en-tag") && mime.hasHtml()) {\r
887                         logger.log(logger.EXTREME, "Intra-note paste found");\r
888                         text = fixInternotePaste(text);\r
889                         mime.setHtml(text);\r
890                         clipboard.setMimeData(mime);\r
891                 }\r
892 \r
893                 logger.log(logger.EXTREME, "Final paste choice encountered");\r
894                 browser.page().triggerAction(WebAction.Paste);\r
895                 browser.setFocus();\r
896 \r
897         }\r
898 \r
899         // Paste text without formatting\r
900         private void pasteWithoutFormattingClicked() {\r
901                 logger.log(logger.EXTREME, "Paste without format clipped");\r
902                 QClipboard clipboard = QApplication.clipboard();\r
903                 QMimeData mime = clipboard.mimeData();\r
904                 if (!mime.hasText())\r
905                         return;\r
906                 String text = mime.text();\r
907                 clipboard.setText(text);\r
908                 browser.page().triggerAction(WebAction.Paste);\r
909                 QApplication.clipboard().setMimeData(mime);\r
910                 browser.setFocus();\r
911 \r
912         }\r
913         \r
914         // insert date/time\r
915         @SuppressWarnings("unused")\r
916         private void insertDateTime() {\r
917                 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();\r
918                 String dateTimeFormat = new String(fmt);\r
919                 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);\r
920                 Calendar cal = Calendar.getInstance();\r
921                 \r
922                 browser.page().mainFrame().evaluateJavaScript(\r
923                         "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");\r
924                 \r
925                 browser.setFocus();\r
926 \r
927         }\r
928 \r
929         // Listener when Left is clicked\r
930         @SuppressWarnings("unused")\r
931         private void justifyLeftClicked() {\r
932                 browser.page().mainFrame().evaluateJavaScript(\r
933                                 "document.execCommand('JustifyLeft', false, '');");\r
934                 browser.setFocus();\r
935         }\r
936 \r
937         // Listener when Center is clicked\r
938         @SuppressWarnings("unused")\r
939         private void justifyCenterClicked() {\r
940                 browser.page().mainFrame().evaluateJavaScript(\r
941                                 "document.execCommand('JustifyCenter', false, '');");\r
942                 browser.setFocus();\r
943         }\r
944 \r
945         // Listener when Left is clicked\r
946         @SuppressWarnings("unused")\r
947         private void justifyRightClicked() {\r
948                 browser.page().mainFrame().evaluateJavaScript(\r
949                                 "document.execCommand('JustifyRight', false, '');");\r
950                 browser.setFocus();\r
951         }\r
952 \r
953         // Listener when HLINE is clicked\r
954         @SuppressWarnings("unused")\r
955         private void hlineClicked() {\r
956                 browser.page().mainFrame().evaluateJavaScript(\r
957                                 "document.execCommand('insertHorizontalRule', false, '');");\r
958                 browser.setFocus();\r
959         }\r
960 \r
961         // Listener when outdent is clicked\r
962         private void outdentClicked() {\r
963                 browser.page().mainFrame().evaluateJavaScript(\r
964                                 "document.execCommand('outdent', false, '');");\r
965                 browser.setFocus();\r
966         }\r
967 \r
968         // Listener when a bullet list is clicked\r
969         @SuppressWarnings("unused")\r
970         private void bulletListClicked() {\r
971                 browser.page().mainFrame().evaluateJavaScript(\r
972                                 "document.execCommand('InsertUnorderedList', false, '');");\r
973                 browser.setFocus();\r
974         }\r
975 \r
976         // Listener when a bullet list is clicked\r
977         @SuppressWarnings("unused")\r
978         private void numberListClicked() {\r
979                 browser.page().mainFrame().evaluateJavaScript(\r
980                                 "document.execCommand('InsertOrderedList', false, '');");\r
981                 browser.setFocus();\r
982         }\r
983 \r
984         // Listener when indent is clicked\r
985         private void indentClicked() {\r
986                 browser.page().mainFrame().evaluateJavaScript(\r
987                                 "document.execCommand('indent', false, '');");\r
988                 browser.setFocus();\r
989         }\r
990 \r
991         // Listener when the font name is changed\r
992         @SuppressWarnings("unused")\r
993         private void fontChanged(String font) {\r
994                 browser.page().mainFrame().evaluateJavaScript(\r
995                                 "document.execCommand('fontName',false,'" + font + "');");\r
996                 browser.setFocus();\r
997         }\r
998 \r
999         // Listener when a font size is changed\r
1000         @SuppressWarnings("unused")\r
1001         private void fontSizeChanged(String font) {\r
1002                 String text = browser.selectedText();\r
1003                 if (text.trim().equalsIgnoreCase(""))\r
1004                         return;\r
1005 \r
1006                 String selectedText = browser.selectedText();\r
1007                 String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";\r
1008                 String script = "document.execCommand('insertHtml', false, '"+url+"');";\r
1009                 browser.page().mainFrame().evaluateJavaScript(script);\r
1010 /*              browser.page().mainFrame().evaluateJavaScript(\r
1011                                 "document.execCommand('fontSize',false,'"\r
1012                                                 + font + "');");\r
1013 */\r
1014                 browser.setFocus();\r
1015         }\r
1016 \r
1017         // Load the font combo box based upon the font selected\r
1018         private void loadFontSize(String name) {        \r
1019                 QFontDatabase db = new QFontDatabase(); \r
1020                 fontSize.clear();\r
1021                 List<Integer> points = db.pointSizes(name); \r
1022                 for (int i=0; i<points.size(); i++) { \r
1023                         fontSize.addItem(points.get(i).toString()); \r
1024                 }\r
1025                 /*\r
1026                 fontSize.addItem("x-small");\r
1027                 fontSize.addItem("small");\r
1028                 fontSize.addItem("medium");\r
1029                 fontSize.addItem("large");\r
1030                 fontSize.addItem("x-large");\r
1031                 fontSize.addItem("xx-large");\r
1032                 fontSize.addItem("xxx-large");\r
1033                 */\r
1034         }\r
1035 \r
1036         // Listener when a font size is changed\r
1037         @SuppressWarnings("unused")\r
1038         private void fontColorClicked() {\r
1039 //              QColorDialog dialog = new QColorDialog();\r
1040 //              QColor color = QColorDialog.getColor();\r
1041                 QColor color = fontColorMenu.getColor();\r
1042                 if (color.isValid())\r
1043                         browser.page().mainFrame().evaluateJavaScript(\r
1044                                         "document.execCommand('foreColor',false,'" + color.name()\r
1045                                                         + "');");\r
1046                 browser.setFocus();\r
1047         }\r
1048 \r
1049         // Listener for when a background color change is requested\r
1050         @SuppressWarnings("unused")\r
1051         private void fontHilightClicked() {\r
1052 //              QColorDialog dialog = new QColorDialog();\r
1053 //              QColor color = QColorDialog.getColor();\r
1054                 QColor color = fontHilightColorMenu.getColor();\r
1055                 if (color.isValid())\r
1056                         browser.page().mainFrame().evaluateJavaScript(\r
1057                                         "document.execCommand('backColor',false,'" + color.name()\r
1058                                                         + "');");\r
1059                 browser.setFocus();\r
1060         }\r
1061         \r
1062         // Listener for when a background color change is requested\r
1063         @SuppressWarnings("unused")\r
1064         private void superscriptClicked() {\r
1065                 browser.page().mainFrame().evaluateJavaScript(\r
1066                                         "document.execCommand('superscript');");\r
1067                 browser.setFocus();\r
1068         }\r
1069         \r
1070         // Listener for when a background color change is requested\r
1071         @SuppressWarnings("unused")\r
1072         private void subscriptClicked() {\r
1073                 browser.page().mainFrame().evaluateJavaScript(\r
1074                                         "document.execCommand('subscript');");\r
1075                 browser.setFocus();\r
1076         }\r
1077         // Insert a to-do checkbox\r
1078         @SuppressWarnings("unused")\r
1079         private void todoClicked() {\r
1080                 FileNameMap fileNameMap = URLConnection.getFileNameMap();\r
1081                 String script_start = new String(\r
1082                                 "document.execCommand('insertHtml', false, '");\r
1083                 String script_end = new String("');");\r
1084                 String todo = new String(\r
1085                                 "<input TYPE=\"CHECKBOX\" value=\"false\" onClick=\"value=checked; window.jambi.contentChanged(); \" />");\r
1086                 browser.page().mainFrame().evaluateJavaScript(\r
1087                                 script_start + todo + script_end);\r
1088                 browser.setFocus();\r
1089         }\r
1090 \r
1091         // Encrypt the selected text\r
1092         @SuppressWarnings("unused")\r
1093         private void encryptText() {\r
1094                 String text = browser.selectedText();\r
1095                 if (text.trim().equalsIgnoreCase(""))\r
1096                         return;\r
1097 \r
1098                 EnCryptDialog dialog = new EnCryptDialog();\r
1099                 dialog.exec();\r
1100                 if (!dialog.okPressed()) {\r
1101                         return;\r
1102                 }\r
1103 \r
1104                 EnCrypt crypt = new EnCrypt();\r
1105                 String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);\r
1106 \r
1107                 if (encrypted.trim().equals("")) {\r
1108                         QMessageBox.information(this, tr("Error"), tr("Error Encrypting String"));\r
1109                         return;\r
1110                 }\r
1111                 StringBuffer buffer = new StringBuffer(encrypted.length() + 100);\r
1112                 buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""\r
1113                                 + dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");\r
1114                 buffer.append("contentEditable=\"false\" alt=\"");\r
1115                 buffer.append(encrypted);\r
1116                 // NFC FIXME: should this be a file URL like in handleLocalAttachment and importAttachment?\r
1117                 buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png") +"\""));\r
1118                 Global.cryptCounter++;\r
1119                 buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");\r
1120                 buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");\r
1121                 buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString() \r
1122                                 +"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&amp;apos;")+"\\');\"");\r
1123                 buffer.append("style=\"display:block\" />");\r
1124 \r
1125                 String script_start = new String(\r
1126                                 "document.execCommand('insertHtml', false, '");\r
1127                 String script_end = new String("');");\r
1128                 browser.page().mainFrame().evaluateJavaScript(\r
1129                                 script_start + buffer.toString() + script_end);\r
1130         }\r
1131 \r
1132         \r
1133         // Insert a hyperlink\r
1134         public void insertLink() {\r
1135                 logger.log(logger.EXTREME, "Inserting link");\r
1136                 String text = browser.selectedText();\r
1137                 if (text.trim().equalsIgnoreCase(""))\r
1138                         return;\r
1139 \r
1140                 InsertLinkDialog dialog = new InsertLinkDialog();\r
1141                 if (currentHyperlink != null && currentHyperlink != "") {\r
1142                         dialog.setUrl(currentHyperlink);\r
1143                 }\r
1144                 dialog.exec();\r
1145                 if (!dialog.okPressed()) {\r
1146                         logger.log(logger.EXTREME, "Insert link canceled");\r
1147                         return;\r
1148                 }\r
1149                 if (browser.insertLinkAction.text().equalsIgnoreCase("Insert Hyperlink")) {\r
1150                         String selectedText = browser.selectedText();\r
1151                         logger.log(logger.EXTREME, "Inserting link on text "+selectedText);\r
1152                         logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim());\r
1153                         String url = "<a href=\"" +dialog.getUrl().trim()+"\" >"+selectedText +"</a>";\r
1154                         String script = "document.execCommand('insertHtml', false, '"+url+"');";\r
1155                         browser.page().mainFrame().evaluateJavaScript(script);\r
1156                         return;\r
1157                 } else {\r
1158                         String js = new String( "function getCursorPos() {"\r
1159                                         +"var cursorPos;"\r
1160                                         +"if (window.getSelection) {"\r
1161                                         +"   var selObj = window.getSelection();"\r
1162                                         +"   var selRange = selObj.getRangeAt(0);"\r
1163                                         +"   var workingNode = window.getSelection().anchorNode.parentNode;"\r
1164                                         +"   while(workingNode != null) { " \r
1165                                         +"      if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');"\r
1166                                         +"      workingNode = workingNode.parentNode;"\r
1167                                         +"   }"\r
1168                                         +"}"\r
1169                                         +"} getCursorPos();");\r
1170                                 browser.page().mainFrame().evaluateJavaScript(js);\r
1171                                 contentChanged();\r
1172                 }\r
1173                 \r
1174         }\r
1175         \r
1176         // Insert a table\r
1177         public void insertTable() {\r
1178                 TableDialog dialog = new TableDialog();\r
1179                 dialog.exec();\r
1180                 if (!dialog.okPressed()) {\r
1181                         return;\r
1182                 }\r
1183                 \r
1184                 int cols = dialog.getCols();\r
1185                 int rows = dialog.getRows();\r
1186                 int width = dialog.getWidth();\r
1187                 boolean percent = dialog.isPercent();\r
1188                 \r
1189                 String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();\r
1190                 if (percent)\r
1191                         newHTML = newHTML +"%";\r
1192                 newHTML = newHTML + "\"><tbody>";\r
1193 \r
1194                 for (int i=0; i<rows; i++) {\r
1195                         newHTML = newHTML +"<tr>";\r
1196                         for (int j=0; j<cols; j++) {\r
1197                                 newHTML = newHTML +"<td>&nbsp;</td>";\r
1198                         }\r
1199                         newHTML = newHTML +"</tr>";\r
1200                 }\r
1201                 newHTML = newHTML+"</tbody></table>";   \r
1202         \r
1203                 String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";\r
1204                 browser.page().mainFrame().evaluateJavaScript(script);\r
1205         }\r
1206         \r
1207         \r
1208         // Text content changed\r
1209         @SuppressWarnings("unused")\r
1210         private void selectionChanged() {\r
1211                 browser.encryptAction.setEnabled(true);\r
1212                 browser.insertLinkAction.setEnabled(true);\r
1213                 String scriptStart = "var selection_text = (window.getSelection()).toString();"\r
1214                                 + "var range = (window.getSelection()).getRangeAt(0);"\r
1215                                 + "var parent_html = range.commonAncestorContainer.innerHTML;"\r
1216                                 + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"\r
1217                                 + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"\r
1218                                 + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"\r
1219                                 + "var start = parent_html.indexOf(first_text);"\r
1220                                 + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"\r
1221                                 + "var value = parent_html.substring(start,end);"\r
1222                                 + "window.jambi.saveSelectedText(value);" ;\r
1223                 browser.page().mainFrame().evaluateJavaScript(scriptStart);\r
1224 \r
1225         }\r
1226 \r
1227         public void saveSelectedText(String text) {\r
1228                 boolean enabled = true;\r
1229                 if (text.trim().length() == 0)\r
1230                         enabled=false;\r
1231                 if (text.indexOf("en-tag=\"en-crypt\"") >= 0)\r
1232                         enabled=false;\r
1233                 if (text.indexOf("<img en-tag=\"en-media\"") >= 0)\r
1234                         enabled=false;\r
1235                 if (text.indexOf("<a en-tag=\"en-media\"") >= 0)\r
1236                         enabled=false;\r
1237                 if (text.indexOf("<input ") >= 0)\r
1238                         enabled=false;\r
1239                 \r
1240                 browser.encryptAction.setEnabled(enabled);\r
1241                 browser.insertLinkAction.setEnabled(enabled);\r
1242 //              selectedText = text;\r
1243         }\r
1244 \r
1245         // Decrypt clicked text\r
1246         public void decryptText(String id, String text, String hint) {\r
1247                 EnCrypt crypt = new EnCrypt();\r
1248                 String plainText = null;\r
1249                 Calendar currentTime = new GregorianCalendar();\r
1250                 Long l = new Long(currentTime.getTimeInMillis());\r
1251                 String slot = new String(Long.toString(l));\r
1252                 \r
1253                 // First, try to decrypt with any keys we already have\r
1254                 for (int i=0; i<Global.passwordRemember.size(); i++) {\r
1255                         plainText = crypt.decrypt(text, Global.passwordRemember.get(i), 64);\r
1256                         if (plainText != null) {\r
1257                                 slot = new String(Long.toString(l));\r
1258                                 Global.passwordSafe.put(slot, Global.passwordRemember.get(i));\r
1259                                 removeEncryption(id, plainText, false, slot);   \r
1260                                 return;\r
1261                         }\r
1262                 }\r
1263                 \r
1264                 \r
1265                 EnDecryptDialog dialog = new EnDecryptDialog();\r
1266                 dialog.setHint(hint);\r
1267                 while (plainText == null || !dialog.okPressed()) {\r
1268                         dialog.exec();\r
1269                         if (!dialog.okPressed()) {\r
1270                                 return;\r
1271                         }\r
1272                         plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);\r
1273                         if (plainText == null) {\r
1274                                 QMessageBox.warning(this, "Incorrect Password", "The password entered is not correct");\r
1275                         }\r
1276                 }\r
1277                 Global.passwordSafe.put(slot, dialog.getPassword());\r
1278                 removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);\r
1279                 if (dialog.rememberPassword())\r
1280                         Global.passwordRemember.add(dialog.getPassword());\r
1281 \r
1282         }\r
1283 \r
1284         // Get the editor tag line\r
1285         public TagLineEdit getTagLine() {\r
1286                 return tagEdit;\r
1287         }\r
1288 \r
1289         // Modify a note's tags\r
1290         @SuppressWarnings("unused")\r
1291         private void modifyTags() {\r
1292                 TagAssign tagWindow = new TagAssign(allTags, currentTags);\r
1293                 tagWindow.exec();\r
1294                 if (tagWindow.okClicked()) {\r
1295                         currentTags.clear();\r
1296                         StringBuffer tagDisplay = new StringBuffer();\r
1297 \r
1298                         List<QListWidgetItem> newTags = tagWindow.getTagList()\r
1299                                         .selectedItems();\r
1300                         for (int i = 0; i < newTags.size(); i++) {\r
1301                                 currentTags.add(newTags.get(i).text());\r
1302                                 tagDisplay.append(newTags.get(i).text());\r
1303                                 if (i < newTags.size() - 1) {\r
1304                                         tagDisplay.append(Global.tagDelimeter + " ");\r
1305                                 }\r
1306                         }\r
1307                         tagEdit.setText(tagDisplay.toString());\r
1308                         noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);\r
1309                 }\r
1310         }\r
1311 \r
1312         // Tag line has been modified by typing text\r
1313         @SuppressWarnings("unused")\r
1314         private void modifyTagsTyping() {\r
1315                 String completionText = "";\r
1316                 if (tagEdit.currentCompleterSelection != null && !tagEdit.currentCompleterSelection.equals("")) {\r
1317                         completionText = tagEdit.currentCompleterSelection;\r
1318                         tagEdit.currentCompleterSelection = "";\r
1319                 }\r
1320                 \r
1321                 if (tagEdit.text().equalsIgnoreCase(saveTagList))\r
1322                         return;\r
1323 \r
1324                 // We know something has changed...\r
1325                 String oldTagArray[] = saveTagList.split(Global.tagDelimeter);\r
1326                 String newTagArray[] = tagEdit.text().split(Global.tagDelimeter);\r
1327                 \r
1328                 if (!completionText.equals("") && newTagArray.length > 0) {\r
1329                         newTagArray[newTagArray.length-1] = completionText;\r
1330                 }\r
1331                 // Remove any potential duplicates from the new list\r
1332                 for (int i=0; i<newTagArray.length; i++) {\r
1333                         boolean foundOnce = false;\r
1334                         for (int j=0; j<newTagArray.length; j++) {\r
1335                                 if (newTagArray[j].equalsIgnoreCase(newTagArray[i])) {\r
1336                                         if (!foundOnce) {\r
1337                                                 foundOnce = true;\r
1338                                         } else\r
1339                                                 newTagArray[j] = "";\r
1340                                 }\r
1341                         }\r
1342                 }\r
1343 \r
1344                 List<String> newTagList = new ArrayList<String>();\r
1345                 List<String> oldTagList = new ArrayList<String>();\r
1346 \r
1347                 for (int i = 0; i < oldTagArray.length; i++)\r
1348                         if (!oldTagArray[i].trim().equals(""))\r
1349                                 oldTagList.add(oldTagArray[i]);\r
1350                 for (int i = 0; i < newTagArray.length; i++)\r
1351                         if (!newTagArray[i].trim().equals(""))\r
1352                                 newTagList.add(newTagArray[i]);\r
1353 \r
1354                 // Let's cleanup the appearance of the tag list\r
1355                 Collections.sort(newTagList);\r
1356                 String newDisplay = "";\r
1357                 for (int i=0; i<newTagList.size(); i++) {\r
1358                         newDisplay = newDisplay+newTagList.get(i);\r
1359                         if (i<newTagList.size()-1)\r
1360                                 newDisplay = newDisplay+", ";\r
1361                 }\r
1362                 tagEdit.blockSignals(true);\r
1363                 tagEdit.setText(newDisplay);\r
1364                 tagEdit.blockSignals(false);\r
1365                 \r
1366                 // We now have lists of the new & old. Remove duplicates. If all\r
1367                 // are removed from both then nothing has really changed\r
1368                 for (int i = newTagList.size() - 1; i >= 0; i--) {\r
1369                         String nTag = newTagList.get(i);\r
1370                         for (int j = oldTagList.size() - 1; j >= 0; j--) {\r
1371                                 String oTag = oldTagList.get(j);\r
1372                                 if (oTag.equalsIgnoreCase(nTag)) {\r
1373                                         oldTagList.remove(j);\r
1374                                         newTagList.remove(i);\r
1375                                         j = -1;\r
1376                                 }\r
1377                         }\r
1378                 }\r
1379 \r
1380                 if (oldTagList.size() != 0 || newTagList.size() != 0) {\r
1381                         currentTags.clear();\r
1382                         newTagArray = tagEdit.text().split(Global.tagDelimeter);\r
1383                         for (int i = 0; i < newTagArray.length; i++)\r
1384                                 if (!newTagArray[i].trim().equals(""))\r
1385                                         currentTags.add(newTagArray[i].trim());\r
1386 \r
1387                         noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);\r
1388                 }\r
1389                 \r
1390         }\r
1391 \r
1392         // Tab button was pressed\r
1393         public void tabPressed() {\r
1394                 if (!insideList) {\r
1395                         String script_start = new String(\r
1396                         "document.execCommand('insertHtml', false, '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');");\r
1397                         browser.page().mainFrame().evaluateJavaScript(script_start);\r
1398                 } else \r
1399                         indentClicked();\r
1400         }\r
1401         \r
1402         public void backtabPressed() {\r
1403                 if (insideList)\r
1404                         outdentClicked();\r
1405         }\r
1406         \r
1407         public void setInsideList() {\r
1408                 insideList = true;\r
1409         }\r
1410         \r
1411         // The title has been edited\r
1412         @SuppressWarnings("unused")\r
1413         private void titleEdited() {\r
1414                 // If we don't have a good note, or if the current title\r
1415                 // matches the old title then we don't need to do anything\r
1416                 if (currentNote == null)\r
1417                         return;\r
1418                 if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))\r
1419                         return;\r
1420                 \r
1421                 // If we have a real change, we need to save it.\r
1422                 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text());\r
1423                 currentNote.setTitle(titleLabel.text());\r
1424                 saveNoteTitle = titleLabel.text();\r
1425                 checkNoteTitle();\r
1426         }\r
1427 \r
1428         // Set the list of note tags\r
1429         public void setAllTags(List<Tag> l) {\r
1430                 allTags = l;\r
1431                 tagEdit.setTagList(l);\r
1432         }\r
1433 \r
1434         // Setter for the current tags\r
1435         public void setCurrentTags(List<String> s) {\r
1436                 currentTags = s;\r
1437         }\r
1438 \r
1439         // Save the list of notebooks\r
1440         public void setNotebookList(List<Notebook> n) {\r
1441                 notebookList = n;\r
1442                 loadNotebookList();\r
1443         }\r
1444 \r
1445         // Load the notebook list and select the current notebook\r
1446         private void loadNotebookList() {\r
1447                 if (notebookBox.count() != 0)\r
1448                         notebookBox.clear();\r
1449                 if (notebookList == null)\r
1450                         return;\r
1451 \r
1452                 for (int i = 0; i < notebookList.size(); i++) {\r
1453                         notebookBox.addItem(notebookList.get(i).getName());\r
1454                         if (currentNote != null) {\r
1455                                 if (currentNote.getNotebookGuid().equals(\r
1456                                                 notebookList.get(i).getGuid())) {\r
1457                                         notebookBox.setCurrentIndex(i);\r
1458                                 }\r
1459                         }\r
1460                 }\r
1461         }\r
1462 \r
1463         // Get the contents of the editor\r
1464         public String getContent() {\r
1465                 return browser.page().currentFrame().toHtml();\r
1466         }\r
1467 \r
1468         // The note contents have changed\r
1469         public void contentChanged() {\r
1470                 String content = getContent();\r
1471                 checkNoteTitle();\r
1472                 noteSignal.noteChanged.emit(currentNote.getGuid(), content); \r
1473         }\r
1474 \r
1475         // The notebook selection has changed\r
1476         @SuppressWarnings("unused")\r
1477         private void notebookChanged() {\r
1478                 boolean changed = false;\r
1479                 String n = notebookBox.currentText();\r
1480                 for (int i = 0; i < notebookList.size(); i++) {\r
1481                         if (n.equals(notebookList.get(i).getName())) {\r
1482                                 if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {\r
1483                                         currentNote.setNotebookGuid(notebookList.get(i).getGuid());\r
1484                                         changed = true;\r
1485                                 }\r
1486                                 i = notebookList.size();\r
1487                         }\r
1488                 }\r
1489                 \r
1490                 // If the notebook changed, signal the update\r
1491                 if (changed)\r
1492                         noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote\r
1493                                         .getNotebookGuid());\r
1494         }\r
1495 \r
1496         // Check the note title\r
1497         private void checkNoteTitle() {\r
1498                 String text = browser.page().currentFrame().toPlainText();\r
1499                 if (saveNoteTitle.trim().equals("")) {\r
1500                         int newLine = text.indexOf("\n");\r
1501                         if (newLine > 0) {\r
1502                                 text = text.substring(0, newLine);\r
1503                                 if (text.trim().equals(""))\r
1504                                         text = tr("Untitled Note");\r
1505                                 titleLabel.setText(text);\r
1506                         } else {\r
1507                                 if (text.length() > 20)\r
1508                                         titleLabel.setText(text.substring(0, 20));\r
1509                                 else {\r
1510                                         if (text.trim().equals(""))\r
1511                                                 titleLabel.setText(tr("Untitled Note"));\r
1512                                         else\r
1513                                                 titleLabel.setText(text);\r
1514                                 }\r
1515                         }\r
1516                         noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel\r
1517                                         .text());\r
1518                 }\r
1519         }\r
1520 \r
1521         // Return the note contents so we can email them\r
1522         public String getContentsToEmail() {\r
1523                 return browser.page().currentFrame().toPlainText().trim();\r
1524                 /*\r
1525                  * int body = browser.page().currentFrame().toHtml().indexOf("<body>");\r
1526                  * String temp = browser.page().currentFrame().toHtml(); if (body == -1)\r
1527                  * temp = "<html><body><b>Test</b></body></html>"; else temp =\r
1528                  * "<html>"+temp.substring(body); return temp; // return\r
1529                  * urlEncode(browser.page().currentFrame().toHtml());\r
1530                  */\r
1531         }\r
1532 \r
1533         // Insert an image into the editor\r
1534         private void insertImage(QMimeData mime) {\r
1535                 logger.log(logger.EXTREME, "Entering insertImage");\r
1536                 QImage img = (QImage) mime.imageData();\r
1537                 String script_start = new String(\r
1538                                 "document.execCommand('insertHTML', false, '");\r
1539                 String script_end = new String("');");\r
1540 \r
1541                 long now = new Date().getTime();\r
1542                 String path = Global.getFileManager().getResDirPath(\r
1543                                 (new Long(now).toString()) + ".jpg");\r
1544 \r
1545                 // This block is just a hack to make sure we wait at least 1ms so we\r
1546                 // don't\r
1547                 // have collisions on image names\r
1548                 long i = new Date().getTime();\r
1549                 while (now == i)\r
1550                         i = new Date().getTime();\r
1551 \r
1552                 // Open the file & write the data\r
1553                 QFile tfile = new QFile(path);\r
1554                 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));\r
1555                 img.save(tfile);\r
1556                 tfile.close();\r
1557                 \r
1558                 Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);\r
1559                 if (newRes == null)\r
1560                         return;\r
1561                 currentNote.getResources().add(newRes);\r
1562 \r
1563                 // do the actual insert into the note\r
1564                 StringBuffer buffer = new StringBuffer(100);\r
1565                 buffer.append("<img src=\"");\r
1566                 buffer.append(tfile.fileName());\r
1567                 buffer.append("\" en-tag=en-media type=\"image/jpeg\""\r
1568                                 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""\r
1569                                 +" guid=\"" +newRes.getGuid() +"\""\r
1570                                 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""\r
1571                                 + " />");\r
1572                 browser.page().mainFrame().evaluateJavaScript(\r
1573                                 script_start + buffer + script_end);\r
1574 \r
1575                 return;\r
1576         }\r
1577 \r
1578         // Handle URLs that are trying to be pasted\r
1579         public void handleUrls(QMimeData mime) {\r
1580                 logger.log(logger.EXTREME, "Starting handleUrls");\r
1581                 FileNameMap fileNameMap = URLConnection.getFileNameMap();\r
1582 \r
1583                 List<QUrl> urlList = mime.urls();\r
1584                 String url = new String();\r
1585                 String script_start = new String(\r
1586                                 "document.execCommand('createLink', false, '");\r
1587                 String script_end = new String("');");\r
1588 \r
1589                 for (int i = 0; i < urlList.size(); i++) {\r
1590                         url = urlList.get(i).toString();\r
1591                         // Find out what type of file we have\r
1592                         String mimeType = fileNameMap.getContentTypeFor(url);\r
1593 \r
1594                         // If null returned, we need to guess at the file type\r
1595                         if (mimeType == null)\r
1596                                 mimeType = "application/"\r
1597                                                 + url.substring(url.lastIndexOf(".") + 1);\r
1598 \r
1599                         // Check if we have an image or some other type of file\r
1600                         if (url.substring(0, 5).equalsIgnoreCase("file:")\r
1601                                         && mimeType.substring(0, 5).equalsIgnoreCase("image")) {\r
1602                                 handleLocalImageURLPaste(mime, mimeType);\r
1603                                 return;\r
1604                         }\r
1605                         String[] type = mimeType.split("/");\r
1606                         boolean valid = validAttachment(type[1]);\r
1607                         boolean smallEnough = checkFileAttachmentSize(url);\r
1608                         if (smallEnough && valid\r
1609                                         && url.substring(0, 5).equalsIgnoreCase("file:")\r
1610                                         && !mimeType.substring(0, 5).equalsIgnoreCase("image")) {\r
1611                                 handleLocalAttachment(mime, mimeType);\r
1612                                 return;\r
1613                         }\r
1614                         browser.page().mainFrame().evaluateJavaScript(\r
1615                                         script_start + url + script_end);\r
1616                 }\r
1617                 return;\r
1618         }\r
1619 \r
1620         // If a URL being pasted is an image URL, then attach the image\r
1621         private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {\r
1622                 List<QUrl> urlList = mime.urls();\r
1623                 String url = new String();\r
1624                 String script_start_image = new String(\r
1625                                 "document.execCommand('insertHtml', false, '");\r
1626                 String script_end = new String("');");\r
1627                 StringBuffer buffer;\r
1628 \r
1629                 // Copy the image over into the resource directory and create a new resource \r
1630                 // record for each url pasted\r
1631                 for (int i = 0; i < urlList.size(); i++) {\r
1632                         url = urlList.get(i).toString();\r
1633 \r
1634                         Resource newRes = createResource(url, i, mimeType, false);\r
1635                         if (newRes == null)\r
1636                                 return;\r
1637                         currentNote.getResources().add(newRes);\r
1638                         buffer = new StringBuffer(100);\r
1639                         \r
1640                         // Open the file & write the data\r
1641                         String fileName = Global.getFileManager().getResDirPath(newRes.getGuid());\r
1642                         QFile tfile = new QFile(fileName);\r
1643                         tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));\r
1644                         tfile.write(newRes.getData().getBody());\r
1645                         tfile.close();\r
1646                         buffer.append(script_start_image);\r
1647                         buffer.append("<img src=\"" + FileUtils.toForwardSlashedPath(fileName));\r
1648 //                      if (mimeType.equalsIgnoreCase("image/jpg"))\r
1649 //                              mimeType = "image/jpeg";\r
1650                         buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""\r
1651                                         +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""\r
1652                                         +" guid=\"" +newRes.getGuid() +"\""\r
1653                                         +" onContextMenu=\"window.jambi.imageContextMenu(&apos;" +tfile.fileName() +"&apos;);\""\r
1654                                         + " />");\r
1655                         buffer.append(script_end);\r
1656                         browser.page().mainFrame().evaluateJavaScript(buffer.toString());\r
1657                 }\r
1658                 return;\r
1659         }\r
1660         \r
1661 \r
1662         // If a URL being pasted is a local file URL, then attach the file\r
1663         private void handleLocalAttachment(QMimeData mime, String mimeType) {\r
1664                 logger.log(logger.EXTREME, "Attaching local file");\r
1665                 List<QUrl> urlList = mime.urls();\r
1666                 String script_start = new String(\r
1667                                 "document.execCommand('insertHtml', false, '");\r
1668                 String script_end = new String("');");\r
1669                 StringBuffer buffer;\r
1670 \r
1671                 for (int i = 0; i < urlList.size(); i++) {\r
1672                         buffer = new StringBuffer(100);\r
1673                         String url = urlList.get(i).toString();\r
1674 \r
1675                         // Start building the HTML\r
1676                         String[] type = mimeType.split("/");\r
1677                         String icon = findIcon(type[1]);\r
1678                         if (icon.equals("attachment.png"))\r
1679                                 icon = findIcon(type[0]);\r
1680                         if (icon.equals("attachment.png"))\r
1681                                 icon = findIcon(url.substring(url.lastIndexOf(".")+1));\r
1682                         String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));\r
1683 \r
1684                         logger.log(logger.EXTREME, "Creating resource ");\r
1685                         Resource newRes = createResource(url, i, mimeType, true);\r
1686                         if (newRes == null)\r
1687                                 return;\r
1688                         logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());\r
1689                         currentNote.getResources().add(newRes);\r
1690                         \r
1691                         String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();\r
1692                         // If we have a PDF, we need to setup the preview.\r
1693                         if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {\r
1694                                 logger.log(logger.EXTREME, "Setting up PDF preview");\r
1695                                 if (newRes.getAttributes() != null && \r
1696                                                 newRes.getAttributes().getFileName() != null && \r
1697                                                 !newRes.getAttributes().getFileName().trim().equals(""))\r
1698                                         fileName = newRes.getGuid()+Global.attachmentNameDelimeter+\r
1699                                                 newRes.getAttributes().getFileName();\r
1700                                 else\r
1701                                         fileName = newRes.getGuid()+".pdf";\r
1702                                 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));\r
1703                         QFile.OpenMode mode = new QFile.OpenMode();\r
1704                         mode.set(QFile.OpenModeFlag.WriteOnly);\r
1705                         file.open(mode);\r
1706                         QDataStream out = new QDataStream(file);\r
1707 //                      Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);\r
1708                                 QByteArray binData = new QByteArray(newRes.getData().getBody());\r
1709 //                              resBinary = null;\r
1710                         out.writeBytes(binData.toByteArray());\r
1711                         file.close();\r
1712 \r
1713                                 PDFPreview pdfPreview = new PDFPreview();\r
1714                                 if (pdfPreview.setupPreview(Global.getFileManager().getResDirPath(fileName), "pdf",0)) {\r
1715                                 // NFC TODO: should this be a 'file://' url like the ones above?\r
1716                                 imageURL = file.fileName() + ".png";\r
1717                                 }\r
1718                         }\r
1719                                                 \r
1720                         logger.log(logger.EXTREME, "Generating link tags");\r
1721                         buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");\r
1722                         buffer.append(" onContextMenu=\"window.jambi.imageContextMenu(&apos;")\r
1723                       .append(Global.getFileManager().getResDirPath(fileName))\r
1724                       .append("&apos;);\" ");                   buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");\r
1725                         buffer.append("<img src=\"" + imageURL + "\" title=\"" +newRes.getAttributes().getFileName());\r
1726                         buffer.append("\"></img>");\r
1727                         buffer.append("</a>");\r
1728                         browser.page().mainFrame().evaluateJavaScript(\r
1729                                         script_start + buffer.toString() + script_end);\r
1730                 }\r
1731                 return;\r
1732         }\r
1733         private Resource createResource(String url, int sequence, String mime, boolean attachment) {\r
1734                 logger.log(logger.EXTREME, "Inside create resource");\r
1735                 QFile resourceFile;\r
1736                 url = new QUrl(url).toLocalFile();\r
1737                 url = url.replace("/", File.separator);\r
1738         resourceFile = new QFile(url); \r
1739         resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));\r
1740         byte[] fileData = resourceFile.readAll().toByteArray();\r
1741         resourceFile.close();\r
1742         if (fileData.length == 0)\r
1743                 return null;\r
1744         MessageDigest md;\r
1745         try {\r
1746                 md = MessageDigest.getInstance("MD5");\r
1747                 md.update(fileData);\r
1748                 byte[] hash = md.digest();\r
1749   \r
1750                 Resource r = new Resource();\r
1751                 Calendar time = new GregorianCalendar();\r
1752                 long prevTime = time.getTimeInMillis();\r
1753                 while (prevTime == time.getTimeInMillis()) {\r
1754                         time = new GregorianCalendar();\r
1755                 }\r
1756                 r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());\r
1757                 r.setNoteGuid(currentNote.getGuid());\r
1758                 r.setMime(mime);\r
1759                 r.setActive(true);\r
1760                 r.setUpdateSequenceNum(0);\r
1761                 r.setWidth((short) 0);\r
1762                 r.setHeight((short) 0);\r
1763                 r.setDuration((short) 0);\r
1764                                 \r
1765                 Data d = new Data();\r
1766                 d.setBody(fileData);\r
1767                 d.setBodyIsSet(true);\r
1768                 d.setBodyHash(hash);\r
1769                 d.setBodyHashIsSet(true);\r
1770                 r.setData(d);\r
1771                 d.setSize(fileData.length);\r
1772                 \r
1773                 int fileNamePos = url.lastIndexOf(File.separator);\r
1774                 if (fileNamePos == -1)\r
1775                         fileNamePos = url.lastIndexOf("/");\r
1776                         String fileName = url.substring(fileNamePos+1);\r
1777                 ResourceAttributes a = new ResourceAttributes();\r
1778                 a.setAltitude(0);\r
1779                 a.setAltitudeIsSet(false);\r
1780                 a.setLongitude(0);\r
1781                 a.setLongitudeIsSet(false);\r
1782                 a.setLatitude(0);\r
1783                 a.setLatitudeIsSet(false);\r
1784                 a.setCameraMake("");\r
1785                 a.setCameraMakeIsSet(false);\r
1786                 a.setCameraModel("");\r
1787                 a.setCameraModelIsSet(false);\r
1788                 a.setAttachment(attachment);\r
1789                 a.setAttachmentIsSet(true);\r
1790                 a.setClientWillIndex(false);\r
1791                 a.setClientWillIndexIsSet(true);\r
1792                 a.setRecoType("");\r
1793                 a.setRecoTypeIsSet(false);\r
1794                 a.setSourceURL(url);\r
1795                 a.setSourceURLIsSet(true);\r
1796                 a.setTimestamp(0);\r
1797                 a.setTimestampIsSet(false);\r
1798                 a.setFileName(fileName);\r
1799                 a.setFileNameIsSet(true);\r
1800                 r.setAttributes(a);\r
1801                 \r
1802                 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);\r
1803                 return r;\r
1804         } catch (NoSuchAlgorithmException e1) {\r
1805                 e1.printStackTrace();\r
1806                 }\r
1807         return null;\r
1808         }\r
1809         \r
1810 \r
1811     // find the appropriate icon for an attachment\r
1812     private String findIcon(String appl) {\r
1813         appl = appl.toLowerCase();\r
1814         File f = Global.getFileManager().getImageDirFile(appl + ".png");\r
1815         if (f.exists())\r
1816                 return appl+".png";\r
1817         return "attachment.png";\r
1818     }\r
1819 \r
1820         // Check if the account supports this type of attachment\r
1821         private boolean validAttachment(String type) {\r
1822                 if (Global.isPremium())\r
1823                         return true;\r
1824                 if (type.equalsIgnoreCase("JPG"))\r
1825                         return true;\r
1826                 if (type.equalsIgnoreCase("PNG"))\r
1827                         return true;\r
1828                 if (type.equalsIgnoreCase("GIF"))\r
1829                         return true;\r
1830                 if (type.equalsIgnoreCase("MP3"))\r
1831                         return true;\r
1832                 if (type.equalsIgnoreCase("WAV"))\r
1833                         return true;\r
1834                 if (type.equalsIgnoreCase("AMR"))\r
1835                         return true;\r
1836                 if (type.equalsIgnoreCase("PDF"))\r
1837                         return true;\r
1838                 String error = tr("Non-premium accounts can only attach JPG, PNG, GIF, MP3, WAV, AMR, or PDF files.");\r
1839                 QMessageBox.information(this, tr("Non-Premium Account"), error);\r
1840 \r
1841                 return false;\r
1842         }\r
1843 \r
1844         // Check the file attachment to be sure it isn't over 25 mb\r
1845         private boolean checkFileAttachmentSize(String url) {\r
1846                 String fileName = url.substring(8);\r
1847                 QFile resourceFile = new QFile(fileName);\r
1848                 resourceFile.open(new QIODevice.OpenMode(\r
1849                                 QIODevice.OpenModeFlag.ReadOnly));\r
1850                 long size = resourceFile.size();\r
1851                 resourceFile.close();\r
1852                 size = size / 1024 / 1024;\r
1853                 if (size < 50 && Global.isPremium())\r
1854                         return true;\r
1855                 if (size < 25)\r
1856                         return true;\r
1857 \r
1858                 String error = tr("A file attachment may not exceed 25MB.");\r
1859                 QMessageBox.information(this, tr("Attachment Size"), error);\r
1860                 return false;\r
1861         }\r
1862 \r
1863 \r
1864         @SuppressWarnings("unused")\r
1865         private void createdChanged() {\r
1866                 QDateTime dt = new QDateTime();\r
1867                 dt.setDate(createdDate.date());\r
1868                 dt.setTime(createdTime.time());\r
1869                 noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);\r
1870 \r
1871         }\r
1872 \r
1873         @SuppressWarnings("unused")\r
1874         private void alteredChanged() {\r
1875                 QDateTime dt = new QDateTime();\r
1876                 dt.setDate(alteredDate.date());\r
1877                 dt.setTime(alteredTime.time());\r
1878                 noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);\r
1879         }\r
1880 \r
1881         @SuppressWarnings("unused")\r
1882         private void subjectDateTimeChanged() {\r
1883                 QDateTime dt = new QDateTime();\r
1884                 dt.setDate(subjectDate.date());\r
1885                 dt.setTime(subjectTime.time());\r
1886                 noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);\r
1887 \r
1888         }\r
1889 \r
1890         @SuppressWarnings("unused")\r
1891         private void sourceUrlChanged() {\r
1892                 noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());\r
1893         }\r
1894 \r
1895         @SuppressWarnings("unused")\r
1896         private void authorChanged() {\r
1897                 noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());\r
1898         }\r
1899         \r
1900         @SuppressWarnings("unused")\r
1901         private void geoBoxChanged() {\r
1902                 int index = geoBox.currentIndex();\r
1903                 geoBox.setCurrentIndex(0);\r
1904                 if (index == 1) {\r
1905                         GeoDialog box = new GeoDialog();\r
1906                         box.setLongitude(currentNote.getAttributes().getLongitude());\r
1907                         box.setLatitude(currentNote.getAttributes().getLatitude());\r
1908                         box.setAltitude(currentNote.getAttributes().getAltitude());\r
1909                         box.exec();\r
1910                         if (!box.okPressed())\r
1911                                 return;\r
1912                         double alt = box.getAltitude();\r
1913                         double lat = box.getLatitude();\r
1914                         double lon = box.getLongitude();\r
1915                         if (alt != currentNote.getAttributes().getAltitude() ||\r
1916                                 lon != currentNote.getAttributes().getLongitude() ||\r
1917                                 lat != currentNote.getAttributes().getLatitude()) {\r
1918                                         noteSignal.geoChanged.emit(currentNote.getGuid(), lon, lat, alt);\r
1919                                         currentNote.getAttributes().setAltitude(alt);\r
1920                                         currentNote.getAttributes().setLongitude(lon);\r
1921                                         currentNote.getAttributes().setLatitude(lat);\r
1922                         }\r
1923                 }\r
1924                 \r
1925                 if (index == 2) {\r
1926                         noteSignal.geoChanged.emit(currentNote.getGuid(), 0.0, 0.0, 0.0);\r
1927                         currentNote.getAttributes().setAltitude(0.0);\r
1928                         currentNote.getAttributes().setLongitude(0.0);\r
1929                         currentNote.getAttributes().setLatitude(0.0);\r
1930                 }\r
1931                 \r
1932                 if (index == 3 || index == 0) {\r
1933                         QDesktopServices.openUrl(new QUrl("http://maps.google.com/maps?z=6&q="+currentNote.getAttributes().getLatitude() +"," +currentNote.getAttributes().getLongitude()));\r
1934                 }\r
1935         }\r
1936 \r
1937         // ************************************************************\r
1938         // * User chose to save an attachment. Pares out the request *\r
1939         // * into a guid & file. Save the result. *\r
1940         // ************************************************************\r
1941         public void downloadAttachment(QNetworkRequest request) {\r
1942                 String guid;\r
1943                 QFileDialog fd = new QFileDialog(this);\r
1944                 fd.setFileMode(FileMode.AnyFile);\r
1945                 fd.setConfirmOverwrite(true);\r
1946                 fd.setWindowTitle(tr("Save File"));\r
1947                 fd.setAcceptMode(AcceptMode.AcceptSave);\r
1948                 fd.setDirectory(System.getProperty("user.home"));\r
1949                 String name = request.url().toString();\r
1950 \r
1951                 int pos = name.lastIndexOf(Global.attachmentNameDelimeter);\r
1952                 if (pos > -1) {\r
1953                         guid = name.substring(0, pos).replace("nnres://", "");\r
1954                         name = name.substring(pos +Global.attachmentNameDelimeter.length());\r
1955                         fd.selectFile(name);\r
1956                         pos = name.lastIndexOf('.');\r
1957                         if (pos > -1) {\r
1958                                 String mimeType = "(*." + name.substring(pos + 1)\r
1959                                                 + ");; All Files (*)";\r
1960                                 fd.setFilter(tr(mimeType));\r
1961                         }\r
1962                 } else {\r
1963                         guid = name;\r
1964                 }\r
1965 \r
1966                 // Strip URL prefix and base dir\r
1967                 guid = guid.replace("nnres://", "")\r
1968                         .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");\r
1969 \r
1970                 pos = guid.lastIndexOf('.');\r
1971                 if (pos > 0)\r
1972                         guid = guid.substring(0,pos);\r
1973                 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {\r
1974                         name = name.replace('\\', '/');\r
1975                         Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);\r
1976                         QFile saveFile = new QFile(fd.selectedFiles().get(0));\r
1977                         QFile.OpenMode mode = new QFile.OpenMode();\r
1978                         mode.set(QFile.OpenModeFlag.WriteOnly);\r
1979                         saveFile.open(mode);\r
1980                         QDataStream saveOut = new QDataStream(saveFile);\r
1981                         QByteArray binData = new QByteArray(resBinary.getData().getBody());\r
1982                         saveOut.writeBytes(binData.toByteArray());\r
1983                         saveFile.close();\r
1984 \r
1985                 }\r
1986         }\r
1987 \r
1988         \r
1989         // ************************************************************\r
1990         // * User chose to save an attachment. Pares out the request *\r
1991         // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!   \r
1992         // ************************************************************\r
1993         // NFC TODO: unused? remove\r
1994         public void downloadImage(QNetworkRequest request) {\r
1995                 QFileDialog fd = new QFileDialog(this);\r
1996                 fd.setFileMode(FileMode.AnyFile);\r
1997                 fd.setConfirmOverwrite(true);\r
1998                 fd.setWindowTitle(tr("Save File"));\r
1999                 fd.setAcceptMode(AcceptMode.AcceptSave);\r
2000                 fd.setDirectory(System.getProperty("user.home"));\r
2001                 String name = request.url().toString();\r
2002                 name = name.replace("nnres://", "");\r
2003                 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());\r
2004                 name = name.replace(dPath, "");\r
2005                 int pos = name.lastIndexOf('.');\r
2006                 String guid = name;\r
2007                 if (pos > -1) {\r
2008                         String mimeType = "(*." + name.substring(pos + 1)\r
2009                         + ");; All Files (*)";\r
2010                                 fd.setFilter(tr(mimeType));\r
2011                         guid = guid.substring(0,pos);\r
2012                 }\r
2013                 pos = name.lastIndexOf(Global.attachmentNameDelimeter);\r
2014                 if (pos > -1) {\r
2015                         guid = name.substring(0, pos);\r
2016                         fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));             \r
2017                 }\r
2018                 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {\r
2019                         Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);\r
2020                         String fileName = fd.selectedFiles().get(0);\r
2021                         QFile saveFile = new QFile(fileName);\r
2022                         QFile.OpenMode mode = new QFile.OpenMode();\r
2023                         mode.set(QFile.OpenModeFlag.WriteOnly);\r
2024                         saveFile.open(mode);\r
2025                         QDataStream saveOut = new QDataStream(saveFile);\r
2026                         QByteArray binData = new QByteArray(resBinary.getData().getBody());\r
2027                         saveOut.writeBytes(binData.toByteArray());\r
2028                         saveFile.close();\r
2029                 }\r
2030         }\r
2031 \r
2032         \r
2033         // *************************************************************\r
2034         // * decrypt any hidden text.  We could do an XML parse, but \r
2035         // * it is quicker here just to scan for an <img tag & do the fix\r
2036         // * the manual way\r
2037         // *************************************************************\r
2038         private void removeEncryption(String id, String plainText, boolean permanent, String slot) {\r
2039                 if (!permanent) {\r
2040                         plainText = " <en-crypt-temp slot=\""+slot  +"\">" +plainText+"</en-crypt-temp> ";\r
2041                 }\r
2042                 \r
2043                 String html = browser.page().mainFrame().toHtml();\r
2044                 String text = html;\r
2045                 int imagePos = html.indexOf("<img");\r
2046                 int endPos;\r
2047                 for ( ;imagePos>0; ) {\r
2048                         // Find the end tag\r
2049                         endPos = text.indexOf(">", imagePos);\r
2050                         String tag = text.substring(imagePos-1,endPos);\r
2051                         if (tag.indexOf("id=\""+id+"\"") > -1) {\r
2052                                         text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);\r
2053                                                                                 \r
2054                                         browser.setContent(new QByteArray(text));\r
2055                                         contentChanged();\r
2056                         }\r
2057                         imagePos = text.indexOf("<img", imagePos+1);\r
2058                 }\r
2059         }\r
2060         \r
2061         \r
2062         //****************************************************************\r
2063         //* Focus shortcuts\r
2064         //****************************************************************\r
2065         @SuppressWarnings("unused")\r
2066         private void focusTitle() {\r
2067                 titleLabel.setFocus();\r
2068         }\r
2069         @SuppressWarnings("unused")\r
2070         private void focusTag() {\r
2071                 tagEdit.setFocus();\r
2072         }\r
2073         @SuppressWarnings("unused")\r
2074         private void focusNote() {\r
2075                 browser.setFocus();\r
2076         }\r
2077         @SuppressWarnings("unused")\r
2078         private void focusAuthor() {\r
2079                 authorLabel.setFocus();\r
2080         }\r
2081         @SuppressWarnings("unused")\r
2082         private void focusUrl() {\r
2083                 urlLabel.setFocus();\r
2084         }\r
2085         \r
2086 \r
2087         //*****************************************************************\r
2088         //* Set the document background color\r
2089         //*****************************************************************\r
2090         public void setBackgroundColor(String color) {\r
2091                 String js = "function changeBackground(color) {"\r
2092                         +"document.body.style.background = color;"\r
2093                         +"}" \r
2094                         +"changeBackground('" +color+"');";\r
2095                 browser.page().mainFrame().evaluateJavaScript(js);\r
2096                 contentChanged();\r
2097         }\r
2098         \r
2099         \r
2100         //****************************************************************\r
2101         //* MicroFocus changed\r
2102         //****************************************************************\r
2103         private void microFocusChanged() {\r
2104                 boldButton.setDown(false);\r
2105                 italicButton.setDown(false);\r
2106                 underlineButton.setDown(false);\r
2107                 browser.openAction.setEnabled(false);\r
2108                 browser.downloadAttachment.setEnabled(false);\r
2109                 browser.downloadImage.setEnabled(false);\r
2110                 browser.rotateImageLeft.setEnabled(false);\r
2111                 browser.rotateImageRight.setEnabled(false);\r
2112                 browser.insertTableAction.setEnabled(true);\r
2113                 browser.insertTableRowAction.setEnabled(false);\r
2114                 browser.deleteTableRowAction.setEnabled(false);\r
2115                 browser.insertLinkAction.setText(tr("Insert Hyperlink"));\r
2116                 currentHyperlink ="";\r
2117                 insideList = false;\r
2118                 forceTextPaste = false;\r
2119                 \r
2120                 String js = new String( "function getCursorPos() {"\r
2121                         +"var cursorPos;"\r
2122                         +"if (window.getSelection) {"\r
2123                         +"   var selObj = window.getSelection();"\r
2124                         +"   var selRange = selObj.getRangeAt(0);"\r
2125                         +"   var workingNode = window.getSelection().anchorNode.parentNode;"\r
2126                         +"   while(workingNode != null) { " \r
2127 //                      +"      window.jambi.printNode(workingNode.nodeName);"\r
2128                         +"      if (workingNode.nodeName=='EN-CRYPT-TEMP') window.jambi.forceTextPaste();"\r
2129                         +"      if (workingNode.nodeName=='B') window.jambi.boldActive();"\r
2130                         +"      if (workingNode.nodeName=='I') window.jambi.italicActive();"\r
2131                         +"      if (workingNode.nodeName=='U') window.jambi.underlineActive();"\r
2132                         +"      if (workingNode.nodeName=='UL') window.jambi.setInsideList();"\r
2133                         +"      if (workingNode.nodeName=='OL') window.jambi.setInsideList();"\r
2134                         +"      if (workingNode.nodeName=='LI') window.jambi.setInsideList();"\r
2135                         +"      if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"\r
2136                         +"      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
2137                         +"      if (workingNode.nodeName=='SPAN') {"\r
2138                         +"         if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"\r
2139                         +"      }"\r
2140                         +"      workingNode = workingNode.parentNode;"\r
2141                         +"   }"\r
2142                         +"}"\r
2143                         +"} getCursorPos();");\r
2144                 browser.page().mainFrame().evaluateJavaScript(js);\r
2145         }\r
2146         \r
2147         public void printNode(String n) {\r
2148                 System.out.println("Node Vaule: " +n);\r
2149         }\r
2150         \r
2151         \r
2152         //****************************************************************\r
2153         //* Insert a table row\r
2154         //****************************************************************\r
2155         public void insertTableRow() {\r
2156                 \r
2157                 String js = new String( "function insertTableRow() {"\r
2158                         +"   var selObj = window.getSelection();"\r
2159                         +"   var selRange = selObj.getRangeAt(0);"\r
2160                         +"   var workingNode = window.getSelection().anchorNode.parentNode;"\r
2161                         +"   var cellCount = 0;"\r
2162                         +"   while(workingNode != null) { " \r
2163                         +"      if (workingNode.nodeName.toLowerCase()=='tr') {"\r
2164                         +"           row = document.createElement('TR');"\r
2165                         +"           var nodes = workingNode.getElementsByTagName('td');"\r
2166                         +"           for (j=0; j<nodes.length; j=j+1) {"\r
2167                         +"              cell = document.createElement('TD');"\r
2168                         +"              cell.innerHTML='&nbsp;';"\r
2169                         +"              row.appendChild(cell);"\r
2170                         +"           }"                 \r
2171                         +"           workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"\r
2172                         +"           return;"\r
2173                         +"      }"\r
2174                         +"      workingNode = workingNode.parentNode;"\r
2175                         +"   }"\r
2176                         +"} insertTableRow();");\r
2177                 browser.page().mainFrame().evaluateJavaScript(js);\r
2178                 contentChanged();\r
2179         }\r
2180         //****************************************************************\r
2181         //* Insert a table row\r
2182         //****************************************************************\r
2183         public void deleteTableRow() {\r
2184                 \r
2185                 String js = new String( "function deleteTableRow() {"\r
2186                         +"   var selObj = window.getSelection();"\r
2187                         +"   var selRange = selObj.getRangeAt(0);"\r
2188                         +"   var workingNode = window.getSelection().anchorNode.parentNode;"\r
2189                         +"   var cellCount = 0;"\r
2190                         +"   while(workingNode != null) { " \r
2191                         +"      if (workingNode.nodeName.toLowerCase()=='tr') {"\r
2192                         +"           workingNode.parentNode.removeChild(workingNode);"\r
2193                         +"           return;"\r
2194                         +"      }"\r
2195                         +"      workingNode = workingNode.parentNode;"\r
2196                         +"   }"\r
2197                         +"} deleteTableRow();");\r
2198                 browser.page().mainFrame().evaluateJavaScript(js);\r
2199                 contentChanged();\r
2200         }\r
2201         public void setInsideTable() {\r
2202                 browser.insertTableRowAction.setEnabled(true);\r
2203                 browser.deleteTableRowAction.setEnabled(true);\r
2204                 browser.insertTableAction.setEnabled(false);\r
2205                 browser.encryptAction.setEnabled(false);\r
2206         }\r
2207         \r
2208         public void setInsideLink(String link) {\r
2209                 browser.insertLinkAction.setText(tr("Edit Hyperlink"));\r
2210                 currentHyperlink = link;\r
2211         }\r
2212         \r
2213         public void italicActive() {\r
2214                 italicButton.setDown(true);\r
2215         }\r
2216         public void boldActive() {\r
2217                 boldButton.setDown(true);\r
2218         }\r
2219         public void underlineActive() {\r
2220                 underlineButton.setDown(true);\r
2221         }\r
2222         public void forceTextPaste() {\r
2223                 forceTextPaste = true;\r
2224         }\r
2225         public void imageContextMenu(String f) {\r
2226                 browser.downloadImage.setEnabled(true);\r
2227                 browser.rotateImageRight.setEnabled(true);\r
2228                 browser.rotateImageLeft.setEnabled(true);\r
2229                 browser.openAction.setEnabled(true);\r
2230                 selectedFile = f;\r
2231         }\r
2232         public void rotateImageRight() {\r
2233                 QWebSettings.setMaximumPagesInCache(0);\r
2234                 QWebSettings.setObjectCacheCapacities(0, 0, 0);\r
2235                 QImage image = new QImage(selectedFile);\r
2236                 QMatrix matrix = new QMatrix();\r
2237                 matrix.rotate( 90.0 );\r
2238                 image = image.transformed(matrix);\r
2239                 image.save(selectedFile);\r
2240                 QWebSettings.setMaximumPagesInCache(0);\r
2241                 QWebSettings.setObjectCacheCapacities(0, 0, 0);\r
2242                 browser.setHtml(browser.page().mainFrame().toHtml());\r
2243                 browser.reload();\r
2244                 contentChanged();\r
2245 //              resourceSignal.contentChanged.emit(selectedFile);\r
2246 \r
2247         }\r
2248         public void rotateImageLeft() {\r
2249                 QImage image = new QImage(selectedFile);\r
2250                 QMatrix matrix = new QMatrix();\r
2251                 matrix.rotate( -90.0 );\r
2252                 image = image.transformed(matrix);\r
2253                 image.save(selectedFile);\r
2254                 browser.setHtml(browser.page().mainFrame().toHtml());\r
2255                 browser.reload();\r
2256                 contentChanged();\r
2257 //              resourceSignal.contentChanged.emit(selectedFile);\r
2258         }\r
2259         public void resourceContextMenu(String f) {\r
2260                 browser.downloadAttachment.setEnabled(true);\r
2261                 browser.openAction.setEnabled(true);\r
2262                 selectedFile = f;\r
2263         }\r
2264         \r
2265         \r
2266         //****************************************************************\r
2267         //* Apply CSS style to specified word\r
2268         //****************************************************************\r
2269 /*      public void applyStyleToWords(String word, String style) {\r
2270                 QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");\r
2271                 script.open(OpenModeFlag.ReadOnly);\r
2272                 String s = script.readAll().toString();\r
2273                 String js = new String(s +" findit('"+word+"', '"+style+"');");\r
2274                 browser.page().mainFrame().evaluateJavaScript(js);\r
2275                 System.out.println(getContent());\r
2276         }\r
2277 */      \r
2278         //****************************************************************\r
2279         //* Someone tried to paste a resource between notes, so we need  *\r
2280         //* to do some special handling.                                 *\r
2281         //****************************************************************\r
2282         private String fixInternotePaste(String text) {\r
2283                 logger.log(logger.EXTREME, "Fixing internote paste");\r
2284                 String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");\r
2285                 return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");\r
2286         }\r
2287         private String fixInternotePasteSearch(String text, String type, String locTag) {\r
2288                 \r
2289                 // First, let's fix the images.\r
2290                 int startPos = text.indexOf(type);\r
2291                 int endPos;\r
2292                 for (; startPos>=0;) {\r
2293                         endPos = text.indexOf(">", startPos+1);\r
2294                         String segment = text.substring(startPos, endPos);\r
2295                         if (segment.indexOf("en-tag") > -1) {\r
2296                                 String newSegment = segment;\r
2297                                 \r
2298                                 int guidStartPos = segment.indexOf("guid=\"");\r
2299                                 int guidEndPos = segment.indexOf("\"", guidStartPos+7);\r
2300                                 String guid = segment.substring(guidStartPos+6,guidEndPos);\r
2301                                 \r
2302                                 Calendar currentTime = new GregorianCalendar();\r
2303                                 Long l = new Long(currentTime.getTimeInMillis());\r
2304                                 long prevTime = l;\r
2305                                 while (l==prevTime) {\r
2306                                         currentTime = new GregorianCalendar();\r
2307                                         l= new Long(currentTime.getTimeInMillis());\r
2308                                 }\r
2309                                 \r
2310                                 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);\r
2311                                 if (r==null)\r
2312                                         return "";\r
2313                         String randint = new String(Long.toString(l));\r
2314                         String extension = null;\r
2315                         if (r.getMime()!= null) {\r
2316                                 extension = r.getMime().toLowerCase();\r
2317                                 if (extension.indexOf("/")>-1)\r
2318                                         extension = extension.substring(extension.indexOf("/")+1);\r
2319                         }\r
2320                         String newFile = randint;\r
2321                         if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")\r
2322                                 if (!locTag.startsWith("src"))\r
2323                                         newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();\r
2324                         r.setNoteGuid(currentNote.getGuid());\r
2325                         \r
2326                         r.setGuid(randint);\r
2327                         conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);\r
2328                                 QFile f = new QFile(Global.getFileManager().getResDirPath(newFile));\r
2329                                 QByteArray bin = new QByteArray(r.getData().getBody());\r
2330                                 f.open(QFile.OpenModeFlag.WriteOnly);\r
2331                                 f.write(bin);\r
2332                                 f.close();\r
2333                                 newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);\r
2334                                 currentNote.getResources().add(r);\r
2335                                 \r
2336                                 int startSrcPos = newSegment.indexOf(locTag);\r
2337                                 int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);\r
2338                                 String source; \r
2339                                 if (locTag.startsWith("src")) {\r
2340                                          source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);\r
2341                                                 newSegment = newSegment.replace(source,\r
2342                                                         FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath(newFile)));\r
2343                                 } else {\r
2344                                         source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);\r
2345                                         newSegment = newSegment.replace(source, newFile);\r
2346                                 }\r
2347                                 \r
2348                                 text = text.substring(0,startPos) + newSegment + text.substring(endPos);\r
2349                         }\r
2350                         startPos = text.indexOf(type, startPos+1);\r
2351                 }\r
2352                 return text;\r
2353         }\r
2354 \r
2355 \r
2356         public void nextPage(String file) {\r
2357                 logger.log(logger.EXTREME, "Starting nextPage()");\r
2358                 \r
2359                 Integer pageNumber;\r
2360                 if (previewPageList.containsKey(file))\r
2361                         pageNumber = previewPageList.get(file)+1;\r
2362                 else\r
2363                         pageNumber = 2;\r
2364                 previewPageList.remove(file);\r
2365                 previewPageList.put(file, pageNumber);\r
2366                 PDFPreview pdfPreview = new PDFPreview();\r
2367                 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);\r
2368                 if (goodPreview) {\r
2369 \r
2370 //                      String html = getContent();\r
2371                         QWebSettings.setMaximumPagesInCache(0);\r
2372                         QWebSettings.setObjectCacheCapacities(0, 0, 0);\r
2373 //                      browser.setContent(new QByteArray());\r
2374                         browser.setHtml(browser.page().mainFrame().toHtml());\r
2375                         browser.reload();\r
2376 //                      browser.setContent(new QByteArray(html));\r
2377 //                      browser.triggerPageAction(WebAction.Reload);\r
2378 //                      pdfMouseOver(selectedFile);\r
2379                 }\r
2380         }\r
2381 \r
2382         public void previousPage(String file) {\r
2383                 logger.log(logger.EXTREME, "Starting previousPage()");\r
2384                 \r
2385                 Integer pageNumber;\r
2386                 if (previewPageList.containsKey(file))\r
2387                         pageNumber = previewPageList.get(file)-1;\r
2388                 else\r
2389                         pageNumber = 1;\r
2390                 previewPageList.remove(file);\r
2391                 previewPageList.put(file, pageNumber);\r
2392                 PDFPreview pdfPreview = new PDFPreview();\r
2393                 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);\r
2394                 if (goodPreview) {\r
2395 \r
2396 //                      String html = getContent();\r
2397                         QWebSettings.setMaximumPagesInCache(0);\r
2398                         QWebSettings.setObjectCacheCapacities(0, 0, 0);\r
2399                         browser.setHtml(browser.page().mainFrame().toHtml());\r
2400                         browser.reload();\r
2401 //                      browser.setContent(new QByteArray(html));\r
2402 //                      browser.triggerPageAction(WebAction.Reload);\r
2403                 }\r
2404         }\r
2405         \r
2406 /*      public void pdfMouseOver(String name) { \r
2407                 int pageNumber;\r
2408                 if (previewPageList.containsKey(selectedFile))\r
2409                         pageNumber = previewPageList.get(selectedFile)+1;\r
2410                 else\r
2411                         pageNumber = 1;\r
2412                 \r
2413                 if (pageNumber <= 1)\r
2414                         browser.previousPageAction.setEnabled(false);\r
2415                 else\r
2416                         browser.previousPageAction.setEnabled(true);\r
2417                 \r
2418                 PDFPreview pdf = new PDFPreview();\r
2419                 int totalPages = pdf.getPageCount(name);\r
2420                 if (previewPageList.containsKey(selectedFile))\r
2421                         pageNumber = previewPageList.get(selectedFile)+1;\r
2422                 else\r
2423                         pageNumber = 1;\r
2424                 if (totalPages > pageNumber)\r
2425                         browser.nextPageAction.setEnabled(true);\r
2426                 else\r
2427                         browser.nextPageAction.setEnabled(false);\r
2428         }\r
2429         \r
2430 \r
2431         public void pdfMouseOut() { \r
2432 //              browser.nextPageAction.setVisible(false);\r
2433 //              browser.previousPageAction.setVisible(false);\r
2434         }\r
2435 */\r
2436 }\r