OSDN Git Service

Added inter-note links. Added index content controls. Altered Android Unicode test...
[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.io.FileNotFoundException;\r
24 import java.io.IOException;\r
25 import java.net.FileNameMap;\r
26 import java.net.URI;\r
27 import java.net.URLConnection;\r
28 import java.security.MessageDigest;\r
29 import java.security.NoSuchAlgorithmException;\r
30 import java.text.SimpleDateFormat;\r
31 import java.util.ArrayList;\r
32 import java.util.Calendar;\r
33 import java.util.Collections;\r
34 import java.util.Date;\r
35 import java.util.GregorianCalendar;\r
36 import java.util.HashMap;\r
37 import java.util.List;\r
38 import java.util.Locale;\r
39 import java.util.StringTokenizer;\r
40 \r
41 import org.apache.commons.lang.StringUtils;\r
42 \r
43 import com.evernote.edam.limits.Constants;\r
44 import com.evernote.edam.type.Data;\r
45 import com.evernote.edam.type.Note;\r
46 import com.evernote.edam.type.Notebook;\r
47 import com.evernote.edam.type.Resource;\r
48 import com.evernote.edam.type.ResourceAttributes;\r
49 import com.evernote.edam.type.Tag;\r
50 import com.swabunga.spell.engine.Configuration;\r
51 import com.swabunga.spell.engine.SpellDictionary;\r
52 import com.swabunga.spell.engine.SpellDictionaryHashMap;\r
53 import com.swabunga.spell.engine.Word;\r
54 import com.swabunga.spell.event.SpellCheckEvent;\r
55 import com.swabunga.spell.event.SpellCheckListener;\r
56 import com.swabunga.spell.event.SpellChecker;\r
57 import com.swabunga.spell.event.StringWordTokenizer;\r
58 import com.trolltech.qt.core.QByteArray;\r
59 import com.trolltech.qt.core.QCoreApplication;\r
60 import com.trolltech.qt.core.QDataStream;\r
61 import com.trolltech.qt.core.QDateTime;\r
62 import com.trolltech.qt.core.QEvent;\r
63 import com.trolltech.qt.core.QEvent.Type;\r
64 import com.trolltech.qt.core.QFile;\r
65 import com.trolltech.qt.core.QFileSystemWatcher;\r
66 import com.trolltech.qt.core.QIODevice;\r
67 import com.trolltech.qt.core.QMimeData;\r
68 import com.trolltech.qt.core.QTextCodec;\r
69 import com.trolltech.qt.core.QUrl;\r
70 import com.trolltech.qt.core.Qt;\r
71 import com.trolltech.qt.core.Qt.Key;\r
72 import com.trolltech.qt.core.Qt.KeyboardModifier;\r
73 import com.trolltech.qt.core.Qt.KeyboardModifiers;\r
74 import com.trolltech.qt.gui.QAction;\r
75 import com.trolltech.qt.gui.QApplication;\r
76 import com.trolltech.qt.gui.QCalendarWidget;\r
77 import com.trolltech.qt.gui.QClipboard;\r
78 import com.trolltech.qt.gui.QClipboard.Mode;\r
79 import com.trolltech.qt.gui.QColor;\r
80 import com.trolltech.qt.gui.QComboBox;\r
81 import com.trolltech.qt.gui.QDateEdit;\r
82 import com.trolltech.qt.gui.QDesktopServices;\r
83 import com.trolltech.qt.gui.QFileDialog;\r
84 import com.trolltech.qt.gui.QFileDialog.AcceptMode;\r
85 import com.trolltech.qt.gui.QFileDialog.FileMode;\r
86 import com.trolltech.qt.gui.QFontDatabase;\r
87 import com.trolltech.qt.gui.QFormLayout;\r
88 import com.trolltech.qt.gui.QGridLayout;\r
89 import com.trolltech.qt.gui.QHBoxLayout;\r
90 import com.trolltech.qt.gui.QIcon;\r
91 import com.trolltech.qt.gui.QImage;\r
92 import com.trolltech.qt.gui.QKeyEvent;\r
93 import com.trolltech.qt.gui.QKeySequence;\r
94 import com.trolltech.qt.gui.QLabel;\r
95 import com.trolltech.qt.gui.QLineEdit;\r
96 import com.trolltech.qt.gui.QListWidgetItem;\r
97 import com.trolltech.qt.gui.QMatrix;\r
98 import com.trolltech.qt.gui.QMessageBox;\r
99 import com.trolltech.qt.gui.QPalette;\r
100 import com.trolltech.qt.gui.QPalette.ColorRole;\r
101 import com.trolltech.qt.gui.QPushButton;\r
102 import com.trolltech.qt.gui.QShortcut;\r
103 import com.trolltech.qt.gui.QTimeEdit;\r
104 import com.trolltech.qt.gui.QToolButton;\r
105 import com.trolltech.qt.gui.QToolButton.ToolButtonPopupMode;\r
106 import com.trolltech.qt.gui.QVBoxLayout;\r
107 import com.trolltech.qt.gui.QWidget;\r
108 import com.trolltech.qt.network.QNetworkAccessManager;\r
109 import com.trolltech.qt.network.QNetworkReply;\r
110 import com.trolltech.qt.network.QNetworkReply.NetworkError;\r
111 import com.trolltech.qt.network.QNetworkRequest;\r
112 import com.trolltech.qt.webkit.QWebPage;\r
113 import com.trolltech.qt.webkit.QWebPage.WebAction;\r
114 import com.trolltech.qt.webkit.QWebSettings;\r
115 import com.trolltech.qt.webkit.QWebView;\r
116 \r
117 import cx.fbn.nevernote.Global;\r
118 import cx.fbn.nevernote.dialog.EnCryptDialog;\r
119 import cx.fbn.nevernote.dialog.EnDecryptDialog;\r
120 import cx.fbn.nevernote.dialog.GeoDialog;\r
121 import cx.fbn.nevernote.dialog.InsertLatexImage;\r
122 import cx.fbn.nevernote.dialog.InsertLinkDialog;\r
123 import cx.fbn.nevernote.dialog.SpellCheck;\r
124 import cx.fbn.nevernote.dialog.TableDialog;\r
125 import cx.fbn.nevernote.dialog.TagAssign;\r
126 import cx.fbn.nevernote.evernote.EnCrypt;\r
127 import cx.fbn.nevernote.filters.FilterEditorTags;\r
128 import cx.fbn.nevernote.signals.NoteResourceSignal;\r
129 import cx.fbn.nevernote.signals.NoteSignal;\r
130 import cx.fbn.nevernote.sql.DatabaseConnection;\r
131 import cx.fbn.nevernote.utilities.ApplicationLogger;\r
132 import cx.fbn.nevernote.utilities.FileUtils;\r
133 import cx.fbn.nevernote.utilities.Pair;\r
134 import cx.fbn.nevernote.xml.HtmlTagModifier;\r
135 \r
136 public class BrowserWindow extends QWidget {\r
137 \r
138         public final QLineEdit titleLabel;\r
139         private final QLineEdit urlText;\r
140         private final QLabel authorLabel;\r
141         private final QLineEdit authorText;\r
142         private final QComboBox geoBox;\r
143         public final TagLineEdit tagEdit;\r
144         public final QLabel tagLabel;\r
145         private final QPushButton urlLabel;\r
146         private final QLabel alteredLabel;\r
147         private final QDateEdit alteredDate;\r
148         private final QTimeEdit alteredTime;\r
149         private final QDateEdit createdDate;\r
150         private final QTimeEdit createdTime;\r
151         private final QLabel subjectLabel;\r
152         private final QDateEdit subjectDate;\r
153         private final QTimeEdit subjectTime;\r
154         public final QComboBox notebookBox;\r
155         private final QLabel notebookLabel;\r
156         private final QLabel createdLabel;\r
157         public final QComboBox fontSize;\r
158         public final QAction    fontSizeAction;\r
159         private boolean extendedOn;\r
160         public boolean buttonsVisible;\r
161         private final String iconPath = new String("classpath:cx/fbn/nevernote/icons/");\r
162         private final ContentView browser;\r
163         private List<Tag> allTags;\r
164         private List<String> currentTags;\r
165         public NoteSignal noteSignal;\r
166         public Signal2<String,String> evernoteLinkClicked;\r
167         private List<Notebook> notebookList;\r
168         private Note currentNote;\r
169         private String saveNoteTitle;\r
170         private String saveTagList;\r
171         private boolean insideList;\r
172         private final DatabaseConnection conn;\r
173         private final QCalendarWidget createdCalendarWidget;\r
174         private final QCalendarWidget alteredCalendarWidget;\r
175         private final QCalendarWidget subjectCalendarWidget;\r
176 \r
177         public final QPushButton undoButton;\r
178         public final QAction    undoAction;\r
179         public final QPushButton redoButton;\r
180         public final QAction    redoAction;\r
181         public final QPushButton cutButton;\r
182         public final QAction    cutAction;\r
183         public final QPushButton copyButton;\r
184         public final QAction    copyAction;\r
185         public final QPushButton pasteButton;\r
186         public final QAction    pasteAction;\r
187         public final QPushButton boldButton;\r
188         public final QAction    boldAction;\r
189         public final QPushButton underlineButton;\r
190         public final QAction    underlineAction;\r
191         public final QPushButton italicButton;\r
192         public final QAction    italicAction;\r
193         public final Signal0 focusLost;\r
194         public final NoteResourceSignal resourceSignal;\r
195 \r
196         public QPushButton rightAlignButton;\r
197         public final QAction    rightAlignAction;\r
198         public QPushButton leftAlignButton;\r
199         public final QAction    leftAlignAction;\r
200         public QPushButton centerAlignButton;\r
201         public final QAction    centerAlignAction;\r
202 \r
203         public final QPushButton strikethroughButton;\r
204         public final QAction    strikethroughAction;\r
205         public final QPushButton hlineButton;\r
206         public final QAction    hlineAction;\r
207         public final QPushButton indentButton;\r
208         public final QAction    indentAction;\r
209         public final QPushButton outdentButton;\r
210         public final QAction    outdentAction;\r
211         public final QPushButton bulletListButton;\r
212         public final QAction    bulletListAction;\r
213         public final QPushButton numberListButton;\r
214         public final QAction    numberListAction;\r
215         public final QPushButton spellCheckButton;\r
216         public final QAction    spellCheckAction;\r
217         public final QPushButton todoButton;\r
218         public final QAction    todoAction;\r
219 \r
220         public final QShortcut focusTitleShortcut;\r
221         public final QShortcut focusTagShortcut;\r
222         public final QShortcut focusNoteShortcut;\r
223         public final QShortcut focusUrlShortcut;\r
224         public final QShortcut focusAuthorShortcut;\r
225         \r
226         public EditorButtonBar buttonLayout;\r
227         public final QComboBox fontList;\r
228         public final QAction    fontListAction;\r
229         public final QToolButton fontColor;\r
230         public final QAction    fontColorAction;\r
231         private final ColorMenu fontColorMenu;\r
232         public final QToolButton fontHilight;\r
233         public final QAction    fontHilightAction;\r
234         private final ColorMenu fontHilightColorMenu;\r
235         public final QFileSystemWatcher fileWatcher;\r
236         public int cursorPosition;\r
237         private boolean forceTextPaste = false;\r
238         private String selectedFile;\r
239         private String currentHyperlink;\r
240         public boolean keepPDFNavigationHidden;\r
241         private final ApplicationLogger logger;\r
242         SpellDictionary dictionary;\r
243     SpellDictionary userDictionary;\r
244     SpellChecker spellChecker;\r
245     SuggestionListener spellListener;\r
246         private final HashMap<String,Integer> previewPageList;  \r
247         boolean insertHyperlink = true;\r
248         boolean insideTable = false;\r
249         boolean insideEncryption = false;\r
250         public Signal1<BrowserWindow> blockApplication;\r
251         public Signal0 unblockApplication;\r
252         public boolean awaitingHttpResponse;\r
253         public long     unblockTime;\r
254         String latexGuid;  // This is set if we are editing an existing LaTeX formula.  Useful to track guid.\r
255 \r
256         \r
257         public static class SuggestionListener implements SpellCheckListener {\r
258                 public boolean abortSpellCheck = false;\r
259                 public boolean errorsFound = false;\r
260                 private final SpellCheck                spellCheckDialog;\r
261                 \r
262                 \r
263                 private final BrowserWindow parent;\r
264                 public SuggestionListener(BrowserWindow parent, SpellChecker checker) {\r
265                         this.parent = parent;\r
266                         spellCheckDialog = new SpellCheck(checker);\r
267                 }\r
268                 public void spellingError(SpellCheckEvent event) {\r
269                         errorsFound = true;\r
270                         spellCheckDialog.setWord(event.getInvalidWord());\r
271 \r
272                     @SuppressWarnings("unchecked")\r
273                         List<Word> suggestions = event.getSuggestions();\r
274                     spellCheckDialog.clearSuggestions();\r
275                     if (!suggestions.isEmpty()) {\r
276 //                     spellCheckDialog.setCurrentSuggestion(suggestions.get(0).getWord());\r
277                        for (int i=0; i<suggestions.size(); i++) {\r
278                           spellCheckDialog.addSuggestion(suggestions.get(i).getWord());\r
279                        }\r
280                        spellCheckDialog.setSelectedSuggestion(0);\r
281                     }\r
282                     spellCheckDialog.exec();\r
283                     if (spellCheckDialog.cancelPressed()) {\r
284                         abortSpellCheck = true;\r
285                         event.cancel();\r
286                         return;\r
287                     }\r
288                     if (spellCheckDialog.replacePressed()) {\r
289                         QClipboard clipboard = QApplication.clipboard();\r
290                         clipboard.setText(spellCheckDialog.getReplacementWord()); \r
291                         parent.pasteClicked();\r
292                     }\r
293                     event.cancel();\r
294                  }\r
295         }\r
296 \r
297         \r
298         \r
299         public BrowserWindow(DatabaseConnection c) {\r
300                 logger = new ApplicationLogger("browser.log");\r
301                 logger.log(logger.HIGH, "Setting up browser");\r
302                 \r
303                 fileWatcher = new QFileSystemWatcher();\r
304 //              fileWatcher.fileChanged.connect(this, "fileChanged(String)");\r
305                 noteSignal = new NoteSignal();\r
306                 titleLabel = new QLineEdit();\r
307                 evernoteLinkClicked = new Signal2<String,String>();\r
308                 titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX);\r
309                 urlText = new QLineEdit();\r
310                 authorText = new QLineEdit();\r
311                 geoBox = new QComboBox();\r
312                 urlLabel = new QPushButton();\r
313                 urlLabel.clicked.connect(this, "sourceUrlClicked()");\r
314                 authorLabel = new QLabel();\r
315                 conn = c;\r
316                 \r
317                 focusLost = new Signal0();\r
318 \r
319                 tagEdit = new TagLineEdit(allTags);\r
320                 tagLabel = new QLabel(tr("Tags:"));\r
321                 tagEdit.focusLost.connect(this, "modifyTagsTyping()");\r
322 \r
323                 createdCalendarWidget = new QCalendarWidget();\r
324                 createdDate = new QDateEdit();\r
325                 createdDate.setDisplayFormat(Global.getDateFormat());\r
326                 createdDate.setCalendarPopup(true);\r
327                 createdDate.setCalendarWidget(createdCalendarWidget);\r
328                 createdTime = new QTimeEdit();\r
329                 createdDate.dateChanged.connect(this, "createdChanged()");\r
330                 createdTime.timeChanged.connect(this, "createdChanged()");\r
331 \r
332                 alteredCalendarWidget = new QCalendarWidget();\r
333                 alteredDate = new QDateEdit();\r
334                 alteredDate.setDisplayFormat(Global.getDateFormat());\r
335                 alteredDate.setCalendarPopup(true);\r
336                 alteredDate.setCalendarWidget(alteredCalendarWidget);\r
337                 alteredTime = new QTimeEdit();\r
338                 alteredLabel = new QLabel(tr("Altered:"));\r
339                 alteredDate.dateChanged.connect(this, "alteredChanged()");\r
340                 alteredTime.timeChanged.connect(this, "alteredChanged()");\r
341 \r
342                 subjectCalendarWidget = new QCalendarWidget();\r
343                 subjectDate = new QDateEdit();\r
344                 subjectDate.setDisplayFormat(Global.getDateFormat());\r
345                 subjectDate.setCalendarPopup(true);\r
346                 subjectDate.setCalendarWidget(subjectCalendarWidget);\r
347                 subjectTime = new QTimeEdit();\r
348                 subjectLabel = new QLabel(tr("Subject Date:"));\r
349                 subjectDate.dateChanged.connect(this, "subjectDateTimeChanged()");\r
350                 subjectTime.timeChanged.connect(this, "subjectDateTimeChanged()");\r
351                 authorText.textChanged.connect(this, "authorChanged()");\r
352                 urlText.textChanged.connect(this, "sourceUrlChanged()");\r
353 \r
354                 notebookBox = new QComboBox();\r
355                 notebookLabel = new QLabel(tr("Notebook"));\r
356                 createdLabel = new QLabel(tr("Created:"));\r
357                 // selectedText = new String();\r
358 \r
359                 urlLabel.setVisible(false);\r
360                 urlText.setVisible(false);\r
361                 authorLabel.setVisible(false);\r
362                 \r
363                 geoBox.setVisible(false);\r
364                 geoBox.addItem(new QIcon(iconPath+"globe.png"), "");\r
365                 geoBox.addItem(new String(tr("Set")));\r
366                 geoBox.addItem(new String(tr("Clear")));\r
367                 geoBox.addItem(new String(tr("View On Map")));\r
368                 geoBox.activated.connect(this, "geoBoxChanged()");\r
369                 \r
370                 authorText.setVisible(false);\r
371                 createdDate.setVisible(false);\r
372                 alteredLabel.setVisible(false);\r
373                 //notebookBox.setVisible(false);\r
374                 notebookLabel.setVisible(false);\r
375                 createdLabel.setVisible(false);\r
376                 createdTime.setVisible(false);\r
377                 alteredDate.setVisible(false);\r
378                 alteredTime.setVisible(false);\r
379                 subjectLabel.setVisible(false);\r
380                 subjectDate.setVisible(false);\r
381                 subjectTime.setVisible(false);\r
382                 extendedOn = false;\r
383                 buttonsVisible = true;\r
384                 setAcceptDrops(true);\r
385 \r
386                 browser = new ContentView(this);\r
387                 browser.page().setLinkDelegationPolicy(\r
388                                 QWebPage.LinkDelegationPolicy.DelegateAllLinks);\r
389                 browser.linkClicked.connect(this, "linkClicked(QUrl)");\r
390                 currentHyperlink = "";\r
391                 \r
392                 QVBoxLayout v = new QVBoxLayout();\r
393                 QFormLayout notebookLayout = new QFormLayout();\r
394                 QGridLayout dateLayout = new QGridLayout();\r
395                 titleLabel.setReadOnly(false);\r
396                 titleLabel.editingFinished.connect(this, "titleEdited()");\r
397                 browser.page().contentsChanged.connect(this, "contentChanged()");\r
398                 browser.page().selectionChanged.connect(this, "selectionChanged()");\r
399                 browser.page().mainFrame().javaScriptWindowObjectCleared.connect(this,\r
400                                 "exposeToJavascript()");\r
401 \r
402                 notebookBox.activated.connect(this, "notebookChanged()");\r
403                 resourceSignal = new NoteResourceSignal();\r
404                 \r
405                 QHBoxLayout tagLayout = new QHBoxLayout();\r
406                 v.addWidget(titleLabel, 0);\r
407                 notebookLayout.addRow(notebookLabel, notebookBox);\r
408                 tagLayout.addLayout(notebookLayout, 0);\r
409                 tagLayout.stretch(4);\r
410                 tagLayout.addWidget(tagLabel, 0);\r
411                 tagLayout.addWidget(tagEdit, 1);\r
412                 v.addLayout(tagLayout);\r
413 \r
414                 QHBoxLayout urlLayout = new QHBoxLayout();\r
415                 urlLayout.addWidget(urlLabel, 0);\r
416                 urlLayout.addWidget(urlText, 0);\r
417                 v.addLayout(urlLayout);\r
418 \r
419                 QHBoxLayout authorLayout = new QHBoxLayout();\r
420                 authorLayout.addWidget(authorLabel, 0);\r
421                 authorLayout.addWidget(authorText, 0);\r
422                 authorLayout.addWidget(geoBox);\r
423                 v.addLayout(authorLayout);\r
424 \r
425                 dateLayout.addWidget(createdLabel, 0, 0);\r
426                 dateLayout.addWidget(createdDate, 0, 1);\r
427                 dateLayout.addWidget(createdTime, 0, 2);\r
428                 dateLayout.setColumnStretch(9, 100);\r
429                 dateLayout.addWidget(alteredLabel, 0, 3);\r
430                 dateLayout.addWidget(alteredDate, 0, 4);\r
431                 dateLayout.addWidget(alteredTime, 0, 5);\r
432                 dateLayout.addWidget(subjectLabel, 0, 6);\r
433                 dateLayout.addWidget(subjectDate, 0, 7);\r
434                 dateLayout.addWidget(subjectTime, 0, 8);\r
435                 v.addLayout(dateLayout, 0);\r
436 \r
437                 undoButton = newEditorButton("undo", tr("Undo Change"));\r
438                 redoButton = newEditorButton("redo", tr("Redo Change"));\r
439                 cutButton = newEditorButton("cut", tr("Cut"));\r
440                 copyButton = newEditorButton("copy", tr("Copy"));\r
441                 pasteButton = newEditorButton("paste", tr("Paste"));\r
442                 boldButton = newEditorButton("bold", tr("Bold"));\r
443                 underlineButton = newEditorButton("underline", tr("Underline"));\r
444                 italicButton = newEditorButton("italic", tr("Italic"));\r
445 \r
446                 rightAlignButton = newEditorButton("justifyRight", tr("Right Align"));\r
447                 leftAlignButton = newEditorButton("justifyLeft", tr("Left Align"));\r
448                 centerAlignButton = newEditorButton("justifyCenter", tr("Center Align"));\r
449 \r
450                 strikethroughButton = newEditorButton("strikethrough", tr("Strikethrough"));\r
451                 hlineButton = newEditorButton("hline", tr("Insert Horizontal Line"));\r
452                 indentButton = newEditorButton("indent", tr("Shift Right"));\r
453                 outdentButton = newEditorButton("outdent", tr("Shift Left"));\r
454                 bulletListButton = newEditorButton("bulletList", tr("Bullet List"));\r
455                 numberListButton = newEditorButton("numberList", tr("Number List"));\r
456                 spellCheckButton = newEditorButton("spellCheck", tr("Spell Check"));\r
457                 todoButton = newEditorButton("todo", tr("To-do"));\r
458 \r
459                 \r
460                 buttonLayout = new EditorButtonBar();\r
461                 v.addWidget(buttonLayout);\r
462                 \r
463                 undoAction = buttonLayout.addWidget(undoButton);\r
464                 buttonLayout.toggleUndoVisible.triggered.connect(this, "toggleUndoVisible(Boolean)");\r
465                 redoAction = buttonLayout.addWidget(redoButton);\r
466                 buttonLayout.toggleRedoVisible.triggered.connect(this, "toggleRedoVisible(Boolean)");\r
467                 \r
468                 buttonLayout.addWidget(newSeparator());\r
469                 cutAction = buttonLayout.addWidget(cutButton);\r
470                 buttonLayout.toggleCutVisible.triggered.connect(this, "toggleCutVisible(Boolean)");\r
471                 copyAction = buttonLayout.addWidget(copyButton);\r
472                 buttonLayout.toggleCopyVisible.triggered.connect(this, "toggleCopyVisible(Boolean)");\r
473                 pasteAction = buttonLayout.addWidget(pasteButton);\r
474                 buttonLayout.togglePasteVisible.triggered.connect(this, "togglePasteVisible(Boolean)");\r
475 \r
476                 buttonLayout.addWidget(newSeparator());\r
477                 boldAction = buttonLayout.addWidget(boldButton);\r
478                 buttonLayout.toggleBoldVisible.triggered.connect(this, "toggleBoldVisible(Boolean)");\r
479                 italicAction = buttonLayout.addWidget(italicButton);\r
480                 buttonLayout.toggleItalicVisible.triggered.connect(this, "toggleItalicVisible(Boolean)");\r
481                 underlineAction = buttonLayout.addWidget(underlineButton);\r
482                 buttonLayout.toggleUnderlineVisible.triggered.connect(this, "toggleUnderlineVisible(Boolean)");\r
483                 strikethroughAction = buttonLayout.addWidget(strikethroughButton);\r
484                 buttonLayout.toggleStrikethroughVisible.triggered.connect(this, "toggleStrikethroughVisible(Boolean)");\r
485 \r
486                 \r
487                 buttonLayout.addWidget(newSeparator());\r
488                 leftAlignAction = buttonLayout.addWidget(leftAlignButton);\r
489                 buttonLayout.toggleLeftAlignVisible.triggered.connect(this, "toggleLeftAlignVisible(Boolean)");\r
490                 centerAlignAction = buttonLayout.addWidget(centerAlignButton);\r
491                 buttonLayout.toggleCenterAlignVisible.triggered.connect(this, "toggleCenterAlignVisible(Boolean)");\r
492                 rightAlignAction = buttonLayout.addWidget(rightAlignButton);\r
493                 buttonLayout.toggleRightAlignVisible.triggered.connect(this, "toggleRightAlignVisible(Boolean)");\r
494 \r
495                 buttonLayout.addWidget(newSeparator());\r
496                 hlineAction = buttonLayout.addWidget(hlineButton);\r
497                 buttonLayout.toggleHLineVisible.triggered.connect(this, "toggleHLineVisible(Boolean)");\r
498 \r
499                 indentAction = buttonLayout.addWidget(indentButton);\r
500                 buttonLayout.toggleIndentVisible.triggered.connect(this, "toggleIndentVisible(Boolean)");\r
501                 outdentAction = buttonLayout.addWidget(outdentButton);\r
502                 buttonLayout.toggleOutdentVisible.triggered.connect(this, "toggleOutdentVisible(Boolean)");\r
503                 bulletListAction = buttonLayout.addWidget(bulletListButton);\r
504                 buttonLayout.toggleBulletListVisible.triggered.connect(this, "toggleBulletListVisible(Boolean)");\r
505                 numberListAction = buttonLayout.addWidget(numberListButton);\r
506                 buttonLayout.toggleNumberListVisible.triggered.connect(this, "toggleNumberListVisible(Boolean)");\r
507 \r
508                 // Setup the font & font size combo boxes\r
509                 buttonLayout.addWidget(newSeparator());\r
510                 fontList = new QComboBox();\r
511                 fontSize = new QComboBox();\r
512                 fontList.setToolTip("Font");\r
513                 fontSize.setToolTip("Font Size");\r
514                 fontList.activated.connect(this, "fontChanged(String)");\r
515                 fontSize.activated.connect(this, "fontSizeChanged(String)");\r
516                 fontListAction = buttonLayout.addWidget(fontList);\r
517                 buttonLayout.toggleFontVisible.triggered.connect(this, "toggleFontListVisible(Boolean)");\r
518                 fontSizeAction = buttonLayout.addWidget(fontSize);\r
519                 buttonLayout.toggleFontSizeVisible.triggered.connect(this, "toggleFontSizeVisible(Boolean)");\r
520                 QFontDatabase fonts = new QFontDatabase();\r
521                 List<String> fontFamilies = fonts.families();\r
522                 for (int i = 0; i < fontFamilies.size(); i++) {\r
523                         fontList.addItem(fontFamilies.get(i));\r
524                         if (i == 0) {\r
525                                 loadFontSize(fontFamilies.get(i));\r
526                         }\r
527                 }\r
528 \r
529 //              buttonLayout.addWidget(newSeparator(), 0);\r
530                 fontColor = newToolButton("fontColor", tr("Font Color"));\r
531                 fontColorMenu = new ColorMenu(this);\r
532                 fontColor.setMenu(fontColorMenu.getMenu());\r
533                 fontColor.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);\r
534                 fontColor.setAutoRaise(false);\r
535                 fontColorMenu.getMenu().triggered.connect(this, "fontColorClicked()");\r
536                 fontColorAction = buttonLayout.addWidget(fontColor);\r
537                 buttonLayout.toggleFontColorVisible.triggered.connect(this, "toggleFontColorVisible(Boolean)");\r
538                 fontHilight = newToolButton("fontHilight", tr("Font Hilight Color"));\r
539                 fontHilight.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);\r
540                 fontHilight.setAutoRaise(false);\r
541                 fontHilightColorMenu = new ColorMenu(this);\r
542                 fontHilightColorMenu.setDefault(QColor.yellow);\r
543                 fontHilight.setMenu(fontHilightColorMenu.getMenu());\r
544                 fontHilightColorMenu.getMenu().triggered.connect(this, "fontHilightClicked()");\r
545                 fontHilightAction = buttonLayout.addWidget(fontHilight);\r
546                 fontHilightColorMenu.setDefault(QColor.yellow);\r
547                 buttonLayout.toggleFontHilight.triggered.connect(this, "toggleFontHilightVisible(Boolean)");\r
548                 \r
549                 spellCheckAction = buttonLayout.addWidget(spellCheckButton);\r
550                 buttonLayout.toggleNumberListVisible.triggered.connect(this, "spellCheckClicked()");\r
551                 buttonLayout.toggleSpellCheck.triggered.connect(this, "toggleSpellCheckVisible(Boolean)");\r
552                 \r
553                 todoAction = buttonLayout.addWidget(todoButton);\r
554                 buttonLayout.toggleNumberListVisible.triggered.connect(this, "todoClicked()");\r
555                 buttonLayout.toggleTodo.triggered.connect(this, "toggleTodoVisible(Boolean)");\r
556 \r
557 \r
558 //              buttonLayout.addWidget(new QLabel(), 1);\r
559                 v.addWidget(browser, 1);\r
560                 setLayout(v);\r
561 \r
562                 browser.downloadAttachmentRequested.connect(this,\r
563                                 "downloadAttachment(QNetworkRequest)");\r
564                 browser.downloadImageRequested.connect(this,\r
565                                 "downloadImage(QNetworkRequest)");\r
566                 setTabOrder(notebookBox, tagEdit);\r
567                 setTabOrder(tagEdit, browser);\r
568                 \r
569                 focusNoteShortcut = new QShortcut(this);\r
570                 setupShortcut(focusNoteShortcut, "Focus_Note");\r
571                 focusNoteShortcut.activated.connect(this, "focusNote()");\r
572                 focusTitleShortcut = new QShortcut(this);\r
573                 setupShortcut(focusTitleShortcut, "Focus_Title");\r
574                 focusTitleShortcut.activated.connect(this, "focusTitle()");\r
575                 focusTagShortcut = new QShortcut(this);\r
576                 setupShortcut(focusTagShortcut, "Focus_Tag");\r
577                 focusTagShortcut.activated.connect(this, "focusTag()");\r
578                 focusAuthorShortcut = new QShortcut(this);\r
579                 setupShortcut(focusAuthorShortcut, "Focus_Author");\r
580                 focusAuthorShortcut.activated.connect(this, "focusAuthor()");\r
581                 focusUrlShortcut = new QShortcut(this);\r
582                 setupShortcut(focusUrlShortcut, "Focus_Url");\r
583                 focusUrlShortcut.activated.connect(this, "focusUrl()");\r
584                 \r
585                 browser.page().mainFrame().setTextSizeMultiplier(Global.getTextSizeMultiplier());\r
586                 browser.page().mainFrame().setZoomFactor(Global.getZoomFactor());\r
587                 \r
588                 previewPageList = new HashMap<String,Integer>();\r
589                 \r
590                 browser.page().microFocusChanged.connect(this, "microFocusChanged()");\r
591                 \r
592                 //Setup colors\r
593                 \r
594                 QPalette pal = new QPalette();\r
595                 pal.setColor(ColorRole.Text, QColor.black);\r
596                 titleLabel.setPalette(pal);\r
597                 authorText.setPalette(pal);\r
598                 authorLabel.setPalette(pal);\r
599                 urlLabel.setPalette(pal);\r
600                 urlText.setPalette(pal);\r
601                 createdDate.setPalette(pal);\r
602                 createdTime.setPalette(pal);\r
603                 alteredDate.setPalette(pal);\r
604                 alteredTime.setPalette(pal);\r
605                 subjectDate.setPalette(pal);\r
606                 subjectTime.setPalette(pal);\r
607                 tagEdit.setPalette(pal);\r
608                 notebookBox.setPalette(pal);\r
609                 \r
610                 blockApplication = new Signal1<BrowserWindow>();\r
611                 unblockApplication = new Signal0();\r
612                 \r
613                 logger.log(logger.HIGH, "Browser setup complete");\r
614         }\r
615 \r
616         \r
617         \r
618         private void setupShortcut(QShortcut action, String text) {\r
619                 if (!Global.shortcutKeys.containsAction(text))\r
620                         return;\r
621                 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));\r
622         }\r
623         \r
624         \r
625 \r
626         \r
627         // Getter for the QWebView\r
628         public QWebView getBrowser() {\r
629                 return browser;\r
630         }\r
631 \r
632         // Block signals while loading data or things are flagged as dirty by\r
633         // mistake\r
634         public void loadingData(boolean val) {\r
635                 logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val);\r
636                 notebookBox.blockSignals(val);\r
637                 browser.page().blockSignals(val);\r
638                 browser.page().mainFrame().blockSignals(val);\r
639                 titleLabel.blockSignals(val);\r
640                 alteredDate.blockSignals(val);\r
641                 alteredTime.blockSignals(val);\r
642                 createdTime.blockSignals(val);\r
643                 createdDate.blockSignals(val);\r
644                 subjectDate.blockSignals(val);\r
645                 subjectTime.blockSignals(val);\r
646                 urlText.blockSignals(val);\r
647                 authorText.blockSignals(val);\r
648                 if (!val)\r
649                         exposeToJavascript();\r
650                 logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val);\r
651         }\r
652 \r
653         // Enable/disable\r
654         public void setReadOnly(boolean v) {\r
655                 setEnabled(true);\r
656                 titleLabel.setEnabled(!v);\r
657                 notebookBox.setEnabled(!v);\r
658                 tagEdit.setEnabled(!v);\r
659                 authorLabel.setEnabled(!v);\r
660                 geoBox.setEnabled(!v);\r
661                 urlText.setEnabled(!v);\r
662                 createdDate.setEnabled(!v);\r
663                 subjectDate.setEnabled(!v);\r
664                 alteredDate.setEnabled(!v);\r
665                 authorText.setEnabled(!v);\r
666                 createdTime.setEnabled(!v);\r
667                 alteredTime.setEnabled(!v);\r
668                 subjectTime.setEnabled(!v);\r
669                 getBrowser().setEnabled(true);\r
670 //              getBrowser().setEnabled(!v);\r
671         }\r
672         \r
673         // expose this class to Javascript on the web page\r
674         private void exposeToJavascript() {\r
675                 browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this);\r
676         }\r
677 \r
678         // Custom event queue\r
679         @Override\r
680         public boolean event(QEvent e) {\r
681                 if (e.type().equals(QEvent.Type.FocusOut)) {\r
682                         logger.log(logger.EXTREME, "Focus lost");\r
683                         focusLost.emit();\r
684                 }\r
685                 return super.event(e);\r
686         }\r
687 \r
688         // clear out browser\r
689         public void clear() {\r
690                 logger.log(logger.EXTREME, "Entering BrowserWindow.clear()");\r
691                 setNote(null);\r
692                 browser.setContent(new QByteArray());\r
693                 tagEdit.setText("");\r
694                 tagEdit.tagCompleter.reset();\r
695                 urlLabel.setText(tr("Source URL:"));\r
696                 titleLabel.setText("");\r
697                 logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()");\r
698         }\r
699 \r
700         // get/set current note\r
701         public void setNote(Note n) {\r
702                 currentNote = n;\r
703                 if (n == null)\r
704                         n = new Note();\r
705                 saveNoteTitle = n.getTitle();\r
706 \r
707         }\r
708 \r
709         public Note getNote() {\r
710                 return currentNote;\r
711         }\r
712 \r
713         // New Editor Button\r
714         private QPushButton newEditorButton(String name, String toolTip) {\r
715                 QPushButton button = new QPushButton();\r
716 //              QIcon icon = new QIcon(iconPath + name + ".gif");\r
717                 QIcon icon = new QIcon(iconPath + name + ".png");\r
718                 button.setIcon(icon);\r
719                 button.setToolTip(toolTip);\r
720                 button.clicked.connect(this, name + "Clicked()");\r
721                 return button;\r
722         }\r
723         // New Editor Button\r
724         private QToolButton newToolButton(String name, String toolTip) {\r
725                 QToolButton button = new QToolButton();\r
726 //              QIcon icon = new QIcon(iconPath + name + ".gif");\r
727                 QIcon icon = new QIcon(iconPath + name + ".png");\r
728                 button.setIcon(icon);\r
729                 button.setToolTip(toolTip);\r
730                 button.clicked.connect(this, name + "Clicked()");\r
731                 return button;\r
732         }\r
733 \r
734         // New Separator\r
735         private QLabel newSeparator() {\r
736                 return new QLabel("   ");\r
737         }\r
738 \r
739         // Set the title in the window\r
740         public void setTitle(String t) {\r
741                 titleLabel.setText(t);\r
742                 saveNoteTitle = t;\r
743                 checkNoteTitle();\r
744         }\r
745 \r
746         // Return the current text title\r
747         public String getTitle() {\r
748                 return titleLabel.text();\r
749         }\r
750 \r
751         // Set the tag name string\r
752         public void setTag(String t) {\r
753                 saveTagList = t;\r
754                 tagEdit.setText(t);\r
755                 tagEdit.tagCompleter.reset();\r
756         }\r
757 \r
758         // Set the source URL\r
759         public void setUrl(String t) {\r
760                 urlLabel.setText(tr("Source URL:\t"));\r
761                 urlText.setText(t);\r
762         }\r
763 \r
764         // The user want's to launch a web browser on the source of the URL\r
765         public void sourceUrlClicked() {\r
766                 // Make sure we have a valid URL\r
767                 if (urlText.text().trim().equals(""))\r
768                         return;\r
769                 \r
770                 String url = urlText.text();\r
771                 if (!url.toLowerCase().startsWith(tr("http://")))\r
772                         url = tr("http://") +url;\r
773                 \r
774         if (!QDesktopServices.openUrl(new QUrl(url))) {\r
775                 logger.log(logger.LOW, "Error opening file :" +url);\r
776         }\r
777         }\r
778         \r
779         public void setAuthor(String t) {\r
780                 authorLabel.setText(tr("Author:\t"));\r
781                 authorText.setText(t);\r
782         }\r
783 \r
784         // Set the creation date\r
785         public void setCreation(long date) {\r
786                 QDateTime dt = new QDateTime();\r
787                 dt.setTime_t((int) (date / 1000));\r
788                 createdDate.setDateTime(dt);\r
789                 createdTime.setDateTime(dt);\r
790                 createdDate.setDisplayFormat(Global.getDateFormat());\r
791                 createdTime.setDisplayFormat(Global.getTimeFormat());\r
792         }\r
793 \r
794         // Set the creation date\r
795         public void setAltered(long date) {\r
796                 QDateTime dt = new QDateTime();\r
797                 dt.setTime_t((int) (date / 1000));\r
798                 alteredDate.setDateTime(dt);\r
799                 alteredTime.setDateTime(dt);\r
800                 alteredDate.setDisplayFormat(Global.getDateFormat());\r
801                 alteredTime.setDisplayFormat(Global.getTimeFormat());\r
802         }\r
803 \r
804         // Set the subject date\r
805         public void setSubjectDate(long date) {\r
806                 QDateTime dt = new QDateTime();\r
807                 dt.setTime_t((int) (date / 1000));\r
808                 subjectDate.setDateTime(dt);\r
809                 subjectTime.setDateTime(dt);\r
810                 subjectDate.setDisplayFormat(Global.getDateFormat());\r
811                 subjectTime.setDisplayFormat(Global.getTimeFormat());\r
812         }\r
813 \r
814         // Toggle the extended attribute information\r
815         public void toggleInformation() {\r
816                 if (extendedOn) {\r
817                         extendedOn = false;\r
818                 } else {\r
819                         extendedOn = true;\r
820                 }\r
821                 urlLabel.setVisible(extendedOn);\r
822                 urlText.setVisible(extendedOn);\r
823                 authorText.setVisible(extendedOn);\r
824                 geoBox.setVisible(extendedOn);\r
825                 authorLabel.setVisible(extendedOn);\r
826                 createdDate.setVisible(extendedOn);\r
827                 createdTime.setVisible(extendedOn);\r
828                 createdLabel.setVisible(extendedOn);\r
829                 alteredLabel.setVisible(extendedOn);\r
830                 alteredDate.setVisible(extendedOn);\r
831                 alteredTime.setVisible(extendedOn);\r
832                 //notebookBox.setVisible(extendedOn);\r
833                 notebookLabel.setVisible(extendedOn);\r
834                 subjectLabel.setVisible(extendedOn);\r
835                 subjectDate.setVisible(extendedOn);\r
836                 subjectTime.setVisible(extendedOn);\r
837         }\r
838 \r
839         public void hideButtons() {\r
840 \r
841                 undoButton.parentWidget().setVisible(false);\r
842                 buttonsVisible = false;\r
843         }\r
844 \r
845 \r
846         // Is the extended view on?\r
847         public boolean isExtended() {\r
848                 return extendedOn;\r
849         }\r
850 \r
851         // Listener for when a link is clicked\r
852         @SuppressWarnings("unused")\r
853         private void openFile() {\r
854                 logger.log(logger.EXTREME, "Starting openFile()");\r
855                 File fileHandle = new File(selectedFile);\r
856                 URI fileURL = fileHandle.toURI();\r
857                 String localURL = fileURL.toString();\r
858                 QUrl url = new QUrl(localURL);\r
859                 QFile file = new QFile(selectedFile);\r
860                 \r
861                 logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName());\r
862                 fileWatcher.addPath(file.fileName());\r
863         \r
864         if (!QDesktopServices.openUrl(url)) {\r
865                 logger.log(logger.LOW, "Error opening file :" +url);\r
866         }\r
867         }\r
868         \r
869         \r
870         // Listener for when a link is clicked\r
871         @SuppressWarnings("unused")\r
872         private void linkClicked(QUrl url) {\r
873                 logger.log(logger.EXTREME, "URL Clicked: " +url.toString());\r
874                 if (url.toString().startsWith("latex:")) {\r
875                         int position = url.toString().lastIndexOf(".");\r
876                         String guid = url.toString().substring(0,position);\r
877                         position = guid.lastIndexOf("/");\r
878                         guid = guid.substring(position+1);\r
879                         editLatex(guid);\r
880                         return;\r
881                 }\r
882                 if (url.toString().startsWith("evernote:/view/")) {\r
883                         StringTokenizer tokens = new StringTokenizer(url.toString().replace("evernote:/view/", ""), "/");\r
884                         tokens.nextToken();\r
885                         tokens.nextToken();\r
886                         String sid = tokens.nextToken();\r
887                         String lid = tokens.nextToken();\r
888                         \r
889                         // Emit that we want to switch to a new note\r
890                         evernoteLinkClicked.emit(sid, lid);\r
891 \r
892                         return;\r
893                 }\r
894                 if (url.toString().startsWith("nnres://")) {\r
895                         logger.log(logger.EXTREME, "URL is NN resource");\r
896                         if (url.toString().endsWith("/vnd.evernote.ink")) {\r
897                                 logger.log(logger.EXTREME, "Unable to open ink note");\r
898                                 QMessageBox.information(this, tr("Unable Open"), tr("This is an ink note.\n"+\r
899                                         "Ink notes are not supported since Evernote has not\n published any specifications on them\n" +\r
900                                         "and I'm too lazy to figure them out by myself."));\r
901                                 return;\r
902                         }\r
903                         String fullName = url.toString().substring(8);\r
904                         int index = fullName.indexOf(".");\r
905                         String guid = "";\r
906                         String type = "";\r
907                         if (index >-1) {\r
908                                 type = fullName.substring(index+1);\r
909                                 guid = fullName.substring(0,index);\r
910                         }\r
911                         index = guid.indexOf(Global.attachmentNameDelimeter);\r
912                         if (index > -1) {\r
913                                 guid = guid.substring(0,index);\r
914                         }\r
915                         List<Resource> resList = currentNote.getResources();\r
916                         Resource res = null;\r
917                         for (int i=0; i<resList.size(); i++) {\r
918                                 if (resList.get(i).getGuid().equals(guid)) {\r
919                                         res = resList.get(i);\r
920                                         i=resList.size();\r
921                                 }\r
922                         }\r
923                         if (res == null) {\r
924                                 String resGuid = Global.resourceMap.get(guid);\r
925                                 if (resGuid != null) \r
926                                         res = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, true);\r
927                         }\r
928                         if (res != null) {\r
929                                 String fileName;\r
930                                 if (res.getAttributes() != null && \r
931                                                 res.getAttributes().getFileName() != null && \r
932                                                 !res.getAttributes().getFileName().trim().equals(""))\r
933                                         fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();\r
934                                 else\r
935                                         fileName = res.getGuid()+"."+type;\r
936                                 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));\r
937                         QFile.OpenMode mode = new QFile.OpenMode();\r
938                         mode.set(QFile.OpenModeFlag.WriteOnly);\r
939                         boolean openResult = file.open(mode);\r
940                                 logger.log(logger.EXTREME, "File opened:" +openResult);\r
941                         QDataStream out = new QDataStream(file);\r
942                         Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);\r
943                                 QByteArray binData = new QByteArray(resBinary.getData().getBody());\r
944                                 resBinary = null;\r
945                                 logger.log(logger.EXTREME, "Writing resource");\r
946                         out.writeBytes(binData.toByteArray());\r
947                         file.close();\r
948                                 \r
949                         String whichOS = System.getProperty("os.name");\r
950                                 if (whichOS.contains("Windows")) \r
951                                 url.setUrl("file:///"+file.fileName());\r
952                         else\r
953                                 url.setUrl("file://"+file.fileName());\r
954                  //       fileWatcher.removePath(file.fileName());\r
955                                 logger.log(logger.EXTREME, "Adding file watcher " +file.fileName());\r
956                                 fileWatcher.addPath(file.fileName());\r
957                         \r
958                         // If we can't open it, then prompt the user to save it.\r
959                         if (!QDesktopServices.openUrl(url)) {\r
960                                         logger.log(logger.EXTREME, "We can't handle this.  Where do we put it?");\r
961                                 QFileDialog dialog = new QFileDialog();\r
962                                 dialog.show();\r
963                                 if (dialog.exec()!=0) {\r
964                                         List<String> fileNames = dialog.selectedFiles(); //gets all selected filenames\r
965                                         if (fileNames.size() == 0) \r
966                                                 return;\r
967                                         String sf = fileNames.get(0);\r
968                                         QFile saveFile = new QFile(sf);\r
969                                         mode.set(QFile.OpenModeFlag.WriteOnly);\r
970                                         saveFile.open(mode);\r
971                                         QDataStream saveOut = new QDataStream(saveFile);\r
972                                         saveOut.writeBytes(binData.toByteArray());\r
973                                         saveFile.close();\r
974                                         return;\r
975                                 }\r
976                                 }\r
977                         }\r
978                         return;\r
979                 }\r
980                 logger.log(logger.EXTREME, "Launching URL");\r
981                 QDesktopServices.openUrl(url);\r
982         }\r
983 \r
984         // Listener for when BOLD is clicked\r
985         @SuppressWarnings("unused")\r
986         private void undoClicked() {\r
987                 browser.page().triggerAction(WebAction.Undo);\r
988                 browser.setFocus();\r
989         }\r
990 \r
991         // Listener for when BOLD is clicked\r
992         @SuppressWarnings("unused")\r
993         private void redoClicked() {\r
994                 browser.page().triggerAction(WebAction.Redo);\r
995                 browser.setFocus();\r
996         }\r
997 \r
998         // Listener for when BOLD is clicked\r
999         @SuppressWarnings("unused")\r
1000         private void boldClicked() {\r
1001                 browser.page().triggerAction(WebAction.ToggleBold);\r
1002                 microFocusChanged();\r
1003                 browser.setFocus();\r
1004         }\r
1005 \r
1006         // Listener for when Italics is clicked\r
1007         @SuppressWarnings("unused")\r
1008         private void italicClicked() {\r
1009                 browser.page().triggerAction(WebAction.ToggleItalic);\r
1010                 microFocusChanged();\r
1011                 browser.setFocus();\r
1012         }\r
1013 \r
1014         // Listener for when UNDERLINE is clicked\r
1015         @SuppressWarnings("unused")\r
1016         private void underlineClicked() {\r
1017                 browser.page().triggerAction(WebAction.ToggleUnderline);\r
1018                 microFocusChanged();\r
1019                 browser.setFocus();\r
1020         }\r
1021 \r
1022         // Listener for when Strikethrough is clicked\r
1023         @SuppressWarnings("unused")\r
1024         private void strikethroughClicked() {\r
1025                 browser.page().mainFrame().evaluateJavaScript(\r
1026                                 "document.execCommand('strikeThrough', false, '');");\r
1027                 browser.setFocus();\r
1028         }\r
1029 \r
1030         // Listener for when cut is clicked\r
1031         @SuppressWarnings("unused")\r
1032         private void cutClicked() {\r
1033                 browser.page().triggerAction(WebAction.Cut);\r
1034                 browser.setFocus();\r
1035         }\r
1036 \r
1037         // Listener when COPY is clicked\r
1038         @SuppressWarnings("unused")\r
1039         private void copyClicked() {\r
1040                 browser.page().triggerAction(WebAction.Copy);\r
1041                 browser.setFocus();\r
1042         }\r
1043 \r
1044         // Listener when PASTE is clicked\r
1045         public void pasteClicked() {\r
1046                 logger.log(logger.EXTREME, "Paste Clicked");\r
1047                 if (forceTextPaste) {\r
1048                         pasteWithoutFormattingClicked();\r
1049                         return;\r
1050                 }\r
1051                 QClipboard clipboard = QApplication.clipboard();\r
1052                 QMimeData mime = clipboard.mimeData();\r
1053                 \r
1054 //               String x = mime.html();\r
1055 \r
1056                 if (mime.hasImage()) {\r
1057                         logger.log(logger.EXTREME, "Image paste found");\r
1058                         browser.setFocus();\r
1059                         insertImage(mime);\r
1060                         browser.setFocus();\r
1061                         return;\r
1062                 }\r
1063 \r
1064                 if (mime.hasUrls()) {\r
1065                         logger.log(logger.EXTREME, "URL paste found");\r
1066                         if (!mime.text().startsWith("evernote:")) {\r
1067                                 handleNoteLink(mime);\r
1068                         } else {\r
1069                                 handleUrls(mime);\r
1070                                 browser.setFocus();\r
1071                         }\r
1072                         return;\r
1073                 }\r
1074                 \r
1075                 String text = mime.html();\r
1076                 if (text.contains("en-tag") && mime.hasHtml()) {\r
1077                         logger.log(logger.EXTREME, "Intra-note paste found");\r
1078                         text = fixInternotePaste(text);\r
1079                         mime.setHtml(text);\r
1080                         clipboard.setMimeData(mime);\r
1081                 }\r
1082 \r
1083                 logger.log(logger.EXTREME, "Final paste choice encountered");\r
1084                 browser.page().triggerAction(WebAction.Paste);\r
1085                 browser.setFocus();\r
1086 \r
1087         }\r
1088 \r
1089         // Paste text without formatting\r
1090         private void pasteWithoutFormattingClicked() {\r
1091                 logger.log(logger.EXTREME, "Paste without format clipped");\r
1092                 QClipboard clipboard = QApplication.clipboard();\r
1093                 QMimeData mime = clipboard.mimeData();\r
1094                 if (!mime.hasText())\r
1095                         return;\r
1096                 String text = mime.text();\r
1097                 clipboard.clear();\r
1098                 clipboard.setText(text, Mode.Clipboard);\r
1099                 browser.page().triggerAction(WebAction.Paste);\r
1100 \r
1101                 // This is done because pasting into an encryption block\r
1102                 // can cause multiple cells (which can't happen).  It \r
1103                 // just goes through the table, extracts the data, & \r
1104                 // puts it back as one table cell.\r
1105                 if (insideEncryption) {\r
1106                         String js = new String( "function fixEncryption() { "\r
1107                                         +"   var selObj = window.getSelection();"\r
1108                                         +"   var selRange = selObj.getRangeAt(0);"\r
1109                                         +"   var workingNode = window.getSelection().anchorNode;"\r
1110                                         +"   while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { " \r
1111                                         +"           workingNode = workingNode.parentNode;"\r
1112                                         +"   } "\r
1113                                         +"   workingNode.innerHTML = window.jambi.fixEncryptionPaste(workingNode.innerHTML);"\r
1114                                         +"} fixEncryption();");\r
1115                         browser.page().mainFrame().evaluateJavaScript(js);\r
1116                 }\r
1117         }\r
1118         \r
1119         // This basically removes all the table tags and returns just the contents.\r
1120         // This is called by JavaScript to fix encryption pastes.\r
1121         public String fixEncryptionPaste(String data) {\r
1122                 data = data.replace("<tbody>", "");\r
1123                 data = data.replace("</tbody>", "");\r
1124                 data = data.replace("<tr>", "");\r
1125                 data = data.replace("</tr>", "");\r
1126                 data = data.replace("<td>", "");\r
1127                 data = data.replace("</td>", "<br>");\r
1128                 data = data.replace("<br><br>", "<br>");\r
1129 \r
1130                 return "<tbody><tr><td>"+data+"</td></tr></tbody>";\r
1131         }\r
1132         \r
1133         // insert date/time\r
1134         @SuppressWarnings("unused")\r
1135         private void insertDateTime() {\r
1136                 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();\r
1137                 String dateTimeFormat = new String(fmt);\r
1138                 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);\r
1139                 Calendar cal = Calendar.getInstance();\r
1140                 \r
1141                 browser.page().mainFrame().evaluateJavaScript(\r
1142                         "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");\r
1143                 \r
1144                 browser.setFocus();\r
1145 \r
1146         }\r
1147 \r
1148         // Listener when Left is clicked\r
1149         @SuppressWarnings("unused")\r
1150         private void justifyLeftClicked() {\r
1151                 browser.page().mainFrame().evaluateJavaScript(\r
1152                                 "document.execCommand('JustifyLeft', false, '');");\r
1153                 browser.setFocus();\r
1154         }\r
1155 \r
1156         // Listener when Center is clicked\r
1157         @SuppressWarnings("unused")\r
1158         private void justifyCenterClicked() {\r
1159                 browser.page().mainFrame().evaluateJavaScript(\r
1160                                 "document.execCommand('JustifyCenter', false, '');");\r
1161                 browser.setFocus();\r
1162         }\r
1163 \r
1164         // Listener when Left is clicked\r
1165         @SuppressWarnings("unused")\r
1166         private void justifyRightClicked() {\r
1167                 browser.page().mainFrame().evaluateJavaScript(\r
1168                                 "document.execCommand('JustifyRight', false, '');");\r
1169                 browser.setFocus();\r
1170         }\r
1171 \r
1172         // Listener when HLINE is clicked\r
1173         @SuppressWarnings("unused")\r
1174         private void hlineClicked() {\r
1175                 browser.page().mainFrame().evaluateJavaScript(\r
1176                                 "document.execCommand('insertHorizontalRule', false, '');");\r
1177                 browser.setFocus();\r
1178         }\r
1179 \r
1180         // Listener when outdent is clicked\r
1181         private void outdentClicked() {\r
1182                 browser.page().mainFrame().evaluateJavaScript(\r
1183                                 "document.execCommand('outdent', false, '');");\r
1184                 browser.setFocus();\r
1185         }\r
1186 \r
1187         // Listener when a bullet list is clicked\r
1188         @SuppressWarnings("unused")\r
1189         private void bulletListClicked() {\r
1190                 browser.page().mainFrame().evaluateJavaScript(\r
1191                                 "document.execCommand('InsertUnorderedList', false, '');");\r
1192                 browser.setFocus();\r
1193         }\r
1194 \r
1195         // Listener when a bullet list is clicked\r
1196         @SuppressWarnings("unused")\r
1197         private void numberListClicked() {\r
1198                 browser.page().mainFrame().evaluateJavaScript(\r
1199                                 "document.execCommand('InsertOrderedList', false, '');");\r
1200                 browser.setFocus();\r
1201         }\r
1202 \r
1203         // Listener when indent is clicked\r
1204         private void indentClicked() {\r
1205                 browser.page().mainFrame().evaluateJavaScript(\r
1206                                 "document.execCommand('indent', false, '');");\r
1207                 browser.setFocus();\r
1208         }\r
1209 \r
1210         // Listener when the font name is changed\r
1211         @SuppressWarnings("unused")\r
1212         private void fontChanged(String font) {\r
1213                 browser.page().mainFrame().evaluateJavaScript(\r
1214                                 "document.execCommand('fontName',false,'" + font + "');");\r
1215                 browser.setFocus();\r
1216         }\r
1217 \r
1218         // Listener when a font size is changed\r
1219         @SuppressWarnings("unused")\r
1220         private void fontSizeChanged(String font) {\r
1221                 String text = browser.selectedText();\r
1222                 if (text.trim().equalsIgnoreCase(""))\r
1223                         return;\r
1224 \r
1225                 String selectedText = browser.selectedText();\r
1226                 String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";\r
1227                 String script = "document.execCommand('insertHtml', false, '"+url+"');";\r
1228                 browser.page().mainFrame().evaluateJavaScript(script);\r
1229 /*              browser.page().mainFrame().evaluateJavaScript(\r
1230                                 "document.execCommand('fontSize',false,'"\r
1231                                                 + font + "');");\r
1232 */\r
1233                 browser.setFocus();\r
1234         }\r
1235 \r
1236         // Load the font combo box based upon the font selected\r
1237         private void loadFontSize(String name) {        \r
1238                 QFontDatabase db = new QFontDatabase(); \r
1239                 fontSize.clear();\r
1240                 List<Integer> points = db.pointSizes(name); \r
1241                 for (int i=0; i<points.size(); i++) { \r
1242                         fontSize.addItem(points.get(i).toString()); \r
1243                 }\r
1244                 /*\r
1245                 fontSize.addItem("x-small");\r
1246                 fontSize.addItem("small");\r
1247                 fontSize.addItem("medium");\r
1248                 fontSize.addItem("large");\r
1249                 fontSize.addItem("x-large");\r
1250                 fontSize.addItem("xx-large");\r
1251                 fontSize.addItem("xxx-large");\r
1252                 */\r
1253         }\r
1254 \r
1255         // Listener when a font size is changed\r
1256         @SuppressWarnings("unused")\r
1257         private void fontColorClicked() {\r
1258 //              QColorDialog dialog = new QColorDialog();\r
1259 //              QColor color = QColorDialog.getColor();\r
1260                 QColor color = fontColorMenu.getColor();\r
1261                 if (color.isValid())\r
1262                         browser.page().mainFrame().evaluateJavaScript(\r
1263                                         "document.execCommand('foreColor',false,'" + color.name()\r
1264                                                         + "');");\r
1265                 browser.setFocus();\r
1266         }\r
1267 \r
1268         // Listener for when a background color change is requested\r
1269         @SuppressWarnings("unused")\r
1270         private void fontHilightClicked() {\r
1271 //              QColorDialog dialog = new QColorDialog();\r
1272 //              QColor color = QColorDialog.getColor();\r
1273                 QColor color = fontHilightColorMenu.getColor();\r
1274                 if (color.isValid())\r
1275                         browser.page().mainFrame().evaluateJavaScript(\r
1276                                         "document.execCommand('backColor',false,'" + color.name()\r
1277                                                         + "');");\r
1278                 browser.setFocus();\r
1279         }\r
1280         \r
1281         // Listener for when a background color change is requested\r
1282         @SuppressWarnings("unused")\r
1283         private void superscriptClicked() {\r
1284                 browser.page().mainFrame().evaluateJavaScript(\r
1285                                         "document.execCommand('superscript');");\r
1286                 browser.setFocus();\r
1287         }\r
1288         \r
1289         // Listener for when a background color change is requested\r
1290         @SuppressWarnings("unused")\r
1291         private void subscriptClicked() {\r
1292                 browser.page().mainFrame().evaluateJavaScript(\r
1293                                         "document.execCommand('subscript');");\r
1294                 browser.setFocus();\r
1295         }\r
1296         // Insert a to-do checkbox\r
1297         @SuppressWarnings("unused")\r
1298         private void todoClicked() {\r
1299                 FileNameMap fileNameMap = URLConnection.getFileNameMap();\r
1300                 String script_start = new String(\r
1301                                 "document.execCommand('insertHtml', false, '");\r
1302                 String script_end = new String("');");\r
1303                 String todo = new String(\r
1304                                 "<input TYPE=\"CHECKBOX\" value=\"false\" " +\r
1305                                 "onMouseOver=\"style.cursor=\\'hand\\'\" " +\r
1306                                 "onClick=\"value=checked; window.jambi.contentChanged(); \" />");\r
1307                 browser.page().mainFrame().evaluateJavaScript(\r
1308                                 script_start + todo + script_end);\r
1309                 browser.setFocus();\r
1310         }\r
1311 \r
1312         // Encrypt the selected text\r
1313         @SuppressWarnings("unused")\r
1314         private void encryptText() {\r
1315                 String text = browser.selectedText();\r
1316                 if (text.trim().equalsIgnoreCase(""))\r
1317                         return;\r
1318                 text = new String(text.replaceAll("\n", "<br/>"));\r
1319 \r
1320                 EnCryptDialog dialog = new EnCryptDialog();\r
1321                 dialog.exec();\r
1322                 if (!dialog.okPressed()) {\r
1323                         return;\r
1324                 }\r
1325 \r
1326                 EnCrypt crypt = new EnCrypt();\r
1327                 String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);\r
1328                 String decrypted = crypt.decrypt(encrypted, dialog.getPassword().trim(), 64);\r
1329 \r
1330                 if (encrypted.trim().equals("")) {\r
1331                         QMessageBox.information(this, tr("Error"), tr("Error Encrypting String"));\r
1332                         return;\r
1333                 }\r
1334                 StringBuffer buffer = new StringBuffer(encrypted.length() + 100);\r
1335                 buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""\r
1336                                 + dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");\r
1337                 buffer.append("contentEditable=\"false\" alt=\"");\r
1338                 buffer.append(encrypted);\r
1339                 buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png") +"\""));\r
1340                 Global.cryptCounter++;\r
1341                 buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");\r
1342                 buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");\r
1343                 buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString() \r
1344                                 +"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&amp;apos;")+"\\');\"");\r
1345                 buffer.append("style=\"display:block\" />");\r
1346 \r
1347                 String script_start = new String(\r
1348                                 "document.execCommand('insertHtml', false, '");\r
1349                 String script_end = new String("');");\r
1350                 browser.page().mainFrame().evaluateJavaScript(\r
1351                                 script_start + buffer.toString() + script_end);\r
1352         }\r
1353 \r
1354         \r
1355         // Insert a hyperlink\r
1356         public void insertLink() {\r
1357                 logger.log(logger.EXTREME, "Inserting link");\r
1358                 String text = browser.selectedText();\r
1359                 if (text.trim().equalsIgnoreCase(""))\r
1360                         return;\r
1361 \r
1362                 InsertLinkDialog dialog = new InsertLinkDialog(insertHyperlink);\r
1363                 if (currentHyperlink != null && currentHyperlink != "") {\r
1364                         dialog.setUrl(currentHyperlink);\r
1365                 }\r
1366                 dialog.exec();\r
1367                 if (!dialog.okPressed()) {\r
1368                         logger.log(logger.EXTREME, "Insert link canceled");\r
1369                         return;\r
1370                 }\r
1371                 \r
1372                 // Take care of inserting new links\r
1373                 if (insertHyperlink) {\r
1374                         String selectedText = browser.selectedText();\r
1375                         if (dialog.getUrl().trim().equals(""))\r
1376                                 return;\r
1377                         logger.log(logger.EXTREME, "Inserting link on text "+selectedText);\r
1378                         logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim());\r
1379                         String dUrl = StringUtils.replace(dialog.getUrl().trim(), "'", "\\'");\r
1380                         String url = "<a href=\"" +dUrl\r
1381                                         +"\" title=" +dUrl \r
1382                                         +" >"+selectedText +"</a>";\r
1383                         String script = "document.execCommand('insertHtml', false, '"+url+"');";\r
1384                         browser.page().mainFrame().evaluateJavaScript(script);\r
1385                         return;\r
1386                 }\r
1387                 \r
1388                 // Edit existing links\r
1389                 String js = new String( "function getCursorPos() {"\r
1390                                 +"var cursorPos;"\r
1391                                 +"if (window.getSelection) {"\r
1392                                 +"   var selObj = window.getSelection();"\r
1393                                 +"   var selRange = selObj.getRangeAt(0);"\r
1394                                 +"   var workingNode = window.getSelection().anchorNode.parentNode;"\r
1395                                 +"   while(workingNode != null) { " \r
1396                                 +"      if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');"\r
1397                                 +"      workingNode = workingNode.parentNode;"\r
1398                                 +"   }"\r
1399                                 +"}"\r
1400                                 +"} getCursorPos();");\r
1401                         browser.page().mainFrame().evaluateJavaScript(js);\r
1402                 \r
1403                 if (!dialog.getUrl().trim().equals("")) {\r
1404                         contentChanged();\r
1405                         return;\r
1406                 }\r
1407                 \r
1408                 // Remove URL\r
1409                 js = new String( "function getCursorPos() {"\r
1410                                 +"var cursorPos;"\r
1411                                 +"if (window.getSelection) {"\r
1412                                 +"   var selObj = window.getSelection();"\r
1413                                 +"   var selRange = selObj.getRangeAt(0);"\r
1414                                 +"   var workingNode = window.getSelection().anchorNode.parentNode;"\r
1415                                 +"   while(workingNode != null) { " \r
1416                                 +"      if (workingNode.nodeName.toLowerCase()=='a') { "\r
1417                                 +"         workingNode.removeAttribute('href');"\r
1418                                 +"         workingNode.removeAttribute('title');"\r
1419                                 +"         var text = document.createTextNode(workingNode.innerText);"\r
1420                                 +"         workingNode.parentNode.insertBefore(text, workingNode);"\r
1421                                 +"         workingNode.parentNode.removeChild(workingNode);"\r
1422                                 +"      }"\r
1423                                 +"      workingNode = workingNode.parentNode;"\r
1424                                 +"   }"\r
1425                                 +"}"\r
1426                                 +"} getCursorPos();");\r
1427                         browser.page().mainFrame().evaluateJavaScript(js);\r
1428                         \r
1429                         contentChanged();\r
1430 \r
1431                 \r
1432         }\r
1433         \r
1434         \r
1435         // Insert a hyperlink\r
1436         public void insertLatex() {\r
1437                 editLatex(null);\r
1438         }\r
1439         public void editLatex(String guid) {\r
1440                 logger.log(logger.EXTREME, "Inserting latex");\r
1441                 String text = browser.selectedText();\r
1442                 if (text.trim().equalsIgnoreCase("")) {\r
1443                         InsertLatexImage dialog = new InsertLatexImage();\r
1444                         if (guid != null) {\r
1445                                 String formula = conn.getNoteTable().noteResourceTable.getNoteSourceUrl(guid).replace("http://latex.codecogs.com/gif.latex?", "");\r
1446                                 dialog.setFormula(formula);\r
1447                         }\r
1448                         dialog.exec();\r
1449                         if (!dialog.okPressed()) {\r
1450                                 logger.log(logger.EXTREME, "Edit LaTex canceled");\r
1451                                 return;\r
1452                         }\r
1453                         text = dialog.getFormula().trim();\r
1454                 }\r
1455                 blockApplication.emit(this);\r
1456                 logger.log(logger.EXTREME, "Inserting LaTeX formula:" +text);\r
1457                 latexGuid = guid;\r
1458                 text = StringUtils.replace(text, "'", "\\'");\r
1459                 String url = "http://latex.codecogs.com/gif.latex?" +text;\r
1460                 logger.log(logger.EXTREME, "Sending request to codecogs --> " + url);\r
1461                 QNetworkAccessManager manager = new QNetworkAccessManager(this);\r
1462                 manager.finished.connect(this, "insertLatexImageReady(QNetworkReply)");\r
1463                 unblockTime = new GregorianCalendar().getTimeInMillis()+5000;\r
1464                 awaitingHttpResponse = true;\r
1465                 manager.get(new QNetworkRequest(new QUrl(url)));\r
1466         }\r
1467         \r
1468         public void insertLatexImageReady(QNetworkReply reply) {\r
1469                 logger.log(logger.EXTREME, "Response received from CodeCogs");\r
1470                 if (reply.error() != NetworkError.NoError) \r
1471                         return;\r
1472 \r
1473                 unblockTime = -1;\r
1474                 if (!awaitingHttpResponse)\r
1475                         return;\r
1476                 \r
1477                 awaitingHttpResponse = false;\r
1478                 QUrl replyUrl = reply.url();            \r
1479                 QByteArray image = reply.readAll();\r
1480                 reply.close();\r
1481                 logger.log(logger.EXTREME, "New image size: " +image.size());\r
1482 \r
1483                 Resource newRes = null;\r
1484                 QFile tfile;\r
1485                 String path;\r
1486                 if (latexGuid == null) {\r
1487                         logger.log(logger.EXTREME, "Creating temporary gif");                   \r
1488                         path = Global.getFileManager().getResDirPath("latex-temp.gif");\r
1489                         tfile = new QFile(path);\r
1490                         tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));\r
1491                         logger.log(logger.EXTREME, "File Open: " +tfile.errorString());\r
1492                         tfile.write(image);\r
1493                         logger.log(logger.EXTREME, "Bytes writtes: "+tfile.size());\r
1494                         tfile.close();\r
1495                         logger.log(logger.EXTREME, "Creating resource");\r
1496                         int sequence = 0;\r
1497                         if (currentNote.getResources() != null || currentNote.getResources().size() > 0)\r
1498                                 sequence = currentNote.getResources().size();\r
1499                         newRes = createResource(path,sequence ,"image/gif", false);\r
1500                         QImage pix = new QImage();\r
1501                         pix.loadFromData(image);\r
1502                         newRes.setHeight(new Integer(pix.height()).shortValue());\r
1503                         newRes.setWidth(new Integer(pix.width()).shortValue());\r
1504                         logger.log(logger.EXTREME, "Renaming temporary file to " +newRes.getGuid()+".gif");\r
1505                         path = Global.getFileManager().getResDirPath(newRes.getGuid()+".gif");\r
1506                         tfile.rename(path);\r
1507                 } else {\r
1508                         newRes = conn.getNoteTable().noteResourceTable.getNoteResource(latexGuid, false);\r
1509                         path = Global.getFileManager().getResDirPath(newRes.getGuid()+".gif");\r
1510                         tfile = new QFile(path);\r
1511                         tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));\r
1512                         tfile.write(image);\r
1513                         tfile.close();\r
1514                         newRes.getData().setBody(image.toByteArray());\r
1515                         // Calculate the new hash value\r
1516                 MessageDigest md;\r
1517 \r
1518                 logger.log(logger.EXTREME, "Generating MD5");\r
1519                 try {\r
1520                                 md = MessageDigest.getInstance("MD5");\r
1521                         md.update(image.toByteArray());\r
1522                         byte[] hash = md.digest();\r
1523                         newRes.getData().setBodyHash(hash);\r
1524                         } catch (NoSuchAlgorithmException e) {\r
1525                                 e.printStackTrace();\r
1526                         }\r
1527                         QImage pix = new QImage();\r
1528                         pix.loadFromData(image);\r
1529                         newRes.setHeight(new Integer(pix.height()).shortValue());\r
1530                         newRes.setWidth(new Integer(pix.width()).shortValue());\r
1531                         conn.getNoteTable().noteResourceTable.updateNoteResource(newRes, true);\r
1532                 }\r
1533 \r
1534                 logger.log(logger.EXTREME, "Setting source: " +replyUrl.toString());\r
1535                 newRes.getAttributes().setSourceURL(replyUrl.toString());\r
1536                 conn.getNoteTable().noteResourceTable.updateNoteSourceUrl(newRes.getGuid(), replyUrl.toString(), true);\r
1537                 \r
1538                 for(int i=0; i<currentNote.getResourcesSize(); i++) {\r
1539                         if (currentNote.getResources().get(i).getGuid().equals(newRes.getGuid())) {\r
1540                                 currentNote.getResources().remove(i);\r
1541                                 i=currentNote.getResourcesSize();\r
1542                         }\r
1543                 }\r
1544                 currentNote.getResources().add(newRes);\r
1545                 \r
1546 \r
1547                 // do the actual insert into the note.  We only do this on new formulas.  \r
1548                 if (latexGuid == null) {\r
1549                         StringBuffer buffer = new StringBuffer(100);\r
1550                         String formula = replyUrl.toString().toLowerCase().replace("http://latex.codecogs.com/gif.latex?", "");\r
1551                         buffer.append("<a href=\"latex://"+path.replace("\\", "/")+"\" title=\""+formula+"\""\r
1552                                         +"><img src=\"");\r
1553                         buffer.append(path.replace("\\", "/"));\r
1554                         buffer.append("\" en-tag=\"en-latex\" type=\"image/gif\""\r
1555                                 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""\r
1556                                 +" guid=\"" +newRes.getGuid() +"\""\r
1557                                 + " /></a>");\r
1558                 \r
1559                         String script_start = new String("document.execCommand('insertHTML', false, '");\r
1560                         String script_end = new String("');");\r
1561                         browser.page().mainFrame().evaluateJavaScript(\r
1562                                         script_start + buffer + script_end);\r
1563                 } else {\r
1564                         HtmlTagModifier modifier = new HtmlTagModifier(getContent());\r
1565                         modifier.modifyLatexTagHash(newRes);\r
1566                         String newContent = modifier.getHtml();\r
1567                         browser.setContent(new QByteArray(newContent));\r
1568                 }\r
1569 \r
1570                 logger.log(logger.EXTREME, "New HTML set\n" +browser.page().currentFrame().toHtml());\r
1571                 QWebSettings.setMaximumPagesInCache(0);\r
1572                 QWebSettings.setObjectCacheCapacities(0, 0, 0);\r
1573                 \r
1574                 browser.page().mainFrame().setHtml(browser.page().mainFrame().toHtml());\r
1575                 browser.reload();\r
1576                 contentChanged();\r
1577 //              resourceSignal.contentChanged.emit(path);\r
1578                 unblockTime = -1;\r
1579         unblockApplication.emit();\r
1580                 return;\r
1581                 \r
1582         }\r
1583 \r
1584         \r
1585         \r
1586         // Insert a table\r
1587         public void insertTable() {\r
1588                 TableDialog dialog = new TableDialog();\r
1589                 dialog.exec();\r
1590                 if (!dialog.okPressed()) {\r
1591                         return;\r
1592                 }\r
1593                 \r
1594                 int cols = dialog.getCols();\r
1595                 int rows = dialog.getRows();\r
1596                 int width = dialog.getWidth();\r
1597                 boolean percent = dialog.isPercent();\r
1598                 \r
1599                 String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();\r
1600                 if (percent)\r
1601                         newHTML = newHTML +"%";\r
1602                 newHTML = newHTML + "\"><tbody>";\r
1603 \r
1604                 for (int i=0; i<rows; i++) {\r
1605                         newHTML = newHTML +"<tr>";\r
1606                         for (int j=0; j<cols; j++) {\r
1607                                 newHTML = newHTML +"<td>&nbsp;</td>";\r
1608                         }\r
1609                         newHTML = newHTML +"</tr>";\r
1610                 }\r
1611                 newHTML = newHTML+"</tbody></table>";   \r
1612         \r
1613                 String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";\r
1614                 browser.page().mainFrame().evaluateJavaScript(script);\r
1615         }\r
1616         \r
1617         \r
1618         // Text content changed\r
1619         @SuppressWarnings("unused")\r
1620         private void selectionChanged() {\r
1621                 browser.encryptAction.setEnabled(true);\r
1622                 browser.insertLinkAction.setEnabled(true);\r
1623                 String scriptStart = "var selection_text = (window.getSelection()).toString();"\r
1624                                 + "var range = (window.getSelection()).getRangeAt(0);"\r
1625                                 + "var parent_html = range.commonAncestorContainer.innerHTML;"\r
1626                                 + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"\r
1627                                 + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"\r
1628                                 + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"\r
1629                                 + "var start = parent_html.indexOf(first_text);"\r
1630                                 + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"\r
1631                                 + "var value = parent_html.substring(start,end);"\r
1632                                 + "window.jambi.saveSelectedText(value);" ;\r
1633                 browser.page().mainFrame().evaluateJavaScript(scriptStart);\r
1634 \r
1635         }\r
1636 \r
1637         public void saveSelectedText(String text) {\r
1638                 boolean enabled = true;\r
1639                 if (text.trim().length() == 0)\r
1640                         enabled=false;\r
1641                 if (text.indexOf("en-tag=\"en-crypt\"") >= 0)\r
1642                         enabled=false;\r
1643                 if (text.indexOf("<img en-tag=\"en-media\"") >= 0)\r
1644                         enabled=false;\r
1645                 if (text.indexOf("<a en-tag=\"en-media\"") >= 0)\r
1646                         enabled=false;\r
1647                 if (text.indexOf("<input ") >= 0)\r
1648                         enabled=false;\r
1649                 \r
1650                 browser.encryptAction.setEnabled(enabled);\r
1651                 browser.insertLinkAction.setEnabled(enabled);\r
1652 //              selectedText = text;\r
1653         }\r
1654 \r
1655         // Decrypt clicked text\r
1656         public void decryptText(String id, String text, String hint) {\r
1657                 EnCrypt crypt = new EnCrypt();\r
1658                 String plainText = null;\r
1659                 Calendar currentTime = new GregorianCalendar();\r
1660                 Long l = new Long(currentTime.getTimeInMillis());\r
1661                 String slot = new String(Long.toString(l));\r
1662                 \r
1663                 // First, try to decrypt with any keys we already have\r
1664                 for (int i=0; i<Global.passwordRemember.size(); i++) {\r
1665                         plainText = crypt.decrypt(text, Global.passwordRemember.get(i).getFirst(), 64);\r
1666                         if (plainText != null) {\r
1667                                 slot = new String(Long.toString(l));\r
1668                                 Global.passwordSafe.put(slot, Global.passwordRemember.get(i));\r
1669                                 removeEncryption(id, plainText, false, slot);   \r
1670                                 return;\r
1671                         }\r
1672                 }\r
1673                 \r
1674                 \r
1675                 EnDecryptDialog dialog = new EnDecryptDialog();\r
1676                 dialog.setHint(hint);\r
1677                 while (plainText == null || !dialog.okPressed()) {\r
1678                         dialog.exec();\r
1679                         if (!dialog.okPressed()) {\r
1680                                 return;\r
1681                         }\r
1682                         plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);\r
1683                         if (plainText == null) {\r
1684                                 QMessageBox.warning(this, tr("Incorrect Password"), tr("The password entered is not correct"));\r
1685                         }\r
1686                 }\r
1687                 Pair<String,String> passwordPair = new Pair<String,String>();\r
1688                 passwordPair.setFirst(dialog.getPassword());\r
1689                 passwordPair.setSecond(dialog.getHint());\r
1690                 Global.passwordSafe.put(slot, passwordPair);\r
1691 //              removeEncryption(id, plainText.replaceAll("\n", "<br/>"), dialog.permanentlyDecrypt(), slot);\r
1692                 removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);\r
1693                 if (dialog.rememberPassword()) {\r
1694                         Pair<String, String> pair = new Pair<String,String>();\r
1695                         pair.setFirst(dialog.getPassword());\r
1696                         pair.setSecond(dialog.getHint());\r
1697                         Global.passwordRemember.add(pair);\r
1698                 }\r
1699 \r
1700         }\r
1701 \r
1702         // Get the editor tag line\r
1703         public TagLineEdit getTagLine() {\r
1704                 return tagEdit;\r
1705         }\r
1706 \r
1707         // Modify a note's tags\r
1708         @SuppressWarnings("unused")\r
1709         private void modifyTags() {\r
1710                 TagAssign tagWindow = new TagAssign(allTags, currentTags, !conn.getNotebookTable().isLinked(currentNote.getNotebookGuid()));\r
1711                 tagWindow.exec();\r
1712                 if (tagWindow.okClicked()) {\r
1713                         currentTags.clear();\r
1714                         StringBuffer tagDisplay = new StringBuffer();\r
1715 \r
1716                         List<QListWidgetItem> newTags = tagWindow.getTagList()\r
1717                                         .selectedItems();\r
1718                         for (int i = 0; i < newTags.size(); i++) {\r
1719                                 currentTags.add(newTags.get(i).text());\r
1720                                 tagDisplay.append(newTags.get(i).text());\r
1721                                 if (i < newTags.size() - 1) {\r
1722                                         tagDisplay.append(Global.tagDelimeter + " ");\r
1723                                 }\r
1724                         }\r
1725                         tagEdit.setText(tagDisplay.toString());\r
1726                         noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);\r
1727                 }\r
1728         }\r
1729 \r
1730         // Tag line has been modified by typing text\r
1731         @SuppressWarnings("unused")\r
1732         private void modifyTagsTyping() {\r
1733                 String completionText = "";\r
1734                 if (tagEdit.currentCompleterSelection != null && !tagEdit.currentCompleterSelection.equals("")) {\r
1735                         completionText = tagEdit.currentCompleterSelection;\r
1736                         tagEdit.currentCompleterSelection = "";\r
1737                 }\r
1738                 \r
1739                 if (tagEdit.text().equalsIgnoreCase(saveTagList))\r
1740                         return;\r
1741 \r
1742                 // We know something has changed...\r
1743                 String oldTagArray[] = saveTagList.split(Global.tagDelimeter);\r
1744                 String newTagArray[];\r
1745                 if (!completionText.equals("")) {\r
1746                         String before = tagEdit.text().substring(0,tagEdit.cursorPosition());\r
1747                         int lastDelimiter = before.lastIndexOf(Global.tagDelimeter);\r
1748                         if (lastDelimiter > 0)\r
1749                                 before = before.substring(0,before.lastIndexOf(Global.tagDelimeter));\r
1750                         else \r
1751                                 before = "";\r
1752                         String after = tagEdit.text().substring(tagEdit.cursorPosition());\r
1753                         newTagArray = (before+Global.tagDelimeter+completionText+Global.tagDelimeter+after).split(Global.tagDelimeter);\r
1754                 }\r
1755                 else {\r
1756                         newTagArray = tagEdit.text().split(Global.tagDelimeter);\r
1757                 }\r
1758                 \r
1759                 // Remove any traling or leading blanks\r
1760                 for (int i=0; i<newTagArray.length; i++)\r
1761                         newTagArray[i] = newTagArray[i].trim().replaceAll("^\\s+", "");;\r
1762                 \r
1763                 // Remove any potential duplicates from the new list\r
1764                 for (int i=0; i<newTagArray.length; i++) {\r
1765                         boolean foundOnce = false;\r
1766                         for (int j=0; j<newTagArray.length; j++) {\r
1767                                 if (newTagArray[j].equalsIgnoreCase(newTagArray[i])) {\r
1768                                         if (!foundOnce) {\r
1769                                                 foundOnce = true;\r
1770                                         } else\r
1771                                                 newTagArray[j] = "";\r
1772                                 }\r
1773                         }\r
1774                 }\r
1775 \r
1776                 List<String> newTagList = new ArrayList<String>();\r
1777                 List<String> oldTagList = new ArrayList<String>();\r
1778 \r
1779                 for (int i = 0; i < oldTagArray.length; i++)\r
1780                         if (!oldTagArray[i].trim().equals(""))\r
1781                                 oldTagList.add(oldTagArray[i]);\r
1782                 for (int i = 0; i < newTagArray.length; i++)\r
1783                         if (!newTagArray[i].trim().equals(""))\r
1784                                 newTagList.add(newTagArray[i]);\r
1785 \r
1786                 if (conn.getNotebookTable().isLinked(currentNote.getNotebookGuid())) {\r
1787                         for (int i=newTagList.size()-1; i>=0; i--) {\r
1788                                 boolean found = false;\r
1789                                 for (int j=0; j<allTags.size(); j++) {\r
1790                                         if (allTags.get(j).getName().equalsIgnoreCase(newTagList.get(i))) {\r
1791                                                 found = true;\r
1792                                                 j=allTags.size();\r
1793                                         }\r
1794                                 }\r
1795                                 if (!found)\r
1796                                         newTagList.remove(i);\r
1797                         }\r
1798                 }\r
1799 \r
1800                 // Let's cleanup the appearance of the tag list\r
1801                 Collections.sort(newTagList);\r
1802                 String newDisplay = "";\r
1803                 for (int i=0; i<newTagList.size(); i++) {\r
1804                         newDisplay = newDisplay+newTagList.get(i);\r
1805                         if (i<newTagList.size()-1)\r
1806                                 newDisplay = newDisplay+Global.tagDelimeter +" ";\r
1807                 }\r
1808                 tagEdit.blockSignals(true);\r
1809                 tagEdit.setText(newDisplay);\r
1810                 tagEdit.blockSignals(false);\r
1811                 \r
1812                 // We now have lists of the new & old. Remove duplicates. If all\r
1813                 // are removed from both then nothing has really changed\r
1814                 for (int i = newTagList.size() - 1; i >= 0; i--) {\r
1815                         String nTag = newTagList.get(i);\r
1816                         for (int j = oldTagList.size() - 1; j >= 0; j--) {\r
1817                                 String oTag = oldTagList.get(j);\r
1818                                 if (oTag.equalsIgnoreCase(nTag)) {\r
1819                                         oldTagList.remove(j);\r
1820                                         newTagList.remove(i);\r
1821                                         j = -1;\r
1822                                 }\r
1823                         }\r
1824                 }\r
1825 \r
1826                 if (oldTagList.size() != 0 || newTagList.size() != 0) {\r
1827                         currentTags.clear();\r
1828                         newTagArray = tagEdit.text().split(Global.tagDelimeter);\r
1829                         for (int i = 0; i < newTagArray.length; i++)\r
1830                                 if (!newTagArray[i].trim().equals(""))\r
1831                                         currentTags.add(newTagArray[i].trim());\r
1832 \r
1833                         noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);\r
1834                 }\r
1835                 \r
1836         }\r
1837 \r
1838         // Tab button was pressed\r
1839         public void tabPressed() {\r
1840                 if (insideEncryption)\r
1841                         return;\r
1842                 if (!insideList && !insideTable) {\r
1843                         String script_start = new String(\r
1844                         "document.execCommand('insertHtml', false, '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');");\r
1845                         browser.page().mainFrame().evaluateJavaScript(script_start);\r
1846                         return;\r
1847                 }\r
1848                 if (insideList) {\r
1849                         indentClicked();\r
1850                 }\r
1851                 if (insideTable) {\r
1852                         String js = new String( "function getCursorPosition() { "\r
1853                                         +"   var selObj = window.getSelection();"\r
1854                                         +"   var selRange = selObj.getRangeAt(0);"\r
1855                                         +"   var workingNode = window.getSelection().anchorNode;"\r
1856                                         +"   var rowCount = 0;"\r
1857                                         +"   var colCount = 0;"\r
1858                                         +"   while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { " \r
1859                                         +"      if (workingNode.nodeName.toLowerCase()=='tr') {"\r
1860                                         +"         rowCount = rowCount+1;"\r
1861                                         +"      }"\r
1862                                         +"      if (workingNode.nodeName.toLowerCase() == 'td') {"\r
1863                                         +"         colCount = colCount+1;"\r
1864                                         +"      }"\r
1865                                         +"      if (workingNode.previousSibling != null)"\r
1866                                         +"          workingNode = workingNode.previousSibling;"\r
1867                                         +"      else "\r
1868                                         +"           workingNode = workingNode.parentNode;"\r
1869                                         +"   }"\r
1870                                         +"   var nodes = workingNode.getElementsByTagName('tr');"\r
1871                                         +"   var tableRows = nodes.length;"\r
1872                                         +"   nodes = nodes[0].getElementsByTagName('td');"\r
1873                                         +"   var tableColumns = nodes.length;"\r
1874                                         +"   window.jambi.setTableCursorPositionTab(rowCount, colCount, tableRows, tableColumns);"\r
1875                                         +"} getCursorPosition();");\r
1876                         browser.page().mainFrame().evaluateJavaScript(js);\r
1877                 }\r
1878         }\r
1879         \r
1880         // If a user presses tab from within a table\r
1881         public void setTableCursorPositionTab(int currentRow, int currentCol, int tableRows, int tableColumns) {\r
1882                 if (tableRows == currentRow && currentCol == tableColumns) {\r
1883                         insertTableRow();\r
1884                 }\r
1885                 KeyboardModifiers modifiers = new KeyboardModifiers(KeyboardModifier.NoModifier);\r
1886                 QKeyEvent right = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Right.value(), modifiers);\r
1887                 QKeyEvent end = new QKeyEvent(Type.KeyPress, Qt.Key.Key_End.value(), modifiers);\r
1888                 QKeyEvent end2 = new QKeyEvent(Type.KeyPress, Qt.Key.Key_End.value(), modifiers);\r
1889                 getBrowser().focusWidget();\r
1890                 QCoreApplication.postEvent(getBrowser(), end);\r
1891                 QCoreApplication.postEvent(getBrowser(), right);\r
1892                 QCoreApplication.postEvent(getBrowser(), end2);\r
1893         }\r
1894                 \r
1895         public void backtabPressed() {\r
1896                 if (insideEncryption) \r
1897                         return;\r
1898                 if (insideList)\r
1899                         outdentClicked();\r
1900                 if (insideTable) {\r
1901                         String js = new String( "function getCursorPosition() { "\r
1902                                         +"   var selObj = window.getSelection();"\r
1903                                         +"   var selRange = selObj.getRangeAt(0);"\r
1904                                         +"   var workingNode = window.getSelection().anchorNode;"\r
1905                                         +"   var rowCount = 0;"\r
1906                                         +"   var colCount = 0;"\r
1907                                         +"   while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { " \r
1908                                         +"      if (workingNode.nodeName.toLowerCase()=='tr') {"\r
1909                                         +"         rowCount = rowCount+1;"\r
1910                                         +"      }"\r
1911                                         +"      if (workingNode.nodeName.toLowerCase() == 'td') {"\r
1912                                         +"         colCount = colCount+1;"\r
1913                                         +"      }"\r
1914                                         +"      if (workingNode.previousSibling != null)"\r
1915                                         +"          workingNode = workingNode.previousSibling;"\r
1916                                         +"      else "\r
1917                                         +"           workingNode = workingNode.parentNode;"\r
1918                                         +"   }"\r
1919                                         +"   var nodes = workingNode.getElementsByTagName('tr');"\r
1920                                         +"   var tableRows = nodes.length;"\r
1921                                         +"   nodes = nodes[0].getElementsByTagName('td');"\r
1922                                         +"   var tableColumns = nodes.length;"\r
1923                                         +"   window.jambi.setTableCursorPositionBackTab(rowCount, colCount, tableRows, tableColumns);"\r
1924                                         +"} getCursorPosition();");\r
1925                         browser.page().mainFrame().evaluateJavaScript(js);\r
1926                         \r
1927                 }\r
1928         }\r
1929         \r
1930         // If a user presses backtab from within a table\r
1931         public void setTableCursorPositionBackTab(int currentRow, int currentCol, int tableRows, int tableColumns) {\r
1932                 if (currentRow  == 1 && currentCol == 1) {\r
1933                         return;\r
1934                 }\r
1935                 KeyboardModifiers modifiers = new KeyboardModifiers(KeyboardModifier.NoModifier);\r
1936                 QKeyEvent left = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Left.value(), modifiers);\r
1937                 QKeyEvent home = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Home.value(), modifiers);\r
1938                 getBrowser().focusWidget();\r
1939                 QCoreApplication.postEvent(getBrowser(), home);\r
1940                 QCoreApplication.postEvent(getBrowser(), left);\r
1941         }\r
1942         \r
1943         \r
1944         public void setInsideList() {\r
1945                 insideList = true;\r
1946         }\r
1947         \r
1948         // The title has been edited\r
1949         @SuppressWarnings("unused")\r
1950         private void titleEdited() {\r
1951                 // If we don't have a good note, or if the current title\r
1952                 // matches the old title then we don't need to do anything\r
1953                 if (currentNote == null)\r
1954                         return;\r
1955                 if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))\r
1956                         return;\r
1957                 \r
1958                 // If we have a real change, we need to save it.\r
1959                 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text());\r
1960                 currentNote.setTitle(titleLabel.text());\r
1961                 saveNoteTitle = titleLabel.text();\r
1962                 checkNoteTitle();\r
1963         }\r
1964 \r
1965         // Set the list of note tags\r
1966         public void setAllTags(List<Tag> l) {\r
1967                 allTags = l;\r
1968                 tagEdit.setTagList(l);\r
1969         }\r
1970 \r
1971         // Setter for the current tags\r
1972         public void setCurrentTags(List<String> s) {\r
1973                 currentTags = s;\r
1974         }\r
1975 \r
1976         // Save the list of notebooks\r
1977         public void setNotebookList(List<Notebook> n) {\r
1978                 notebookList = n;\r
1979                 loadNotebookList();\r
1980         }\r
1981 \r
1982         // Load the notebook list and select the current notebook\r
1983         private void loadNotebookList() {\r
1984                 if (notebookBox.count() != 0)\r
1985                         notebookBox.clear();\r
1986                 if (notebookList == null)\r
1987                         return;\r
1988 \r
1989                 for (int i = 0; i < notebookList.size(); i++) {\r
1990                         notebookBox.addItem(notebookList.get(i).getName());\r
1991                         if (currentNote != null) {\r
1992                                 if (currentNote.getNotebookGuid().equals(\r
1993                                                 notebookList.get(i).getGuid())) {\r
1994                                         notebookBox.setCurrentIndex(i);\r
1995                                 }\r
1996                         }\r
1997                 }\r
1998         }\r
1999         \r
2000         \r
2001         // Set the notebook for a note\r
2002         public void setNotebook(String notebook) {\r
2003                 currentNote.setNotebookGuid(notebook);\r
2004                 loadNotebookList();\r
2005         }\r
2006 \r
2007         // Get the contents of the editor\r
2008         public String getContent() {\r
2009                 return browser.page().currentFrame().toHtml();\r
2010         }\r
2011 \r
2012         // The note contents have changed\r
2013         public void contentChanged() {\r
2014                 String content = getContent();\r
2015                 checkNoteTitle();\r
2016                 noteSignal.noteChanged.emit(currentNote.getGuid(), content); \r
2017         }\r
2018 \r
2019         // The notebook selection has changed\r
2020         @SuppressWarnings("unused")\r
2021         private void notebookChanged() {\r
2022                 boolean changed = false;\r
2023                 String n = notebookBox.currentText();\r
2024                 for (int i = 0; i < notebookList.size(); i++) {\r
2025                         if (n.equals(notebookList.get(i).getName())) {\r
2026                                 if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {\r
2027                                         String guid = conn.getNotebookTable().findNotebookByName(n);\r
2028                                         if (conn.getNotebookTable().isLinked(guid)) {\r
2029                                                 tagEdit.setText("");\r
2030                                                 noteSignal.tagsChanged.emit(currentNote.getGuid(), new ArrayList<String>());\r
2031                                                 FilterEditorTags t = new FilterEditorTags(conn, logger);\r
2032                                                 setAllTags(t.getValidTags(currentNote));\r
2033                                         }\r
2034                                         currentNote.setNotebookGuid(notebookList.get(i).getGuid());\r
2035                                         changed = true;\r
2036                                 }\r
2037                                 i = notebookList.size();\r
2038                         }\r
2039                 }\r
2040                 \r
2041                 // If the notebook changed, signal the update\r
2042                 if (changed)\r
2043                         noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote\r
2044                                         .getNotebookGuid());\r
2045         }\r
2046 \r
2047         // Check the note title\r
2048         private void checkNoteTitle() {\r
2049                 String text = browser.page().currentFrame().toPlainText();\r
2050                 if (saveNoteTitle.trim().equals("") || saveNoteTitle.trim().equals("Untitled Note")) {\r
2051                         int newLine = text.indexOf("\n");\r
2052                         if (newLine > 0) {\r
2053                                 text = text.substring(0, newLine);\r
2054                                 if (text.trim().equals(""))\r
2055                                         text = tr("Untitled Note");\r
2056                                 titleLabel.setText(text);\r
2057                         } else {\r
2058                                 if (text.length() > Constants.EDAM_NOTE_TITLE_LEN_MAX)\r
2059                                         titleLabel.setText(text.substring(0, Constants.EDAM_NOTE_TITLE_LEN_MAX));\r
2060                                 else {\r
2061                                         titleLabel.blockSignals(true);\r
2062                                         if (text.trim().equals(""))\r
2063                                                 titleLabel.setText(tr("Untitled Note"));\r
2064                                         else\r
2065                                                 titleLabel.setText(text);\r
2066                                         titleLabel.blockSignals(false);\r
2067                                 }\r
2068                         }\r
2069                         noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel\r
2070                                         .text());\r
2071                 }\r
2072         }\r
2073 \r
2074         // Return the note contents so we can email them\r
2075         public String getContentsToEmail() {\r
2076                 return browser.page().currentFrame().toPlainText().trim();\r
2077                 /*\r
2078                  * int body = browser.page().currentFrame().toHtml().indexOf("<body>");\r
2079                  * String temp = browser.page().currentFrame().toHtml(); if (body == -1)\r
2080                  * temp = "<html><body><b>Test</b></body></html>"; else temp =\r
2081                  * "<html>"+temp.substring(body); return temp; // return\r
2082                  * urlEncode(browser.page().currentFrame().toHtml());\r
2083                  */\r
2084         }\r
2085 \r
2086         // Insert an image into the editor\r
2087         private void insertImage(QMimeData mime) {\r
2088                 logger.log(logger.EXTREME, "Entering insertImage");\r
2089                 QImage img = (QImage) mime.imageData();\r
2090                 String script_start = new String(\r
2091                                 "document.execCommand('insertHTML', false, '");\r
2092                 String script_end = new String("');");\r
2093 \r
2094                 long now = new Date().getTime();\r
2095                 String path = Global.getFileManager().getResDirPath(\r
2096                                 (new Long(now).toString()) + ".jpg");\r
2097 \r
2098                 // This block is just a hack to make sure we wait at least 1ms so we\r
2099                 // don't\r
2100                 // have collisions on image names\r
2101                 long i = new Date().getTime();\r
2102                 while (now == i)\r
2103                         i = new Date().getTime();\r
2104 \r
2105                 // Open the file & write the data\r
2106                 QFile tfile = new QFile(path);\r
2107                 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));\r
2108                 if (!img.save(tfile)) {\r
2109                         tfile.close();\r
2110                         return;\r
2111                 }\r
2112                 tfile.close();\r
2113                 \r
2114                 Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);\r
2115                 if (newRes == null)\r
2116                         return;\r
2117                 currentNote.getResources().add(newRes);\r
2118 \r
2119                 // do the actual insert into the note\r
2120                 StringBuffer buffer = new StringBuffer(100);\r
2121                 buffer.append("<img src=\"");\r
2122                 buffer.append(tfile.fileName());\r
2123                 buffer.append("\" en-tag=en-media type=\"image/jpeg\""\r
2124                                 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""\r
2125                                 +" guid=\"" +newRes.getGuid() +"\""\r
2126                                 +" onContextMenu=\"window.jambi.imageContextMenu(&amp." +tfile.fileName() +"&amp.);\""\r
2127                                 + " />");\r
2128                 \r
2129                 browser.page().mainFrame().evaluateJavaScript(\r
2130                                 script_start + buffer + script_end);\r
2131 \r
2132                 return;\r
2133         }\r
2134 \r
2135         // Handle pasting of a note-to-note link\r
2136         private void handleNoteLink(QMimeData mime) {\r
2137                 for (int i=0; i<mime.urls().size(); i++) {\r
2138                         StringTokenizer tokens = new StringTokenizer(mime.urls().get(i).toString().replace("evernote:///view/", ""), "/");\r
2139                         tokens.nextToken();\r
2140                         tokens.nextToken();\r
2141                         String sid = tokens.nextToken();\r
2142                         String lid = tokens.nextToken();\r
2143                         \r
2144                         if (!sid.equals(currentNote.getGuid()) && !lid.equals(currentNote.getGuid())) {\r
2145                                 \r
2146                                 Note note = conn.getNoteTable().getNote(sid, false, false, false, false, false);\r
2147                                 if (note == null)\r
2148                                         note = conn.getNoteTable().getNote(lid, false, false, false, false, false);\r
2149                 \r
2150                                 if (note == null)\r
2151                                         return;\r
2152 \r
2153                                 // If we've gotten this far, we have a bunch of values.  We need to build the link.\r
2154                                 StringBuffer url = new StringBuffer(100);\r
2155                                 String script_start = new String(\r
2156                                         "document.execCommand('insertHtml', false, '");\r
2157                                 String script_end = new String("');");\r
2158         \r
2159                                 url.append("<a href=\""+mime.urls().get(i).toString() +"\" style=\"color:#69aa35\">");\r
2160                                 url.append(note.getTitle());\r
2161                                 url.append("</a>");\r
2162                                 if (mime.urls().size() > 1)\r
2163                                         url.append("&nbsp;");\r
2164                                 browser.page().mainFrame().evaluateJavaScript(\r
2165                                                 script_start + url + script_end);\r
2166                         }\r
2167                 }\r
2168         }\r
2169         \r
2170         // Handle URLs that are trying to be pasted\r
2171         public void handleUrls(QMimeData mime) {\r
2172                 logger.log(logger.EXTREME, "Starting handleUrls");\r
2173                 FileNameMap fileNameMap = URLConnection.getFileNameMap();\r
2174 \r
2175                 List<QUrl> urlList = mime.urls();\r
2176                 String url = new String();\r
2177                 String script_start = new String(\r
2178                                 "document.execCommand('createLink', false, '");\r
2179                 String script_end = new String("');");\r
2180 \r
2181                 for (int i = 0; i < urlList.size(); i++) {\r
2182                         url = urlList.get(i).toString();\r
2183                         // Find out what type of file we have\r
2184                         String mimeType = fileNameMap.getContentTypeFor(url);\r
2185 \r
2186                         // If null returned, we need to guess at the file type\r
2187                         if (mimeType == null)\r
2188                                 mimeType = "application/"\r
2189                                                 + url.substring(url.lastIndexOf(".") + 1);\r
2190 \r
2191                         // Check if we have an image or some other type of file\r
2192                         if (url.substring(0, 5).equalsIgnoreCase("file:")\r
2193                                         && mimeType.substring(0, 5).equalsIgnoreCase("image")) {\r
2194                                 handleLocalImageURLPaste(mime, mimeType);\r
2195                                 return;\r
2196                         }\r
2197                         String[] type = mimeType.split("/");\r
2198                         boolean valid = validAttachment(type[1]);\r
2199                         boolean smallEnough = checkFileAttachmentSize(url);\r
2200                         if (smallEnough && valid\r
2201                                         && url.substring(0, 5).equalsIgnoreCase("file:")\r
2202                                         && !mimeType.substring(0, 5).equalsIgnoreCase("image")) {\r
2203                                 handleLocalAttachment(mime, mimeType);\r
2204                                 return;\r
2205                         }\r
2206                         browser.page().mainFrame().evaluateJavaScript(\r
2207                                         script_start + url + script_end);\r
2208                 }\r
2209                 return;\r
2210         }\r
2211 \r
2212         // If a URL being pasted is an image URL, then attach the image\r
2213         private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {\r
2214                 List<QUrl> urlList = mime.urls();\r
2215                 String url = new String();\r
2216                 String script_start_image = new String(\r
2217                                 "document.execCommand('insertHtml', false, '");\r
2218                 String script_end = new String("');");\r
2219                 StringBuffer buffer;\r
2220 \r
2221                 // Copy the image over into the resource directory and create a new resource \r
2222                 // record for each url pasted\r
2223                 for (int i = 0; i < urlList.size(); i++) {\r
2224                         url = urlList.get(i).toString();\r
2225 \r
2226                         Resource newRes = createResource(url, i, mimeType, false);\r
2227                         if (newRes == null)\r
2228                                 return;\r
2229                         currentNote.getResources().add(newRes);\r
2230                         buffer = new StringBuffer(100);\r
2231                         \r
2232                         // Open the file & write the data\r
2233                         String fileName = Global.getFileManager().getResDirPath(newRes.getGuid());\r
2234                         QFile tfile = new QFile(fileName);\r
2235                         tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));\r
2236                         tfile.write(newRes.getData().getBody());\r
2237                         tfile.close();\r
2238                         buffer.append(script_start_image);\r
2239                         buffer.append("<img src=\"" + FileUtils.toForwardSlashedPath(fileName));\r
2240 //                      if (mimeType.equalsIgnoreCase("image/jpg"))\r
2241 //                              mimeType = "image/jpeg";\r
2242                         buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""\r
2243                                         +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""\r
2244                                         +" guid=\"" +newRes.getGuid() +"\""\r
2245                                         +" onContextMenu=\"window.jambi.imageContextMenu(&apos;" +tfile.fileName() +"&apos;);\""\r
2246                                         + " />");\r
2247                         buffer.append(script_end);\r
2248                         browser.page().mainFrame().evaluateJavaScript(buffer.toString());\r
2249                 }\r
2250                 return;\r
2251         }\r
2252         \r
2253 \r
2254         // If a URL being pasted is a local file URL, then attach the file\r
2255         private void handleLocalAttachment(QMimeData mime, String mimeType) {\r
2256                 logger.log(logger.EXTREME, "Attaching local file");\r
2257                 List<QUrl> urlList = mime.urls();\r
2258                 String script_start = new String(\r
2259                                 "document.execCommand('insertHtml', false, '");\r
2260                 String script_end = new String("');");\r
2261                 StringBuffer buffer;\r
2262 \r
2263                         String[] type = mimeType.split("/");\r
2264                         String icon = findIcon(type[1]);\r
2265                         if (icon.equals("attachment.png"))\r
2266                                 icon = findIcon(type[0]);\r
2267                         buffer = new StringBuffer(100);\r
2268 \r
2269                 for (int i = 0; i < urlList.size(); i++) {\r
2270                         String url = urlList.get(i).toString();\r
2271 \r
2272                         // Start building the HTML\r
2273                         if (icon.equals("attachment.png"))\r
2274                                 icon = findIcon(url.substring(url.lastIndexOf(".")+1));\r
2275                         String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));\r
2276 \r
2277                         logger.log(logger.EXTREME, "Creating resource ");\r
2278                         Resource newRes = createResource(url, i, mimeType, true);\r
2279                         if (newRes == null)\r
2280                                 return;\r
2281                         logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());\r
2282                         currentNote.getResources().add(newRes);\r
2283                         \r
2284                         String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();\r
2285                         // If we have a PDF, we need to setup the preview.\r
2286                         if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {\r
2287                                 logger.log(logger.EXTREME, "Setting up PDF preview");\r
2288                                 if (newRes.getAttributes() != null && \r
2289                                                 newRes.getAttributes().getFileName() != null && \r
2290                                                 !newRes.getAttributes().getFileName().trim().equals(""))\r
2291                                         fileName = newRes.getGuid()+Global.attachmentNameDelimeter+\r
2292                                                 newRes.getAttributes().getFileName();\r
2293                                 else\r
2294                                         fileName = newRes.getGuid()+".pdf";\r
2295                                 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));\r
2296                         QFile.OpenMode mode = new QFile.OpenMode();\r
2297                         mode.set(QFile.OpenModeFlag.WriteOnly);\r
2298                         file.open(mode);\r
2299                         QDataStream out = new QDataStream(file);\r
2300 //                      Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);\r
2301                                 QByteArray binData = new QByteArray(newRes.getData().getBody());\r
2302 //                              resBinary = null;\r
2303                         out.writeBytes(binData.toByteArray());\r
2304                         file.close();\r
2305 \r
2306                                 PDFPreview pdfPreview = new PDFPreview();\r
2307                                 if (pdfPreview.setupPreview(Global.getFileManager().getResDirPath(fileName), "pdf",0)) {\r
2308                                 imageURL = file.fileName() + ".png";\r
2309                                 }\r
2310                         }\r
2311                                                 \r
2312                         logger.log(logger.EXTREME, "Generating link tags");\r
2313                         buffer.delete(0, buffer.length());\r
2314                         buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");\r
2315                         buffer.append(" onContextMenu=\"window.jambi.imageContextMenu(&apos;")\r
2316                       .append(Global.getFileManager().getResDirPath(fileName))\r
2317                       .append("&apos;);\" ");                   buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");\r
2318                         buffer.append("<img src=\"" + imageURL + "\" title=\"" +newRes.getAttributes().getFileName());\r
2319                         buffer.append("\"></img>");\r
2320                         buffer.append("</a>");\r
2321                         browser.page().mainFrame().evaluateJavaScript(\r
2322                                         script_start + buffer.toString() + script_end);\r
2323                 }\r
2324                 return;\r
2325         }\r
2326 \r
2327         private Resource createResource(String url, int sequence, String mime, boolean attachment) {\r
2328                 logger.log(logger.EXTREME, "Inside create resource");\r
2329                 QFile resourceFile;\r
2330                 String urlTest = new QUrl(url).toLocalFile();\r
2331                 if (!urlTest.equals(""))\r
2332                         url = urlTest;\r
2333                 url = url.replace("/", File.separator);\r
2334                 logger.log(logger.EXTREME, "Reading from file to create resource");\r
2335         resourceFile = new QFile(url); \r
2336         resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));\r
2337 //      logger.log(logger.EXTREME, "Error opening file "+url.toString()  +": "+resourceFile.errorString());\r
2338         byte[] fileData = resourceFile.readAll().toByteArray();\r
2339         resourceFile.close();\r
2340         if (fileData.length == 0)\r
2341                 return null;\r
2342         MessageDigest md;\r
2343         try {\r
2344                 logger.log(logger.EXTREME, "Generating MD5");\r
2345                 md = MessageDigest.getInstance("MD5");\r
2346                 md.update(fileData);\r
2347                 byte[] hash = md.digest();\r
2348   \r
2349                 Resource r = new Resource();\r
2350                 Calendar time = new GregorianCalendar();\r
2351                 long prevTime = time.getTimeInMillis();\r
2352                 while (prevTime == time.getTimeInMillis()) {\r
2353                         time = new GregorianCalendar();\r
2354                 }\r
2355                 r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());\r
2356                 r.setNoteGuid(currentNote.getGuid());\r
2357                 r.setMime(mime);\r
2358                 r.setActive(true);\r
2359                 r.setUpdateSequenceNum(0);\r
2360                 r.setWidth((short) 0);\r
2361                 r.setHeight((short) 0);\r
2362                 r.setDuration((short) 0);\r
2363                                 \r
2364                 Data d = new Data();\r
2365                 d.setBody(fileData);\r
2366                 d.setBodyIsSet(true);\r
2367                 d.setBodyHash(hash);\r
2368                 d.setBodyHashIsSet(true);\r
2369                 r.setData(d);\r
2370                 d.setSize(fileData.length);\r
2371                 \r
2372                 int fileNamePos = url.lastIndexOf(File.separator);\r
2373                 if (fileNamePos == -1)\r
2374                         fileNamePos = url.lastIndexOf("/");\r
2375                         String fileName = url.substring(fileNamePos+1);\r
2376                 ResourceAttributes a = new ResourceAttributes();\r
2377                 a.setAltitude(0);\r
2378                 a.setAltitudeIsSet(false);\r
2379                 a.setLongitude(0);\r
2380                 a.setLongitudeIsSet(false);\r
2381                 a.setLatitude(0);\r
2382                 a.setLatitudeIsSet(false);\r
2383                 a.setCameraMake("");\r
2384                 a.setCameraMakeIsSet(false);\r
2385                 a.setCameraModel("");\r
2386                 a.setCameraModelIsSet(false);\r
2387                 a.setAttachment(attachment);\r
2388                 a.setAttachmentIsSet(true);\r
2389                 a.setClientWillIndex(false);\r
2390                 a.setClientWillIndexIsSet(true);\r
2391                 a.setRecoType("");\r
2392                 a.setRecoTypeIsSet(false);\r
2393                 a.setSourceURL(url);\r
2394                 a.setSourceURLIsSet(true);\r
2395                 a.setTimestamp(0);\r
2396                 a.setTimestampIsSet(false);\r
2397                 a.setFileName(fileName);\r
2398                 a.setFileNameIsSet(true);\r
2399                 r.setAttributes(a);\r
2400                 \r
2401                 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);\r
2402                 logger.log(logger.EXTREME, "Resource created");\r
2403                 return r;\r
2404         } catch (NoSuchAlgorithmException e1) {\r
2405                 e1.printStackTrace();\r
2406                 }\r
2407         return null;\r
2408         }\r
2409         \r
2410 \r
2411     // find the appropriate icon for an attachment\r
2412     private String findIcon(String appl) {\r
2413         appl = appl.toLowerCase();\r
2414         File f = Global.getFileManager().getImageDirFile(appl + ".png");\r
2415         if (f.exists())\r
2416                 return appl+".png";\r
2417         return "attachment.png";\r
2418     }\r
2419 \r
2420         // Check if the account supports this type of attachment\r
2421         private boolean validAttachment(String type) {\r
2422                 if (Global.isPremium())\r
2423                         return true;\r
2424                 if (type.equalsIgnoreCase("JPG"))\r
2425                         return true;\r
2426                 if (type.equalsIgnoreCase("PNG"))\r
2427                         return true;\r
2428                 if (type.equalsIgnoreCase("GIF"))\r
2429                         return true;\r
2430                 if (type.equalsIgnoreCase("MP3"))\r
2431                         return true;\r
2432                 if (type.equalsIgnoreCase("WAV"))\r
2433                         return true;\r
2434                 if (type.equalsIgnoreCase("AMR"))\r
2435                         return true;\r
2436                 if (type.equalsIgnoreCase("PDF"))\r
2437                         return true;\r
2438                 String error = tr("Non-premium accounts can only attach JPG, PNG, GIF, MP3, WAV, AMR, or PDF files.");\r
2439                 QMessageBox.information(this, tr("Non-Premium Account"), error);\r
2440 \r
2441                 return false;\r
2442         }\r
2443 \r
2444         // Check the file attachment to be sure it isn't over 25 mb\r
2445         private boolean checkFileAttachmentSize(String url) {\r
2446                 String fileName = url.substring(8);\r
2447                 QFile resourceFile = new QFile(fileName);\r
2448                 resourceFile.open(new QIODevice.OpenMode(\r
2449                                 QIODevice.OpenModeFlag.ReadOnly));\r
2450                 long size = resourceFile.size();\r
2451                 resourceFile.close();\r
2452                 size = size / 1024 / 1024;\r
2453                 if (size < 50 && Global.isPremium())\r
2454                         return true;\r
2455                 if (size < 25)\r
2456                         return true;\r
2457 \r
2458                 String error = tr("A file attachment may not exceed 25MB.");\r
2459                 QMessageBox.information(this, tr("Attachment Size"), error);\r
2460                 return false;\r
2461         }\r
2462 \r
2463 \r
2464         @SuppressWarnings("unused")\r
2465         private void createdChanged() {\r
2466                 QDateTime dt = new QDateTime();\r
2467                 dt.setDate(createdDate.date());\r
2468                 dt.setTime(createdTime.time());\r
2469                 noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);\r
2470 \r
2471         }\r
2472 \r
2473         @SuppressWarnings("unused")\r
2474         private void alteredChanged() {\r
2475                 QDateTime dt = new QDateTime();\r
2476                 dt.setDate(alteredDate.date());\r
2477                 dt.setTime(alteredTime.time());\r
2478                 noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);\r
2479         }\r
2480 \r
2481         @SuppressWarnings("unused")\r
2482         private void subjectDateTimeChanged() {\r
2483                 QDateTime dt = new QDateTime();\r
2484                 dt.setDate(subjectDate.date());\r
2485                 dt.setTime(subjectTime.time());\r
2486                 noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);\r
2487 \r
2488         }\r
2489 \r
2490         @SuppressWarnings("unused")\r
2491         private void sourceUrlChanged() {\r
2492                 noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());\r
2493         }\r
2494 \r
2495         @SuppressWarnings("unused")\r
2496         private void authorChanged() {\r
2497                 noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());\r
2498         }\r
2499         \r
2500         @SuppressWarnings("unused")\r
2501         private void geoBoxChanged() {\r
2502                 int index = geoBox.currentIndex();\r
2503                 geoBox.setCurrentIndex(0);\r
2504                 if (index == 1) {\r
2505                         GeoDialog box = new GeoDialog();\r
2506                         box.setLongitude(currentNote.getAttributes().getLongitude());\r
2507                         box.setLatitude(currentNote.getAttributes().getLatitude());\r
2508                         box.setAltitude(currentNote.getAttributes().getAltitude());\r
2509                         box.exec();\r
2510                         if (!box.okPressed())\r
2511                                 return;\r
2512                         double alt = box.getAltitude();\r
2513                         double lat = box.getLatitude();\r
2514                         double lon = box.getLongitude();\r
2515                         if (alt != currentNote.getAttributes().getAltitude() ||\r
2516                                 lon != currentNote.getAttributes().getLongitude() ||\r
2517                                 lat != currentNote.getAttributes().getLatitude()) {\r
2518                                         noteSignal.geoChanged.emit(currentNote.getGuid(), lon, lat, alt);\r
2519                                         currentNote.getAttributes().setAltitude(alt);\r
2520                                         currentNote.getAttributes().setLongitude(lon);\r
2521                                         currentNote.getAttributes().setLatitude(lat);\r
2522                         }\r
2523                 }\r
2524                 \r
2525                 if (index == 2) {\r
2526                         noteSignal.geoChanged.emit(currentNote.getGuid(), 0.0, 0.0, 0.0);\r
2527                         currentNote.getAttributes().setAltitude(0.0);\r
2528                         currentNote.getAttributes().setLongitude(0.0);\r
2529                         currentNote.getAttributes().setLatitude(0.0);\r
2530                 }\r
2531                 \r
2532                 if (index == 3 || index == 0) {\r
2533                         QDesktopServices.openUrl(new QUrl("http://maps.google.com/maps?z=6&q="+currentNote.getAttributes().getLatitude() +"," +currentNote.getAttributes().getLongitude()));\r
2534                 }\r
2535         }\r
2536 \r
2537         // ************************************************************\r
2538         // * User chose to save an attachment. Pares out the request *\r
2539         // * into a guid & file. Save the result. *\r
2540         // ************************************************************\r
2541         public void downloadAttachment(QNetworkRequest request) {\r
2542                 String guid;\r
2543                 QFileDialog fd = new QFileDialog(this);\r
2544                 fd.setFileMode(FileMode.AnyFile);\r
2545                 fd.setConfirmOverwrite(true);\r
2546                 fd.setWindowTitle(tr("Save File"));\r
2547                 fd.setAcceptMode(AcceptMode.AcceptSave);\r
2548                 fd.setDirectory(System.getProperty("user.home"));\r
2549                 String name = request.url().toString();\r
2550 \r
2551                 int pos = name.lastIndexOf(Global.attachmentNameDelimeter);\r
2552                 if (pos > -1) {\r
2553                         guid = name.substring(0, pos).replace("nnres://", "");\r
2554                         name = name.substring(pos +Global.attachmentNameDelimeter.length());\r
2555                         fd.selectFile(name);\r
2556                         pos = name.lastIndexOf('.');\r
2557                         if (pos > -1) {\r
2558                                 String mimeType = "(*." + name.substring(pos + 1)\r
2559                                                 + ");; All Files (*)";\r
2560                                 fd.setFilter(tr(mimeType));\r
2561                         }\r
2562                 } else {\r
2563                         guid = name;\r
2564                 }\r
2565 \r
2566                 // Strip URL prefix and base dir\r
2567                 guid = guid.replace("nnres://", "")\r
2568                         .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");\r
2569                 guid = guid.replace("file://", "").replace("/", "")\r
2570                 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");\r
2571 \r
2572                 pos = guid.lastIndexOf('.');\r
2573                 if (pos > 0)\r
2574                         guid = guid.substring(0,pos);\r
2575                 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {\r
2576                         name = name.replace('\\', '/');\r
2577                         Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);\r
2578                         QFile saveFile = new QFile(fd.selectedFiles().get(0));\r
2579                         QFile.OpenMode mode = new QFile.OpenMode();\r
2580                         mode.set(QFile.OpenModeFlag.WriteOnly);\r
2581                         saveFile.open(mode);\r
2582                         QDataStream saveOut = new QDataStream(saveFile);\r
2583                         QByteArray binData = new QByteArray(resBinary.getData().getBody());\r
2584                         saveOut.writeBytes(binData.toByteArray());\r
2585                         saveFile.close();\r
2586 \r
2587                 }\r
2588         }\r
2589 \r
2590         \r
2591         // ************************************************************\r
2592         // * User chose to save an attachment. Pares out the request *\r
2593         // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!   \r
2594         // ************************************************************\r
2595         public void downloadImage(QNetworkRequest request) {\r
2596                 QFileDialog fd = new QFileDialog(this);\r
2597                 fd.setFileMode(FileMode.AnyFile);\r
2598                 fd.setConfirmOverwrite(true);\r
2599                 fd.setWindowTitle(tr("Save File"));\r
2600                 fd.setAcceptMode(AcceptMode.AcceptSave);\r
2601                 fd.setDirectory(System.getProperty("user.home"));\r
2602                 String name = request.url().toString();\r
2603                 name = name.replace("nnres://", "");\r
2604                 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());\r
2605                 name = name.replace(dPath, "");\r
2606                 int pos = name.lastIndexOf('.');\r
2607                 String guid = name;\r
2608                 if (pos > -1) {\r
2609                         String mimeType = "(*." + name.substring(pos + 1)\r
2610                         + ");; All Files (*)";\r
2611                                 fd.setFilter(tr(mimeType));\r
2612                         guid = guid.substring(0,pos);\r
2613                 }\r
2614                 pos = name.lastIndexOf(Global.attachmentNameDelimeter);\r
2615                 if (pos > -1) {\r
2616                         guid = name.substring(0, pos);\r
2617                         fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));             \r
2618                 }\r
2619                 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {\r
2620                         Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);\r
2621                         String fileName = fd.selectedFiles().get(0);\r
2622                         QFile saveFile = new QFile(fileName);\r
2623                         QFile.OpenMode mode = new QFile.OpenMode();\r
2624                         mode.set(QFile.OpenModeFlag.WriteOnly);\r
2625                         saveFile.open(mode);\r
2626                         QDataStream saveOut = new QDataStream(saveFile);\r
2627                         QByteArray binData = new QByteArray(resBinary.getData().getBody());\r
2628                         saveOut.writeBytes(binData.toByteArray());\r
2629                         saveFile.close();\r
2630                 }\r
2631         }\r
2632 \r
2633         \r
2634         // *************************************************************\r
2635         // * decrypt any hidden text.  We could do an XML parse, but \r
2636         // * it is quicker here just to scan for an <img tag & do the fix\r
2637         // * the manual way\r
2638         // *************************************************************\r
2639         private void removeEncryption(String id, String plainText, boolean permanent, String slot) {\r
2640                 if (!permanent) {\r
2641                         plainText = " <table class=\"en-crypt-temp\" slot=\""\r
2642                                         +slot \r
2643                                         +"\""\r
2644                                         +"border=1 width=100%><tbody><tr><td>"\r
2645                                         +plainText+"</td></tr></tbody></table>";\r
2646                 }\r
2647                 \r
2648                 String html = browser.page().mainFrame().toHtml();\r
2649                 String text = html;\r
2650                 int imagePos = html.indexOf("<img");\r
2651                 int endPos;\r
2652                 for ( ;imagePos>0; ) {\r
2653                         // Find the end tag\r
2654                         endPos = text.indexOf(">", imagePos);\r
2655                         String tag = text.substring(imagePos-1,endPos);\r
2656                         if (tag.indexOf("id=\""+id+"\"") > -1) {\r
2657                                         text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);  \r
2658                                         QTextCodec codec = QTextCodec.codecForName("UTF-8");\r
2659                                 QByteArray unicode =  codec.fromUnicode(text);\r
2660                                         browser.setContent(unicode);\r
2661                                         if (permanent)\r
2662                                                 contentChanged();\r
2663                         }\r
2664                         imagePos = text.indexOf("<img", imagePos+1);\r
2665                 }\r
2666         }\r
2667         \r
2668         \r
2669         //****************************************************************\r
2670         //* Focus shortcuts\r
2671         //****************************************************************\r
2672         @SuppressWarnings("unused")\r
2673         private void focusTitle() {\r
2674                 titleLabel.setFocus();\r
2675         }\r
2676         @SuppressWarnings("unused")\r
2677         private void focusTag() {\r
2678                 tagEdit.setFocus();\r
2679         }\r
2680         @SuppressWarnings("unused")\r
2681         private void focusNote() {\r
2682                 browser.setFocus();\r
2683         }\r
2684         @SuppressWarnings("unused")\r
2685         private void focusAuthor() {\r
2686                 authorLabel.setFocus();\r
2687         }\r
2688         @SuppressWarnings("unused")\r
2689         private void focusUrl() {\r
2690                 urlLabel.setFocus();\r
2691         }\r
2692         \r
2693 \r
2694         //*****************************************************************\r
2695         //* Set the document background color\r
2696         //*****************************************************************\r
2697         public void setBackgroundColor(String color) {\r
2698                 String js = "function changeBackground(color) {"\r
2699                         +"document.body.style.background = color;"\r
2700                         +"}" \r
2701                         +"changeBackground('" +color+"');";\r
2702                 browser.page().mainFrame().evaluateJavaScript(js);\r
2703                 contentChanged();\r
2704         }\r
2705         \r
2706         \r
2707         //****************************************************************\r
2708         //* MicroFocus changed\r
2709         //****************************************************************\r
2710         private void microFocusChanged() {\r
2711                 boldButton.setDown(false);\r
2712                 italicButton.setDown(false);\r
2713                 underlineButton.setDown(false);\r
2714                 browser.openAction.setEnabled(false);\r
2715                 browser.downloadAttachment.setEnabled(false);\r
2716                 browser.downloadImage.setEnabled(false);\r
2717                 browser.rotateImageLeft.setEnabled(false);\r
2718                 browser.rotateImageRight.setEnabled(false);\r
2719                 browser.insertTableAction.setEnabled(true);\r
2720                 browser.deleteTableColumnAction.setEnabled(false);\r
2721                 browser.insertTableRowAction.setEnabled(false);\r
2722                 browser.insertTableColumnAction.setEnabled(false);\r
2723                 browser.deleteTableRowAction.setEnabled(false);\r
2724                 browser.insertLinkAction.setText(tr("Insert Hyperlink"));\r
2725                 insertHyperlink = true;\r
2726                 currentHyperlink ="";\r
2727                 insideList = false;\r
2728                 insideTable = false;\r
2729                 insideEncryption = false;\r
2730                 forceTextPaste = false;\r
2731                 \r
2732                 String js = new String( "function getCursorPos() {"\r
2733                         +"var cursorPos;"\r
2734                         +"if (window.getSelection) {"\r
2735                         +"   var selObj = window.getSelection();"\r
2736                         +"   var selRange = selObj.getRangeAt(0);"\r
2737                         +"   var workingNode = window.getSelection().anchorNode.parentNode;"\r
2738                         +"   while(workingNode != null) { " \r
2739 //                      +"      window.jambi.printNode(workingNode.nodeName);"\r
2740                         +"      if (workingNode.nodeName=='TABLE') { if (workingNode.getAttribute('class').toLowerCase() == 'en-crypt-temp') window.jambi.insideEncryption(); }"\r
2741                         +"      if (workingNode.nodeName=='B') window.jambi.boldActive();"\r
2742                         +"      if (workingNode.nodeName=='I') window.jambi.italicActive();"\r
2743                         +"      if (workingNode.nodeName=='U') window.jambi.underlineActive();"\r
2744                         +"      if (workingNode.nodeName=='UL') window.jambi.setInsideList();"\r
2745                         +"      if (workingNode.nodeName=='OL') window.jambi.setInsideList();"\r
2746                         +"      if (workingNode.nodeName=='LI') window.jambi.setInsideList();"\r
2747                         +"      if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"\r
2748                         +"      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
2749                         +"      if (workingNode.nodeName=='SPAN') {"\r
2750                         +"         if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"\r
2751                         +"      }"\r
2752                         +"      workingNode = workingNode.parentNode;"\r
2753                         +"   }"\r
2754                         +"}"\r
2755                         +"} getCursorPos();");\r
2756                 browser.page().mainFrame().evaluateJavaScript(js);\r
2757         }\r
2758         \r
2759         public void printNode(String n) {\r
2760                 System.out.println("Node Vaule: " +n);\r
2761         }\r
2762         \r
2763         public void insideEncryption() {\r
2764                 insideEncryption = true;\r
2765                 forceTextPaste();\r
2766         }\r
2767         \r
2768         //****************************************************************\r
2769         //* Insert a table row\r
2770         //****************************************************************\r
2771         public void insertTableRow() {\r
2772                 \r
2773                 String js = new String( "function insertTableRow() {"\r
2774                         +"   var selObj = window.getSelection();"\r
2775                         +"   var selRange = selObj.getRangeAt(0);"\r
2776                         +"   var workingNode = window.getSelection().anchorNode.parentNode;"\r
2777                         +"   var cellCount = 0;"\r
2778                         +"   while(workingNode != null) { " \r
2779                         +"      if (workingNode.nodeName.toLowerCase()=='tr') {"\r
2780                         +"           row = document.createElement('TR');"\r
2781                         +"           var nodes = workingNode.getElementsByTagName('td');"\r
2782                         +"           for (j=0; j<nodes.length; j=j+1) {"\r
2783                         +"              cell = document.createElement('TD');"\r
2784                         +"              cell.innerHTML='&nbsp;';"\r
2785                         +"              row.appendChild(cell);"\r
2786                         +"           }"                 \r
2787                         +"           workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"\r
2788                         +"           return;"\r
2789                         +"      }"\r
2790                         +"      workingNode = workingNode.parentNode;"\r
2791                         +"   }"\r
2792                         +"} insertTableRow();");\r
2793                 browser.page().mainFrame().evaluateJavaScript(js);\r
2794                 contentChanged();\r
2795         }\r
2796         \r
2797         public void insertTableColumn() {\r
2798                 String js = new String( "function insertTableColumn() {"\r
2799                                 +"   var selObj = window.getSelection();"\r
2800                                 +"   var selRange = selObj.getRangeAt(0);"\r
2801                                 +"   var workingNode = window.getSelection().anchorNode.parentNode;"\r
2802                                 +"   var current = 0;"\r
2803                                 +"   while (workingNode.nodeName.toLowerCase() != 'table' && workingNode != null) {"\r
2804                                 +"       if (workingNode.nodeName.toLowerCase() == 'td') {"\r
2805                                 +"          var td = workingNode;"\r
2806                                 +"          while (td.previousSibling != null) { " \r
2807                                 +"             current = current+1; td = td.previousSibling;"\r
2808                                 +"          }"\r
2809                                 +"       }"\r
2810                                 +"       workingNode = workingNode.parentNode; "\r
2811                                 +"   }"\r
2812                                 +"   if (workingNode == null) return;"\r
2813                                 +"   for (var i=0; i<workingNode.rows.length; i++) { " \r
2814                                 +"      var cell = workingNode.rows[i].insertCell(current+1); "                 \r
2815                                 +"      cell.innerHTML = '&nbsp'; "\r
2816                                 +"   }"\r
2817                                 +"} insertTableColumn();");\r
2818                         browser.page().mainFrame().evaluateJavaScript(js);\r
2819                         contentChanged();\r
2820         }\r
2821         \r
2822         //****************************************************************\r
2823         //* Delete a table row\r
2824         //****************************************************************\r
2825         public void deleteTableRow() {\r
2826                 \r
2827                 String js = new String( "function deleteTableRow() {"\r
2828                         +"   var selObj = window.getSelection();"\r
2829                         +"   var selRange = selObj.getRangeAt(0);"\r
2830                         +"   var workingNode = window.getSelection().anchorNode.parentNode;"\r
2831                         +"   var cellCount = 0;"\r
2832                         +"   while(workingNode != null) { " \r
2833                         +"      if (workingNode.nodeName.toLowerCase()=='tr') {"\r
2834                         +"           workingNode.parentNode.removeChild(workingNode);"\r
2835                         +"           return;"\r
2836                         +"      }"\r
2837                         +"      workingNode = workingNode.parentNode;"\r
2838                         +"   }"\r
2839                         +"} deleteTableRow();");\r
2840                 browser.page().mainFrame().evaluateJavaScript(js);\r
2841                 contentChanged();\r
2842         }\r
2843 \r
2844         public void deleteTableColumn() {\r
2845                 String js = new String( "function deleteTableColumn() {"\r
2846                                 +"   var selObj = window.getSelection();"\r
2847                                 +"   var selRange = selObj.getRangeAt(0);"\r
2848                                 +"   var workingNode = window.getSelection().anchorNode.parentNode;"\r
2849                                 +"   var current = 0;"\r
2850                                 +"   while (workingNode.nodeName.toLowerCase() != 'table' && workingNode != null) {"\r
2851                                 +"       if (workingNode.nodeName.toLowerCase() == 'td') {"\r
2852                                 +"          var td = workingNode;"\r
2853                                 +"          while (td.previousSibling != null) { " \r
2854                                 +"             current = current+1; td = td.previousSibling;"\r
2855                                 +"          }"\r
2856                                 +"       }"\r
2857                                 +"       workingNode = workingNode.parentNode; "\r
2858                                 +"   }"\r
2859                                 +"   if (workingNode == null) return;"\r
2860                                 +"   for (var i=0; i<workingNode.rows.length; i++) { " \r
2861                                 +"      workingNode.rows[i].deleteCell(current); "                      \r
2862                                 +"   }"\r
2863                                 +"} deleteTableColumn();");\r
2864                         browser.page().mainFrame().evaluateJavaScript(js);\r
2865                         contentChanged();\r
2866         }\r
2867         \r
2868         \r
2869         public void setInsideTable() {\r
2870                 browser.insertTableRowAction.setEnabled(true);\r
2871                 browser.insertTableColumnAction.setEnabled(true);\r
2872                 browser.deleteTableRowAction.setEnabled(true);\r
2873                 browser.deleteTableColumnAction.setEnabled(true);\r
2874                 browser.insertTableAction.setEnabled(false);\r
2875                 browser.encryptAction.setEnabled(false);\r
2876                 insideTable = true;\r
2877         }\r
2878         \r
2879         public void setInsideLink(String link) {\r
2880                 browser.insertLinkAction.setText(tr("Edit Hyperlink"));\r
2881                 currentHyperlink = link;\r
2882                 insertHyperlink = false;\r
2883         }\r
2884         \r
2885         public void italicActive() {\r
2886                 italicButton.setDown(true);\r
2887         }\r
2888         public void boldActive() {\r
2889                 boldButton.setDown(true);\r
2890         }\r
2891         public void underlineActive() {\r
2892                 underlineButton.setDown(true);\r
2893         }\r
2894         public void forceTextPaste() {\r
2895                 forceTextPaste = true;\r
2896         }\r
2897         public void imageContextMenu(String f) {\r
2898                 browser.downloadImage.setEnabled(true);\r
2899                 browser.rotateImageRight.setEnabled(true);\r
2900                 browser.rotateImageLeft.setEnabled(true);\r
2901                 browser.openAction.setEnabled(true);\r
2902                 selectedFile = f;\r
2903         }\r
2904         public void rotateImageRight() {\r
2905                 QWebSettings.setMaximumPagesInCache(0);\r
2906                 QWebSettings.setObjectCacheCapacities(0, 0, 0);\r
2907                 QImage image = new QImage(selectedFile);\r
2908                 QMatrix matrix = new QMatrix();\r
2909                 matrix.rotate( 90.0 );\r
2910                 image = image.transformed(matrix);\r
2911                 image.save(selectedFile);\r
2912                 QWebSettings.setMaximumPagesInCache(0);\r
2913                 QWebSettings.setObjectCacheCapacities(0, 0, 0);\r
2914                 browser.setHtml(browser.page().mainFrame().toHtml());\r
2915                 browser.reload();\r
2916                 contentChanged();\r
2917                 resourceSignal.contentChanged.emit(selectedFile);\r
2918 \r
2919         }\r
2920         public void rotateImageLeft() {\r
2921                 QImage image = new QImage(selectedFile);\r
2922                 QMatrix matrix = new QMatrix();\r
2923                 matrix.rotate( -90.0 );\r
2924                 image = image.transformed(matrix);\r
2925                 image.save(selectedFile);\r
2926                 browser.setHtml(browser.page().mainFrame().toHtml());\r
2927                 browser.reload();\r
2928                 contentChanged();\r
2929                 resourceSignal.contentChanged.emit(selectedFile);\r
2930         }\r
2931         public void resourceContextMenu(String f) {\r
2932                 browser.downloadAttachment.setEnabled(true);\r
2933                 browser.openAction.setEnabled(true);\r
2934                 selectedFile = f;\r
2935         }\r
2936         public void latexContextMenu(String f) {\r
2937                 browser.downloadImage.setEnabled(true);\r
2938                 browser.rotateImageRight.setEnabled(true);\r
2939                 browser.rotateImageLeft.setEnabled(true);\r
2940                 browser.openAction.setEnabled(true);\r
2941                 selectedFile = f;\r
2942         }\r
2943 \r
2944         //****************************************************************\r
2945         //* Apply CSS style to specified word\r
2946         //****************************************************************\r
2947 /*      public void applyStyleToWords(String word, String style) {\r
2948                 QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");\r
2949                 script.open(OpenModeFlag.ReadOnly);\r
2950                 String s = script.readAll().toString();\r
2951                 String js = new String(s +" findit('"+word+"', '"+style+"');");\r
2952                 browser.page().mainFrame().evaluateJavaScript(js);\r
2953                 System.out.println(getContent());\r
2954         }\r
2955 */      \r
2956         //****************************************************************\r
2957         //* Someone tried to paste a resource between notes, so we need  *\r
2958         //* to do some special handling.                                 *\r
2959         //****************************************************************\r
2960         private String fixInternotePaste(String text) {\r
2961                 logger.log(logger.EXTREME, "Fixing internote paste");\r
2962                 String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");\r
2963                 return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");\r
2964         }\r
2965         private String fixInternotePasteSearch(String text, String type, String locTag) {\r
2966                 \r
2967                 // First, let's fix the images.\r
2968                 int startPos = text.indexOf(type);\r
2969                 int endPos;\r
2970                 for (; startPos>=0;) {\r
2971                         endPos = text.indexOf(">", startPos+1);\r
2972                         String segment = text.substring(startPos, endPos);\r
2973                         if (segment.indexOf("en-tag") > -1) {\r
2974                                 String newSegment = segment;\r
2975                                 \r
2976                                 int guidStartPos = segment.indexOf("guid=\"");\r
2977                                 int guidEndPos = segment.indexOf("\"", guidStartPos+7);\r
2978                                 String guid = segment.substring(guidStartPos+6,guidEndPos);\r
2979                                 \r
2980                                 int mimeStartPos = segment.indexOf("type");\r
2981                                 int mimeEndPos = segment.indexOf("\"", mimeStartPos+7);\r
2982                                 String mime = segment.substring(mimeStartPos+6,mimeEndPos);\r
2983 \r
2984                                 int srcStartPos = segment.indexOf("src");\r
2985                                 int srcEndPos = segment.indexOf("\"", srcStartPos+6);\r
2986                                 String src = segment.substring(srcStartPos+5,srcEndPos);\r
2987                                 \r
2988                                 Calendar currentTime = new GregorianCalendar();\r
2989                                 Long l = new Long(currentTime.getTimeInMillis());\r
2990                                 long prevTime = l;\r
2991                                 while (l==prevTime) {\r
2992                                         currentTime = new GregorianCalendar();\r
2993                                         l= new Long(currentTime.getTimeInMillis());\r
2994                                 }\r
2995                                 \r
2996                                 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);\r
2997                                 // if r==null, then the image doesn't exist (it was probably cut out of another note, so \r
2998                                 // we need to recereate it\r
2999                                 if (r==null) {\r
3000                                         r = createResource(src, 1, mime, false);\r
3001                                         if (r==null)\r
3002                                                 return "";\r
3003                                 }\r
3004                         String randint = new String(Long.toString(l));\r
3005                         String extension = null;\r
3006                         if (r.getMime()!= null) {\r
3007                                 extension = r.getMime().toLowerCase();\r
3008                                 if (extension.indexOf("/")>-1)\r
3009                                         extension = extension.substring(extension.indexOf("/")+1);\r
3010                         }\r
3011                         String newFile = randint;\r
3012                         if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")\r
3013                                 if (!locTag.startsWith("src"))\r
3014                                         newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();\r
3015                         r.setNoteGuid(currentNote.getGuid());\r
3016                         \r
3017                         r.setGuid(randint);\r
3018                         conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);\r
3019                                 QFile f = new QFile(Global.getFileManager().getResDirPath(newFile));\r
3020                                 QByteArray bin = new QByteArray(r.getData().getBody());\r
3021                                 f.open(QFile.OpenModeFlag.WriteOnly);\r
3022                                 f.write(bin);\r
3023                                 f.close();\r
3024                                 newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);\r
3025                                 currentNote.getResources().add(r);\r
3026                                 \r
3027                                 int startSrcPos = newSegment.indexOf(locTag);\r
3028                                 int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);\r
3029                                 String source; \r
3030                                 if (locTag.startsWith("src")) {\r
3031                                          source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);\r
3032                                                 newSegment = newSegment.replace(source,\r
3033                                                         FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath(newFile)));\r
3034                                 } else {\r
3035                                         source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);\r
3036                                         newSegment = newSegment.replace(source, newFile);\r
3037                                 }\r
3038                                 \r
3039                                 text = text.substring(0,startPos) + newSegment + text.substring(endPos);\r
3040                         }\r
3041                         startPos = text.indexOf(type, startPos+1);\r
3042                 }\r
3043                 return text;\r
3044         }\r
3045 \r
3046 \r
3047         public void nextPage(String file) {\r
3048                 logger.log(logger.EXTREME, "Starting nextPage()");\r
3049                 \r
3050                 Integer pageNumber;\r
3051                 if (previewPageList.containsKey(file))\r
3052                         pageNumber = previewPageList.get(file)+1;\r
3053                 else\r
3054                         pageNumber = 2;\r
3055                 previewPageList.remove(file);\r
3056                 previewPageList.put(file, pageNumber);\r
3057                 PDFPreview pdfPreview = new PDFPreview();\r
3058                 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);\r
3059                 if (goodPreview) {\r
3060 \r
3061 //                      String html = getContent();\r
3062                         QWebSettings.setMaximumPagesInCache(0);\r
3063                         QWebSettings.setObjectCacheCapacities(0, 0, 0);\r
3064 //                      browser.setContent(new QByteArray());\r
3065                         browser.setHtml(browser.page().mainFrame().toHtml());\r
3066                         browser.reload();\r
3067 //                      browser.setContent(new QByteArray(html));\r
3068 //                      browser.triggerPageAction(WebAction.Reload);\r
3069 //                      pdfMouseOver(selectedFile);\r
3070                 }\r
3071         }\r
3072 \r
3073         public void previousPage(String file) {\r
3074                 logger.log(logger.EXTREME, "Starting previousPage()");\r
3075                 \r
3076                 Integer pageNumber;\r
3077                 if (previewPageList.containsKey(file))\r
3078                         pageNumber = previewPageList.get(file)-1;\r
3079                 else\r
3080                         pageNumber = 1;\r
3081                 previewPageList.remove(file);\r
3082                 previewPageList.put(file, pageNumber);\r
3083                 PDFPreview pdfPreview = new PDFPreview();\r
3084                 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);\r
3085                 if (goodPreview) {\r
3086 \r
3087 //                      String html = getContent();\r
3088                         QWebSettings.setMaximumPagesInCache(0);\r
3089                         QWebSettings.setObjectCacheCapacities(0, 0, 0);\r
3090                         browser.setHtml(browser.page().mainFrame().toHtml());\r
3091                         browser.reload();\r
3092 //                      browser.setContent(new QByteArray(html));\r
3093 //                      browser.triggerPageAction(WebAction.Reload);\r
3094                 }\r
3095         }\r
3096         \r
3097 /*      public void pdfMouseOver(String name) { \r
3098                 int pageNumber;\r
3099                 if (previewPageList.containsKey(selectedFile))\r
3100                         pageNumber = previewPageList.get(selectedFile)+1;\r
3101                 else\r
3102                         pageNumber = 1;\r
3103                 \r
3104                 if (pageNumber <= 1)\r
3105                         browser.previousPageAction.setEnabled(false);\r
3106                 else\r
3107                         browser.previousPageAction.setEnabled(true);\r
3108                 \r
3109                 PDFPreview pdf = new PDFPreview();\r
3110                 int totalPages = pdf.getPageCount(name);\r
3111                 if (previewPageList.containsKey(selectedFile))\r
3112                         pageNumber = previewPageList.get(selectedFile)+1;\r
3113                 else\r
3114                         pageNumber = 1;\r
3115                 if (totalPages > pageNumber)\r
3116                         browser.nextPageAction.setEnabled(true);\r
3117                 else\r
3118                         browser.nextPageAction.setEnabled(false);\r
3119         }\r
3120         \r
3121 \r
3122         public void pdfMouseOut() { \r
3123 //              browser.nextPageAction.setVisible(false);\r
3124 //              browser.previousPageAction.setVisible(false);\r
3125         }\r
3126 */\r
3127         \r
3128         @SuppressWarnings("unused")\r
3129         private void toggleUndoVisible(Boolean toggle) {\r
3130                 undoAction.setVisible(toggle);\r
3131                 Global.saveEditorButtonsVisible("undo", toggle);\r
3132         }\r
3133         @SuppressWarnings("unused")\r
3134         private void toggleRedoVisible(Boolean toggle) {\r
3135                 redoAction.setVisible(toggle);\r
3136                 Global.saveEditorButtonsVisible("redo", toggle);\r
3137         }\r
3138         @SuppressWarnings("unused")\r
3139         private void toggleCutVisible(Boolean toggle) {\r
3140                 cutAction.setVisible(toggle);\r
3141                 Global.saveEditorButtonsVisible("cut", toggle);\r
3142         }\r
3143         @SuppressWarnings("unused")\r
3144         private void toggleCopyVisible(Boolean toggle) {\r
3145                 copyAction.setVisible(toggle);\r
3146                 Global.saveEditorButtonsVisible("copy", toggle);\r
3147         }\r
3148         @SuppressWarnings("unused")\r
3149         private void togglePasteVisible(Boolean toggle) {\r
3150                 pasteAction.setVisible(toggle);\r
3151                 Global.saveEditorButtonsVisible("paste", toggle);\r
3152         }\r
3153         @SuppressWarnings("unused")\r
3154         private void toggleBoldVisible(Boolean toggle) {\r
3155                 boldAction.setVisible(toggle);\r
3156                 Global.saveEditorButtonsVisible("bold", toggle);\r
3157         }\r
3158         @SuppressWarnings("unused")\r
3159         private void toggleItalicVisible(Boolean toggle) {\r
3160                 italicAction.setVisible(toggle);\r
3161                 Global.saveEditorButtonsVisible("italic", toggle);\r
3162         }\r
3163         @SuppressWarnings("unused")\r
3164         private void toggleUnderlineVisible(Boolean toggle) {\r
3165                 underlineAction.setVisible(toggle);\r
3166                 Global.saveEditorButtonsVisible("underline", toggle);\r
3167         }\r
3168         @SuppressWarnings("unused")\r
3169         private void toggleStrikethroughVisible(Boolean toggle) {\r
3170                 strikethroughAction.setVisible(toggle);\r
3171                 Global.saveEditorButtonsVisible("strikethrough", toggle);\r
3172         }\r
3173         @SuppressWarnings("unused")\r
3174         private void toggleLeftAlignVisible(Boolean toggle) {\r
3175                 leftAlignAction.setVisible(toggle);\r
3176                 Global.saveEditorButtonsVisible("alignLeft", toggle);\r
3177         }\r
3178         @SuppressWarnings("unused")\r
3179         private void toggleRightAlignVisible(Boolean toggle) {\r
3180                 rightAlignAction.setVisible(toggle);\r
3181                 Global.saveEditorButtonsVisible("alignRight", toggle);\r
3182         }       \r
3183         @SuppressWarnings("unused")\r
3184         private void toggleCenterAlignVisible(Boolean toggle) {\r
3185                 centerAlignAction.setVisible(toggle);\r
3186                 Global.saveEditorButtonsVisible("alignCenter", toggle);\r
3187         }\r
3188         @SuppressWarnings("unused")\r
3189         private void toggleHLineVisible(Boolean toggle) {\r
3190                 hlineAction.setVisible(toggle);\r
3191                 Global.saveEditorButtonsVisible("hline", toggle);\r
3192         }\r
3193         @SuppressWarnings("unused")\r
3194         private void toggleIndentVisible(Boolean toggle) {\r
3195                 indentAction.setVisible(toggle);\r
3196                 Global.saveEditorButtonsVisible("indent", toggle);\r
3197         }\r
3198         @SuppressWarnings("unused")\r
3199         private void toggleTodoVisible(Boolean toggle) {\r
3200                 todoAction.setVisible(toggle);\r
3201                 Global.saveEditorButtonsVisible("todo", toggle);\r
3202         }\r
3203         @SuppressWarnings("unused")\r
3204         private void toggleOutdentVisible(Boolean toggle) {\r
3205                 outdentAction.setVisible(toggle);\r
3206                 Global.saveEditorButtonsVisible("outdent", toggle);\r
3207         }\r
3208         @SuppressWarnings("unused")\r
3209         private void toggleBulletListVisible(Boolean toggle) {\r
3210                 bulletListAction.setVisible(toggle);\r
3211                 Global.saveEditorButtonsVisible("bulletList", toggle);\r
3212         }\r
3213         @SuppressWarnings("unused")\r
3214         private void toggleNumberListVisible(Boolean toggle) {\r
3215                 numberListAction.setVisible(toggle);\r
3216                 Global.saveEditorButtonsVisible("numberList", toggle);\r
3217         }\r
3218         @SuppressWarnings("unused")\r
3219         private void toggleFontListVisible(Boolean toggle) {\r
3220                 fontListAction.setVisible(toggle);\r
3221                 Global.saveEditorButtonsVisible("font", toggle);\r
3222         }\r
3223         @SuppressWarnings("unused")\r
3224         private void toggleFontColorVisible(Boolean toggle) {\r
3225                 fontColorAction.setVisible(toggle);\r
3226                 Global.saveEditorButtonsVisible("fontColor", toggle);\r
3227         }\r
3228         @SuppressWarnings("unused")\r
3229         private void toggleFontSizeVisible(Boolean toggle) {\r
3230                 fontSizeAction.setVisible(toggle);\r
3231                 Global.saveEditorButtonsVisible("fontSize", toggle);\r
3232         }\r
3233         @SuppressWarnings("unused")\r
3234         private void toggleFontHilightVisible(Boolean toggle) {\r
3235                 fontHilightAction.setVisible(toggle);\r
3236                 Global.saveEditorButtonsVisible("fontHilight", toggle);\r
3237         }\r
3238         @SuppressWarnings("unused")\r
3239         private void toggleSpellCheckVisible(Boolean toggle) {\r
3240                 spellCheckAction.setVisible(toggle);\r
3241                 Global.saveEditorButtonsVisible("spellCheck", toggle);\r
3242         }\r
3243 \r
3244 \r
3245         private void setupDictionary() {\r
3246                 File wordList = new File(Global.getFileManager().getSpellDirPath()+Locale.getDefault()+".dic");\r
3247                 try {\r
3248                         dictionary = new SpellDictionaryHashMap(wordList);\r
3249                         spellChecker = new SpellChecker(dictionary);\r
3250                         \r
3251                         File userWordList;\r
3252                         userWordList = new File(Global.getFileManager().getSpellDirPathUser()+"user.dic");\r
3253                         \r
3254                         // Get the local user spell dictionary\r
3255                         try {\r
3256                                 userDictionary = new SpellDictionaryHashMap(userWordList);\r
3257                         } catch (FileNotFoundException e) {\r
3258                                 userWordList.createNewFile();\r
3259                                 userDictionary = new SpellDictionaryHashMap(userWordList);\r
3260                         } catch (IOException e) {\r
3261                                 userWordList.createNewFile();\r
3262                                 userDictionary = new SpellDictionaryHashMap(userWordList);\r
3263                         }\r
3264                         \r
3265                         spellListener = new SuggestionListener(this, spellChecker);\r
3266                         \r
3267                         // Add the user dictionary\r
3268                         spellChecker.addSpellCheckListener(spellListener);\r
3269                         spellChecker.setUserDictionary(userDictionary);\r
3270 \r
3271                 } catch (FileNotFoundException e) {\r
3272                         QMessageBox.critical(this, tr("Spell Check Error"), \r
3273                                         tr("Dictionary ")+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+\r
3274                                                 tr(".dic was not found."));\r
3275                 } catch (IOException e) {\r
3276                         QMessageBox.critical(this, tr("Spell Check Error"), \r
3277                                         tr("Dictionary ")+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+\r
3278                                                 tr(".dic is invalid."));\r
3279                 }\r
3280 \r
3281         }\r
3282         \r
3283         // Invoke spell checker dialog\r
3284         @SuppressWarnings("unused")\r
3285         private void spellCheckClicked() {\r
3286 \r
3287                 if (spellChecker == null) {\r
3288                         setupDictionary();      \r
3289                 }\r
3290                 \r
3291                 // Read user settings\r
3292                 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREDIGITWORDS, \r
3293                                 Global.getSpellSetting(Configuration.SPELL_IGNOREDIGITWORDS));\r
3294                 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREINTERNETADDRESSES, \r
3295                                 Global.getSpellSetting(Configuration.SPELL_IGNOREINTERNETADDRESSES));\r
3296                 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREMIXEDCASE, \r
3297                                 Global.getSpellSetting(Configuration.SPELL_IGNOREMIXEDCASE));\r
3298                 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREUPPERCASE, \r
3299                                 Global.getSpellSetting(Configuration.SPELL_IGNOREUPPERCASE));\r
3300                 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNORESENTENCECAPITALIZATION, \r
3301                                 Global.getSpellSetting(Configuration.SPELL_IGNORESENTENCECAPITALIZATION));\r
3302 \r
3303                 spellListener.abortSpellCheck = false;\r
3304                 spellListener.errorsFound = false;\r
3305                 String content = getBrowser().page().mainFrame().toPlainText();\r
3306                 StringWordTokenizer tokenizer = new StringWordTokenizer(content);\r
3307                 if (!tokenizer.hasMoreWords())\r
3308                         return;\r
3309                 getBrowser().page().action(WebAction.MoveToStartOfDocument);\r
3310 \r
3311                 getBrowser().setFocus();\r
3312                 boolean found;\r
3313                         \r
3314                 // Move to the start of page\r
3315                 KeyboardModifiers ctrl = new KeyboardModifiers(KeyboardModifier.ControlModifier.value());\r
3316                 QKeyEvent home = new QKeyEvent(Type.KeyPress, Key.Key_Home.value(), ctrl);  \r
3317                 browser.keyPressEvent(home);\r
3318                 getBrowser().setFocus();\r
3319                         \r
3320                 tokenizer = new StringWordTokenizer(content);\r
3321                 String word;\r
3322                         \r
3323                 while(tokenizer.hasMoreWords()) {\r
3324                         word = tokenizer.nextWord();\r
3325                         found = getBrowser().page().findText(word);\r
3326                         if (found && !spellListener.abortSpellCheck) {\r
3327                                 spellChecker.checkSpelling(new StringWordTokenizer(word));\r
3328                                 getBrowser().setFocus();\r
3329                         }\r
3330                 }\r
3331 \r
3332                 // Go to the end of the document & finish up.\r
3333                 home = new QKeyEvent(Type.KeyPress, Key.Key_End.value(), ctrl);  \r
3334                 browser.keyPressEvent(home);\r
3335                 if (!spellListener.errorsFound)\r
3336                         QMessageBox.information(this, tr("Spell Check Complete"), \r
3337                                         tr("No Errors Found"));\r
3338 \r
3339     }\r
3340 \r
3341 }\r