OSDN Git Service

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