OSDN Git Service

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