OSDN Git Service

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