OSDN Git Service

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