2 * This file is part of NeverNote
\r
3 * Copyright 2009 Randy Baumgarte
\r
5 * This file may be licensed under the terms of of the
\r
6 * GNU General Public License Version 2 (the ``GPL'').
\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
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
20 package cx.fbn.nevernote.gui;
\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
40 import org.apache.commons.lang.StringUtils;
\r
42 import com.evernote.edam.limits.Constants;
\r
43 import com.evernote.edam.type.Data;
\r
44 import com.evernote.edam.type.Note;
\r
45 import com.evernote.edam.type.Notebook;
\r
46 import com.evernote.edam.type.Resource;
\r
47 import com.evernote.edam.type.ResourceAttributes;
\r
48 import com.evernote.edam.type.Tag;
\r
49 import com.swabunga.spell.engine.Configuration;
\r
50 import com.swabunga.spell.engine.SpellDictionary;
\r
51 import com.swabunga.spell.engine.SpellDictionaryHashMap;
\r
52 import com.swabunga.spell.engine.Word;
\r
53 import com.swabunga.spell.event.SpellCheckEvent;
\r
54 import com.swabunga.spell.event.SpellCheckListener;
\r
55 import com.swabunga.spell.event.SpellChecker;
\r
56 import com.swabunga.spell.event.StringWordTokenizer;
\r
57 import com.trolltech.qt.core.QByteArray;
\r
58 import com.trolltech.qt.core.QCoreApplication;
\r
59 import com.trolltech.qt.core.QDataStream;
\r
60 import com.trolltech.qt.core.QDateTime;
\r
61 import com.trolltech.qt.core.QEvent;
\r
62 import com.trolltech.qt.core.QEvent.Type;
\r
63 import com.trolltech.qt.core.QFile;
\r
64 import com.trolltech.qt.core.QFileSystemWatcher;
\r
65 import com.trolltech.qt.core.QIODevice;
\r
66 import com.trolltech.qt.core.QMimeData;
\r
67 import com.trolltech.qt.core.QTextCodec;
\r
68 import com.trolltech.qt.core.QUrl;
\r
69 import com.trolltech.qt.core.Qt;
\r
70 import com.trolltech.qt.core.Qt.Key;
\r
71 import com.trolltech.qt.core.Qt.KeyboardModifier;
\r
72 import com.trolltech.qt.core.Qt.KeyboardModifiers;
\r
73 import com.trolltech.qt.gui.QAction;
\r
74 import com.trolltech.qt.gui.QApplication;
\r
75 import com.trolltech.qt.gui.QCalendarWidget;
\r
76 import com.trolltech.qt.gui.QClipboard;
\r
77 import com.trolltech.qt.gui.QClipboard.Mode;
\r
78 import com.trolltech.qt.gui.QColor;
\r
79 import com.trolltech.qt.gui.QComboBox;
\r
80 import com.trolltech.qt.gui.QDateEdit;
\r
81 import com.trolltech.qt.gui.QDesktopServices;
\r
82 import com.trolltech.qt.gui.QFileDialog;
\r
83 import com.trolltech.qt.gui.QFileDialog.AcceptMode;
\r
84 import com.trolltech.qt.gui.QFileDialog.FileMode;
\r
85 import com.trolltech.qt.gui.QFontDatabase;
\r
86 import com.trolltech.qt.gui.QFormLayout;
\r
87 import com.trolltech.qt.gui.QGridLayout;
\r
88 import com.trolltech.qt.gui.QHBoxLayout;
\r
89 import com.trolltech.qt.gui.QIcon;
\r
90 import com.trolltech.qt.gui.QImage;
\r
91 import com.trolltech.qt.gui.QKeyEvent;
\r
92 import com.trolltech.qt.gui.QKeySequence;
\r
93 import com.trolltech.qt.gui.QLabel;
\r
94 import com.trolltech.qt.gui.QLineEdit;
\r
95 import com.trolltech.qt.gui.QListWidgetItem;
\r
96 import com.trolltech.qt.gui.QMatrix;
\r
97 import com.trolltech.qt.gui.QMessageBox;
\r
98 import com.trolltech.qt.gui.QPalette;
\r
99 import com.trolltech.qt.gui.QPalette.ColorRole;
\r
100 import com.trolltech.qt.gui.QPushButton;
\r
101 import com.trolltech.qt.gui.QShortcut;
\r
102 import com.trolltech.qt.gui.QTimeEdit;
\r
103 import com.trolltech.qt.gui.QToolButton;
\r
104 import com.trolltech.qt.gui.QToolButton.ToolButtonPopupMode;
\r
105 import com.trolltech.qt.gui.QVBoxLayout;
\r
106 import com.trolltech.qt.gui.QWidget;
\r
107 import com.trolltech.qt.network.QNetworkRequest;
\r
108 import com.trolltech.qt.webkit.QWebPage;
\r
109 import com.trolltech.qt.webkit.QWebPage.WebAction;
\r
110 import com.trolltech.qt.webkit.QWebSettings;
\r
111 import com.trolltech.qt.webkit.QWebView;
\r
113 import cx.fbn.nevernote.Global;
\r
114 import cx.fbn.nevernote.dialog.EnCryptDialog;
\r
115 import cx.fbn.nevernote.dialog.EnDecryptDialog;
\r
116 import cx.fbn.nevernote.dialog.GeoDialog;
\r
117 import cx.fbn.nevernote.dialog.InsertLinkDialog;
\r
118 import cx.fbn.nevernote.dialog.SpellCheck;
\r
119 import cx.fbn.nevernote.dialog.TableDialog;
\r
120 import cx.fbn.nevernote.dialog.TagAssign;
\r
121 import cx.fbn.nevernote.evernote.EnCrypt;
\r
122 import cx.fbn.nevernote.filters.FilterEditorTags;
\r
123 import cx.fbn.nevernote.signals.NoteResourceSignal;
\r
124 import cx.fbn.nevernote.signals.NoteSignal;
\r
125 import cx.fbn.nevernote.sql.DatabaseConnection;
\r
126 import cx.fbn.nevernote.utilities.ApplicationLogger;
\r
127 import cx.fbn.nevernote.utilities.FileUtils;
\r
128 import cx.fbn.nevernote.utilities.Pair;
\r
130 public class BrowserWindow extends QWidget {
\r
132 public final QLineEdit titleLabel;
\r
133 private final QLineEdit urlText;
\r
134 private final QLabel authorLabel;
\r
135 private final QLineEdit authorText;
\r
136 private final QComboBox geoBox;
\r
137 public final TagLineEdit tagEdit;
\r
138 public final QLabel tagLabel;
\r
139 private final QPushButton urlLabel;
\r
140 private final QLabel alteredLabel;
\r
141 private final QDateEdit alteredDate;
\r
142 private final QTimeEdit alteredTime;
\r
143 private final QDateEdit createdDate;
\r
144 private final QTimeEdit createdTime;
\r
145 private final QLabel subjectLabel;
\r
146 private final QDateEdit subjectDate;
\r
147 private final QTimeEdit subjectTime;
\r
148 public final QComboBox notebookBox;
\r
149 private final QLabel notebookLabel;
\r
150 private final QLabel createdLabel;
\r
151 public final QComboBox fontSize;
\r
152 public final QAction fontSizeAction;
\r
153 private boolean extendedOn;
\r
154 public boolean buttonsVisible;
\r
155 private final String iconPath = new String("classpath:cx/fbn/nevernote/icons/");
\r
156 private final ContentView browser;
\r
157 private List<Tag> allTags;
\r
158 private List<String> currentTags;
\r
159 public NoteSignal noteSignal;
\r
160 private List<Notebook> notebookList;
\r
161 private Note currentNote;
\r
162 private String saveNoteTitle;
\r
163 private String saveTagList;
\r
164 private boolean insideList;
\r
165 // private String selectedText;
\r
166 private final DatabaseConnection conn;
\r
167 private final QCalendarWidget createdCalendarWidget;
\r
168 private final QCalendarWidget alteredCalendarWidget;
\r
169 private final QCalendarWidget subjectCalendarWidget;
\r
171 public final QPushButton undoButton;
\r
172 public final QAction undoAction;
\r
173 public final QPushButton redoButton;
\r
174 public final QAction redoAction;
\r
175 public final QPushButton cutButton;
\r
176 public final QAction cutAction;
\r
177 public final QPushButton copyButton;
\r
178 public final QAction copyAction;
\r
179 public final QPushButton pasteButton;
\r
180 public final QAction pasteAction;
\r
181 public final QPushButton boldButton;
\r
182 public final QAction boldAction;
\r
183 public final QPushButton underlineButton;
\r
184 public final QAction underlineAction;
\r
185 public final QPushButton italicButton;
\r
186 public final QAction italicAction;
\r
187 public final Signal0 focusLost;
\r
188 public final NoteResourceSignal resourceSignal;
\r
190 public QPushButton rightAlignButton;
\r
191 public final QAction rightAlignAction;
\r
192 public QPushButton leftAlignButton;
\r
193 public final QAction leftAlignAction;
\r
194 public QPushButton centerAlignButton;
\r
195 public final QAction centerAlignAction;
\r
197 public final QPushButton strikethroughButton;
\r
198 public final QAction strikethroughAction;
\r
199 public final QPushButton hlineButton;
\r
200 public final QAction hlineAction;
\r
201 public final QPushButton indentButton;
\r
202 public final QAction indentAction;
\r
203 public final QPushButton outdentButton;
\r
204 public final QAction outdentAction;
\r
205 public final QPushButton bulletListButton;
\r
206 public final QAction bulletListAction;
\r
207 public final QPushButton numberListButton;
\r
208 public final QAction numberListAction;
\r
209 public final QPushButton spellCheckButton;
\r
210 public final QAction spellCheckAction;
\r
211 public final QPushButton todoButton;
\r
212 public final QAction todoAction;
\r
214 public final QShortcut focusTitleShortcut;
\r
215 public final QShortcut focusTagShortcut;
\r
216 public final QShortcut focusNoteShortcut;
\r
217 public final QShortcut focusUrlShortcut;
\r
218 public final QShortcut focusAuthorShortcut;
\r
220 public EditorButtonBar buttonLayout;
\r
221 public final QComboBox fontList;
\r
222 public final QAction fontListAction;
\r
223 public final QToolButton fontColor;
\r
224 public final QAction fontColorAction;
\r
225 private final ColorMenu fontColorMenu;
\r
226 public final QToolButton fontHilight;
\r
227 public final QAction fontHilightAction;
\r
228 private final ColorMenu fontHilightColorMenu;
\r
229 public final QFileSystemWatcher fileWatcher;
\r
230 public int cursorPosition;
\r
231 private boolean forceTextPaste = false;
\r
232 private String selectedFile;
\r
233 private String currentHyperlink;
\r
234 public boolean keepPDFNavigationHidden;
\r
235 private final ApplicationLogger logger;
\r
236 SpellDictionary dictionary;
\r
237 SpellDictionary userDictionary;
\r
238 SpellChecker spellChecker;
\r
239 SuggestionListener spellListener;
\r
240 private final HashMap<String,Integer> previewPageList;
\r
241 boolean insertHyperlink = true;
\r
242 boolean insideTable = false;
\r
243 boolean insideEncryption = false;
\r
246 public static class SuggestionListener implements SpellCheckListener {
\r
247 public boolean abortSpellCheck = false;
\r
248 public boolean errorsFound = false;
\r
249 private final SpellCheck spellCheckDialog;
\r
252 private final BrowserWindow parent;
\r
253 public SuggestionListener(BrowserWindow parent, SpellChecker checker) {
\r
254 this.parent = parent;
\r
255 spellCheckDialog = new SpellCheck(checker);
\r
257 public void spellingError(SpellCheckEvent event) {
\r
258 errorsFound = true;
\r
259 spellCheckDialog.setWord(event.getInvalidWord());
\r
261 @SuppressWarnings("unchecked")
\r
262 List<Word> suggestions = event.getSuggestions();
\r
263 spellCheckDialog.clearSuggestions();
\r
264 if (!suggestions.isEmpty()) {
\r
265 // spellCheckDialog.setCurrentSuggestion(suggestions.get(0).getWord());
\r
266 for (int i=0; i<suggestions.size(); i++) {
\r
267 spellCheckDialog.addSuggestion(suggestions.get(i).getWord());
\r
269 spellCheckDialog.setSelectedSuggestion(0);
\r
271 spellCheckDialog.exec();
\r
272 if (spellCheckDialog.cancelPressed()) {
\r
273 abortSpellCheck = true;
\r
277 if (spellCheckDialog.replacePressed()) {
\r
278 QClipboard clipboard = QApplication.clipboard();
\r
279 clipboard.setText(spellCheckDialog.getReplacementWord());
\r
280 parent.pasteClicked();
\r
288 public BrowserWindow(DatabaseConnection c) {
\r
289 logger = new ApplicationLogger("browser.log");
\r
290 logger.log(logger.HIGH, "Setting up browser");
\r
292 fileWatcher = new QFileSystemWatcher();
\r
293 // fileWatcher.fileChanged.connect(this, "fileChanged(String)");
\r
294 noteSignal = new NoteSignal();
\r
295 titleLabel = new QLineEdit();
\r
296 titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX);
\r
297 urlText = new QLineEdit();
\r
298 authorText = new QLineEdit();
\r
299 geoBox = new QComboBox();
\r
300 urlLabel = new QPushButton();
\r
301 urlLabel.clicked.connect(this, "sourceUrlClicked()");
\r
302 authorLabel = new QLabel();
\r
305 focusLost = new Signal0();
\r
307 tagEdit = new TagLineEdit(allTags);
\r
308 tagLabel = new QLabel("Tags:");
\r
309 tagEdit.focusLost.connect(this, "modifyTagsTyping()");
\r
311 createdCalendarWidget = new QCalendarWidget();
\r
312 createdDate = new QDateEdit();
\r
313 createdDate.setDisplayFormat(Global.getDateFormat());
\r
314 createdDate.setCalendarPopup(true);
\r
315 createdDate.setCalendarWidget(createdCalendarWidget);
\r
316 createdTime = new QTimeEdit();
\r
317 createdDate.dateChanged.connect(this, "createdChanged()");
\r
318 createdTime.timeChanged.connect(this, "createdChanged()");
\r
320 alteredCalendarWidget = new QCalendarWidget();
\r
321 alteredDate = new QDateEdit();
\r
322 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
323 alteredDate.setCalendarPopup(true);
\r
324 alteredDate.setCalendarWidget(alteredCalendarWidget);
\r
325 alteredTime = new QTimeEdit();
\r
326 alteredLabel = new QLabel("Altered:");
\r
327 alteredDate.dateChanged.connect(this, "alteredChanged()");
\r
328 alteredTime.timeChanged.connect(this, "alteredChanged()");
\r
330 subjectCalendarWidget = new QCalendarWidget();
\r
331 subjectDate = new QDateEdit();
\r
332 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
333 subjectDate.setCalendarPopup(true);
\r
334 subjectDate.setCalendarWidget(subjectCalendarWidget);
\r
335 subjectTime = new QTimeEdit();
\r
336 subjectLabel = new QLabel(tr("Subject Date:"));
\r
337 subjectDate.dateChanged.connect(this, "subjectDateTimeChanged()");
\r
338 subjectTime.timeChanged.connect(this, "subjectDateTimeChanged()");
\r
339 authorText.textChanged.connect(this, "authorChanged()");
\r
340 urlText.textChanged.connect(this, "sourceUrlChanged()");
\r
342 notebookBox = new QComboBox();
\r
343 notebookLabel = new QLabel(tr("Notebook"));
\r
344 createdLabel = new QLabel(tr("Created:"));
\r
345 // selectedText = new String();
\r
347 urlLabel.setVisible(false);
\r
348 urlText.setVisible(false);
\r
349 authorLabel.setVisible(false);
\r
351 geoBox.setVisible(false);
\r
352 geoBox.addItem(new QIcon(iconPath+"globe.png"), "");
\r
353 geoBox.addItem(new String(tr("Set")));
\r
354 geoBox.addItem(new String(tr("Clear")));
\r
355 geoBox.addItem(new String(tr("View On Map")));
\r
356 geoBox.activated.connect(this, "geoBoxChanged()");
\r
358 authorText.setVisible(false);
\r
359 createdDate.setVisible(false);
\r
360 alteredLabel.setVisible(false);
\r
361 //notebookBox.setVisible(false);
\r
362 notebookLabel.setVisible(false);
\r
363 createdLabel.setVisible(false);
\r
364 createdTime.setVisible(false);
\r
365 alteredDate.setVisible(false);
\r
366 alteredTime.setVisible(false);
\r
367 subjectLabel.setVisible(false);
\r
368 subjectDate.setVisible(false);
\r
369 subjectTime.setVisible(false);
\r
370 extendedOn = false;
\r
371 buttonsVisible = true;
\r
372 setAcceptDrops(true);
\r
374 browser = new ContentView(this);
\r
375 browser.page().setLinkDelegationPolicy(
\r
376 QWebPage.LinkDelegationPolicy.DelegateAllLinks);
\r
377 browser.linkClicked.connect(this, "linkClicked(QUrl)");
\r
378 currentHyperlink = "";
\r
380 QVBoxLayout v = new QVBoxLayout();
\r
381 QFormLayout notebookLayout = new QFormLayout();
\r
382 QGridLayout dateLayout = new QGridLayout();
\r
383 titleLabel.setReadOnly(false);
\r
384 titleLabel.editingFinished.connect(this, "titleEdited()");
\r
385 browser.page().contentsChanged.connect(this, "contentChanged()");
\r
386 browser.page().selectionChanged.connect(this, "selectionChanged()");
\r
387 browser.page().mainFrame().javaScriptWindowObjectCleared.connect(this,
\r
388 "exposeToJavascript()");
\r
390 notebookBox.activated.connect(this, "notebookChanged()");
\r
391 resourceSignal = new NoteResourceSignal();
\r
393 QHBoxLayout tagLayout = new QHBoxLayout();
\r
394 v.addWidget(titleLabel, 0);
\r
395 notebookLayout.addRow(notebookLabel, notebookBox);
\r
396 tagLayout.addLayout(notebookLayout, 0);
\r
397 tagLayout.stretch(4);
\r
398 tagLayout.addWidget(tagLabel, 0);
\r
399 tagLayout.addWidget(tagEdit, 1);
\r
400 v.addLayout(tagLayout);
\r
402 QHBoxLayout urlLayout = new QHBoxLayout();
\r
403 urlLayout.addWidget(urlLabel, 0);
\r
404 urlLayout.addWidget(urlText, 0);
\r
405 v.addLayout(urlLayout);
\r
407 QHBoxLayout authorLayout = new QHBoxLayout();
\r
408 authorLayout.addWidget(authorLabel, 0);
\r
409 authorLayout.addWidget(authorText, 0);
\r
410 authorLayout.addWidget(geoBox);
\r
411 v.addLayout(authorLayout);
\r
413 dateLayout.addWidget(createdLabel, 0, 0);
\r
414 dateLayout.addWidget(createdDate, 0, 1);
\r
415 dateLayout.addWidget(createdTime, 0, 2);
\r
416 dateLayout.setColumnStretch(9, 100);
\r
417 dateLayout.addWidget(alteredLabel, 0, 3);
\r
418 dateLayout.addWidget(alteredDate, 0, 4);
\r
419 dateLayout.addWidget(alteredTime, 0, 5);
\r
420 dateLayout.addWidget(subjectLabel, 0, 6);
\r
421 dateLayout.addWidget(subjectDate, 0, 7);
\r
422 dateLayout.addWidget(subjectTime, 0, 8);
\r
423 v.addLayout(dateLayout, 0);
\r
425 undoButton = newEditorButton("undo", tr("Undo Change"));
\r
426 redoButton = newEditorButton("redo", tr("Redo Change"));
\r
427 cutButton = newEditorButton("cut", tr("Cut"));
\r
428 copyButton = newEditorButton("copy", tr("Copy"));
\r
429 pasteButton = newEditorButton("paste", tr("Paste"));
\r
430 boldButton = newEditorButton("bold", tr("Bold"));
\r
431 underlineButton = newEditorButton("underline", tr("Underline"));
\r
432 italicButton = newEditorButton("italic", tr("Italic"));
\r
434 rightAlignButton = newEditorButton("justifyRight", tr("Right Align"));
\r
435 leftAlignButton = newEditorButton("justifyLeft", tr("Left Align"));
\r
436 centerAlignButton = newEditorButton("justifyCenter", tr("Center Align"));
\r
438 strikethroughButton = newEditorButton("strikethrough", tr("Strikethrough"));
\r
439 hlineButton = newEditorButton("hline", tr("Insert Horizontal Line"));
\r
440 indentButton = newEditorButton("indent", tr("Shift Right"));
\r
441 outdentButton = newEditorButton("outdent", tr("Shift Left"));
\r
442 bulletListButton = newEditorButton("bulletList", tr("Bullet List"));
\r
443 numberListButton = newEditorButton("numberList", tr("Number List"));
\r
444 spellCheckButton = newEditorButton("spellCheck", tr("Spell Check"));
\r
445 todoButton = newEditorButton("todo", tr("To-do"));
\r
448 buttonLayout = new EditorButtonBar();
\r
449 v.addWidget(buttonLayout);
\r
451 undoAction = buttonLayout.addWidget(undoButton);
\r
452 buttonLayout.toggleUndoVisible.triggered.connect(this, "toggleUndoVisible(Boolean)");
\r
453 redoAction = buttonLayout.addWidget(redoButton);
\r
454 buttonLayout.toggleRedoVisible.triggered.connect(this, "toggleRedoVisible(Boolean)");
\r
456 buttonLayout.addWidget(newSeparator());
\r
457 cutAction = buttonLayout.addWidget(cutButton);
\r
458 buttonLayout.toggleCutVisible.triggered.connect(this, "toggleCutVisible(Boolean)");
\r
459 copyAction = buttonLayout.addWidget(copyButton);
\r
460 buttonLayout.toggleCopyVisible.triggered.connect(this, "toggleCopyVisible(Boolean)");
\r
461 pasteAction = buttonLayout.addWidget(pasteButton);
\r
462 buttonLayout.togglePasteVisible.triggered.connect(this, "togglePasteVisible(Boolean)");
\r
464 buttonLayout.addWidget(newSeparator());
\r
465 boldAction = buttonLayout.addWidget(boldButton);
\r
466 buttonLayout.toggleBoldVisible.triggered.connect(this, "toggleBoldVisible(Boolean)");
\r
467 italicAction = buttonLayout.addWidget(italicButton);
\r
468 buttonLayout.toggleItalicVisible.triggered.connect(this, "toggleItalicVisible(Boolean)");
\r
469 underlineAction = buttonLayout.addWidget(underlineButton);
\r
470 buttonLayout.toggleUnderlineVisible.triggered.connect(this, "toggleUnderlineVisible(Boolean)");
\r
471 strikethroughAction = buttonLayout.addWidget(strikethroughButton);
\r
472 buttonLayout.toggleStrikethroughVisible.triggered.connect(this, "toggleStrikethroughVisible(Boolean)");
\r
475 buttonLayout.addWidget(newSeparator());
\r
476 leftAlignAction = buttonLayout.addWidget(leftAlignButton);
\r
477 buttonLayout.toggleLeftAlignVisible.triggered.connect(this, "toggleLeftAlignVisible(Boolean)");
\r
478 centerAlignAction = buttonLayout.addWidget(centerAlignButton);
\r
479 buttonLayout.toggleCenterAlignVisible.triggered.connect(this, "toggleCenterAlignVisible(Boolean)");
\r
480 rightAlignAction = buttonLayout.addWidget(rightAlignButton);
\r
481 buttonLayout.toggleRightAlignVisible.triggered.connect(this, "toggleRightAlignVisible(Boolean)");
\r
483 buttonLayout.addWidget(newSeparator());
\r
484 hlineAction = buttonLayout.addWidget(hlineButton);
\r
485 buttonLayout.toggleHLineVisible.triggered.connect(this, "toggleHLineVisible(Boolean)");
\r
487 indentAction = buttonLayout.addWidget(indentButton);
\r
488 buttonLayout.toggleIndentVisible.triggered.connect(this, "toggleIndentVisible(Boolean)");
\r
489 outdentAction = buttonLayout.addWidget(outdentButton);
\r
490 buttonLayout.toggleOutdentVisible.triggered.connect(this, "toggleOutdentVisible(Boolean)");
\r
491 bulletListAction = buttonLayout.addWidget(bulletListButton);
\r
492 buttonLayout.toggleBulletListVisible.triggered.connect(this, "toggleBulletListVisible(Boolean)");
\r
493 numberListAction = buttonLayout.addWidget(numberListButton);
\r
494 buttonLayout.toggleNumberListVisible.triggered.connect(this, "toggleNumberListVisible(Boolean)");
\r
496 // Setup the font & font size combo boxes
\r
497 buttonLayout.addWidget(newSeparator());
\r
498 fontList = new QComboBox();
\r
499 fontSize = new QComboBox();
\r
500 fontList.setToolTip("Font");
\r
501 fontSize.setToolTip("Font Size");
\r
502 fontList.activated.connect(this, "fontChanged(String)");
\r
503 fontSize.activated.connect(this, "fontSizeChanged(String)");
\r
504 fontListAction = buttonLayout.addWidget(fontList);
\r
505 buttonLayout.toggleFontVisible.triggered.connect(this, "toggleFontListVisible(Boolean)");
\r
506 fontSizeAction = buttonLayout.addWidget(fontSize);
\r
507 buttonLayout.toggleFontSizeVisible.triggered.connect(this, "toggleFontSizeVisible(Boolean)");
\r
508 QFontDatabase fonts = new QFontDatabase();
\r
509 List<String> fontFamilies = fonts.families();
\r
510 for (int i = 0; i < fontFamilies.size(); i++) {
\r
511 fontList.addItem(fontFamilies.get(i));
\r
513 loadFontSize(fontFamilies.get(i));
\r
517 // buttonLayout.addWidget(newSeparator(), 0);
\r
518 fontColor = newToolButton("fontColor", tr("Font Color"));
\r
519 fontColorMenu = new ColorMenu(this);
\r
520 fontColor.setMenu(fontColorMenu.getMenu());
\r
521 fontColor.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
522 fontColor.setAutoRaise(false);
\r
523 fontColorMenu.getMenu().triggered.connect(this, "fontColorClicked()");
\r
524 fontColorAction = buttonLayout.addWidget(fontColor);
\r
525 buttonLayout.toggleFontColorVisible.triggered.connect(this, "toggleFontColorVisible(Boolean)");
\r
526 fontHilight = newToolButton("fontHilight", tr("Font Hilight Color"));
\r
527 fontHilight.setPopupMode(ToolButtonPopupMode.MenuButtonPopup);
\r
528 fontHilight.setAutoRaise(false);
\r
529 fontHilightColorMenu = new ColorMenu(this);
\r
530 fontHilightColorMenu.setDefault(QColor.yellow);
\r
531 fontHilight.setMenu(fontHilightColorMenu.getMenu());
\r
532 fontHilightColorMenu.getMenu().triggered.connect(this, "fontHilightClicked()");
\r
533 fontHilightAction = buttonLayout.addWidget(fontHilight);
\r
534 fontHilightColorMenu.setDefault(QColor.yellow);
\r
535 buttonLayout.toggleFontHilight.triggered.connect(this, "toggleFontHilightVisible(Boolean)");
\r
537 spellCheckAction = buttonLayout.addWidget(spellCheckButton);
\r
538 buttonLayout.toggleNumberListVisible.triggered.connect(this, "spellCheckClicked()");
\r
539 buttonLayout.toggleSpellCheck.triggered.connect(this, "toggleSpellCheckVisible(Boolean)");
\r
541 todoAction = buttonLayout.addWidget(todoButton);
\r
542 buttonLayout.toggleNumberListVisible.triggered.connect(this, "todoClicked()");
\r
543 buttonLayout.toggleTodo.triggered.connect(this, "toggleTodoVisible(Boolean)");
\r
546 // buttonLayout.addWidget(new QLabel(), 1);
\r
547 v.addWidget(browser, 1);
\r
550 browser.downloadAttachmentRequested.connect(this,
\r
551 "downloadAttachment(QNetworkRequest)");
\r
552 browser.downloadImageRequested.connect(this,
\r
553 "downloadImage(QNetworkRequest)");
\r
554 setTabOrder(notebookBox, tagEdit);
\r
555 setTabOrder(tagEdit, browser);
\r
557 focusNoteShortcut = new QShortcut(this);
\r
558 setupShortcut(focusNoteShortcut, "Focus_Note");
\r
559 focusNoteShortcut.activated.connect(this, "focusNote()");
\r
560 focusTitleShortcut = new QShortcut(this);
\r
561 setupShortcut(focusTitleShortcut, "Focus_Title");
\r
562 focusTitleShortcut.activated.connect(this, "focusTitle()");
\r
563 focusTagShortcut = new QShortcut(this);
\r
564 setupShortcut(focusTagShortcut, "Focus_Tag");
\r
565 focusTagShortcut.activated.connect(this, "focusTag()");
\r
566 focusAuthorShortcut = new QShortcut(this);
\r
567 setupShortcut(focusAuthorShortcut, "Focus_Author");
\r
568 focusAuthorShortcut.activated.connect(this, "focusAuthor()");
\r
569 focusUrlShortcut = new QShortcut(this);
\r
570 setupShortcut(focusUrlShortcut, "Focus_Url");
\r
571 focusUrlShortcut.activated.connect(this, "focusUrl()");
\r
573 browser.page().mainFrame().setTextSizeMultiplier(Global.getTextSizeMultiplier());
\r
574 browser.page().mainFrame().setZoomFactor(Global.getZoomFactor());
\r
576 previewPageList = new HashMap<String,Integer>();
\r
578 browser.page().microFocusChanged.connect(this, "microFocusChanged()");
\r
582 QPalette pal = new QPalette();
\r
583 pal.setColor(ColorRole.Text, QColor.black);
\r
584 titleLabel.setPalette(pal);
\r
585 authorText.setPalette(pal);
\r
586 authorLabel.setPalette(pal);
\r
587 urlLabel.setPalette(pal);
\r
588 urlText.setPalette(pal);
\r
589 createdDate.setPalette(pal);
\r
590 createdTime.setPalette(pal);
\r
591 alteredDate.setPalette(pal);
\r
592 alteredTime.setPalette(pal);
\r
593 subjectDate.setPalette(pal);
\r
594 subjectTime.setPalette(pal);
\r
595 tagEdit.setPalette(pal);
\r
596 notebookBox.setPalette(pal);
\r
598 logger.log(logger.HIGH, "Browser setup complete");
\r
603 private void setupShortcut(QShortcut action, String text) {
\r
604 if (!Global.shortcutKeys.containsAction(text))
\r
606 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
\r
612 // Getter for the QWebView
\r
613 public QWebView getBrowser() {
\r
617 // Block signals while loading data or things are flagged as dirty by
\r
619 public void loadingData(boolean val) {
\r
620 logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val);
\r
621 notebookBox.blockSignals(val);
\r
622 browser.page().blockSignals(val);
\r
623 browser.page().mainFrame().blockSignals(val);
\r
624 titleLabel.blockSignals(val);
\r
625 alteredDate.blockSignals(val);
\r
626 alteredTime.blockSignals(val);
\r
627 createdTime.blockSignals(val);
\r
628 createdDate.blockSignals(val);
\r
629 subjectDate.blockSignals(val);
\r
630 subjectTime.blockSignals(val);
\r
631 urlText.blockSignals(val);
\r
632 authorText.blockSignals(val);
\r
634 exposeToJavascript();
\r
635 logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val);
\r
639 public void setReadOnly(boolean v) {
\r
641 titleLabel.setEnabled(!v);
\r
642 notebookBox.setEnabled(!v);
\r
643 tagEdit.setEnabled(!v);
\r
644 authorLabel.setEnabled(!v);
\r
645 geoBox.setEnabled(!v);
\r
646 urlText.setEnabled(!v);
\r
647 createdDate.setEnabled(!v);
\r
648 subjectDate.setEnabled(!v);
\r
649 alteredDate.setEnabled(!v);
\r
650 authorText.setEnabled(!v);
\r
651 createdTime.setEnabled(!v);
\r
652 alteredTime.setEnabled(!v);
\r
653 subjectTime.setEnabled(!v);
\r
654 getBrowser().setEnabled(true);
\r
657 // expose this class to Javascript on the web page
\r
658 private void exposeToJavascript() {
\r
659 browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this);
\r
662 // Custom event queue
\r
664 public boolean event(QEvent e) {
\r
665 if (e.type().equals(QEvent.Type.FocusOut)) {
\r
666 logger.log(logger.EXTREME, "Focus lost");
\r
669 return super.event(e);
\r
672 // clear out browser
\r
673 public void clear() {
\r
674 logger.log(logger.EXTREME, "Entering BrowserWindow.clear()");
\r
676 browser.setContent(new QByteArray());
\r
677 tagEdit.setText("");
\r
678 tagEdit.tagCompleter.reset();
\r
679 urlLabel.setText(tr("Source URL:"));
\r
680 titleLabel.setText("");
\r
681 logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()");
\r
684 // get/set current note
\r
685 public void setNote(Note n) {
\r
689 saveNoteTitle = n.getTitle();
\r
693 public Note getNote() {
\r
694 return currentNote;
\r
697 // New Editor Button
\r
698 private QPushButton newEditorButton(String name, String toolTip) {
\r
699 QPushButton button = new QPushButton();
\r
700 // QIcon icon = new QIcon(iconPath + name + ".gif");
\r
701 QIcon icon = new QIcon(iconPath + name + ".png");
\r
702 button.setIcon(icon);
\r
703 button.setToolTip(toolTip);
\r
704 button.clicked.connect(this, name + "Clicked()");
\r
707 // New Editor Button
\r
708 private QToolButton newToolButton(String name, String toolTip) {
\r
709 QToolButton button = new QToolButton();
\r
710 // QIcon icon = new QIcon(iconPath + name + ".gif");
\r
711 QIcon icon = new QIcon(iconPath + name + ".png");
\r
712 button.setIcon(icon);
\r
713 button.setToolTip(toolTip);
\r
714 button.clicked.connect(this, name + "Clicked()");
\r
719 private QLabel newSeparator() {
\r
720 return new QLabel(" ");
\r
723 // Set the title in the window
\r
724 public void setTitle(String t) {
\r
725 titleLabel.setText(t);
\r
730 // Return the current text title
\r
731 public String getTitle() {
\r
732 return titleLabel.text();
\r
735 // Set the tag name string
\r
736 public void setTag(String t) {
\r
738 tagEdit.setText(t);
\r
739 tagEdit.tagCompleter.reset();
\r
742 // Set the source URL
\r
743 public void setUrl(String t) {
\r
744 urlLabel.setText(tr("Source URL:\t"));
\r
745 urlText.setText(t);
\r
748 // The user want's to launch a web browser on the source of the URL
\r
749 public void sourceUrlClicked() {
\r
750 // Make sure we have a valid URL
\r
751 if (urlText.text().trim().equals(""))
\r
754 String url = urlText.text();
\r
755 if (!url.toLowerCase().startsWith(tr("http://")))
\r
756 url = tr("http://") +url;
\r
758 if (!QDesktopServices.openUrl(new QUrl(url))) {
\r
759 logger.log(logger.LOW, "Error opening file :" +url);
\r
763 public void setAuthor(String t) {
\r
764 authorLabel.setText(tr("Author:\t"));
\r
765 authorText.setText(t);
\r
768 // Set the creation date
\r
769 public void setCreation(long date) {
\r
770 QDateTime dt = new QDateTime();
\r
771 dt.setTime_t((int) (date / 1000));
\r
772 createdDate.setDateTime(dt);
\r
773 createdTime.setDateTime(dt);
\r
774 createdDate.setDisplayFormat(Global.getDateFormat());
\r
775 createdTime.setDisplayFormat(Global.getTimeFormat());
\r
778 // Set the creation date
\r
779 public void setAltered(long date) {
\r
780 QDateTime dt = new QDateTime();
\r
781 dt.setTime_t((int) (date / 1000));
\r
782 alteredDate.setDateTime(dt);
\r
783 alteredTime.setDateTime(dt);
\r
784 alteredDate.setDisplayFormat(Global.getDateFormat());
\r
785 alteredTime.setDisplayFormat(Global.getTimeFormat());
\r
788 // Set the subject date
\r
789 public void setSubjectDate(long date) {
\r
790 QDateTime dt = new QDateTime();
\r
791 dt.setTime_t((int) (date / 1000));
\r
792 subjectDate.setDateTime(dt);
\r
793 subjectTime.setDateTime(dt);
\r
794 subjectDate.setDisplayFormat(Global.getDateFormat());
\r
795 subjectTime.setDisplayFormat(Global.getTimeFormat());
\r
798 // Toggle the extended attribute information
\r
799 public void toggleInformation() {
\r
801 extendedOn = false;
\r
805 urlLabel.setVisible(extendedOn);
\r
806 urlText.setVisible(extendedOn);
\r
807 authorText.setVisible(extendedOn);
\r
808 geoBox.setVisible(extendedOn);
\r
809 authorLabel.setVisible(extendedOn);
\r
810 createdDate.setVisible(extendedOn);
\r
811 createdTime.setVisible(extendedOn);
\r
812 createdLabel.setVisible(extendedOn);
\r
813 alteredLabel.setVisible(extendedOn);
\r
814 alteredDate.setVisible(extendedOn);
\r
815 alteredTime.setVisible(extendedOn);
\r
816 //notebookBox.setVisible(extendedOn);
\r
817 notebookLabel.setVisible(extendedOn);
\r
818 subjectLabel.setVisible(extendedOn);
\r
819 subjectDate.setVisible(extendedOn);
\r
820 subjectTime.setVisible(extendedOn);
\r
823 public void hideButtons() {
\r
825 undoButton.parentWidget().setVisible(false);
\r
826 buttonsVisible = false;
\r
830 // Is the extended view on?
\r
831 public boolean isExtended() {
\r
835 // Listener for when a link is clicked
\r
836 @SuppressWarnings("unused")
\r
837 private void openFile() {
\r
838 logger.log(logger.EXTREME, "Starting openFile()");
\r
839 File fileHandle = new File(selectedFile);
\r
840 URI fileURL = fileHandle.toURI();
\r
841 String localURL = fileURL.toString();
\r
842 QUrl url = new QUrl(localURL);
\r
843 QFile file = new QFile(selectedFile);
\r
845 logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName());
\r
846 fileWatcher.addPath(file.fileName());
\r
848 if (!QDesktopServices.openUrl(url)) {
\r
849 logger.log(logger.LOW, "Error opening file :" +url);
\r
854 // Listener for when a link is clicked
\r
855 @SuppressWarnings("unused")
\r
856 private void linkClicked(QUrl url) {
\r
857 logger.log(logger.EXTREME, "URL Clicked: " +url.toString());
\r
858 if (url.toString().substring(0,8).equals("nnres://")) {
\r
859 logger.log(logger.EXTREME, "URL is NN resource");
\r
860 if (url.toString().endsWith("/vnd.evernote.ink")) {
\r
861 logger.log(logger.EXTREME, "Unable to open ink note");
\r
862 QMessageBox.information(this, tr("Unable Open"), tr("This is an ink note.\n"+
\r
863 "Ink notes are not supported since Evernote has not\n published any specifications on them\n" +
\r
864 "and I'm too lazy to figure them out by myself."));
\r
867 String fullName = url.toString().substring(8);
\r
868 int index = fullName.indexOf(".");
\r
872 type = fullName.substring(index+1);
\r
873 guid = fullName.substring(0,index);
\r
875 index = guid.indexOf(Global.attachmentNameDelimeter);
\r
877 guid = guid.substring(0,index);
\r
879 List<Resource> resList = currentNote.getResources();
\r
880 Resource res = null;
\r
881 for (int i=0; i<resList.size(); i++) {
\r
882 if (resList.get(i).getGuid().equals(guid)) {
\r
883 res = resList.get(i);
\r
888 String resGuid = Global.resourceMap.get(guid);
\r
889 if (resGuid != null)
\r
890 res = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, true);
\r
894 if (res.getAttributes() != null &&
\r
895 res.getAttributes().getFileName() != null &&
\r
896 !res.getAttributes().getFileName().trim().equals(""))
\r
897 fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();
\r
899 fileName = res.getGuid()+"."+type;
\r
900 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
901 QFile.OpenMode mode = new QFile.OpenMode();
\r
902 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
903 boolean openResult = file.open(mode);
\r
904 logger.log(logger.EXTREME, "File opened:" +openResult);
\r
905 QDataStream out = new QDataStream(file);
\r
906 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);
\r
907 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
909 logger.log(logger.EXTREME, "Writing resource");
\r
910 out.writeBytes(binData.toByteArray());
\r
913 String whichOS = System.getProperty("os.name");
\r
914 if (whichOS.contains("Windows"))
\r
915 url.setUrl("file:///"+file.fileName());
\r
917 url.setUrl("file://"+file.fileName());
\r
918 // fileWatcher.removePath(file.fileName());
\r
919 logger.log(logger.EXTREME, "Adding file watcher " +file.fileName());
\r
920 fileWatcher.addPath(file.fileName());
\r
922 // If we can't open it, then prompt the user to save it.
\r
923 if (!QDesktopServices.openUrl(url)) {
\r
924 logger.log(logger.EXTREME, "We can't handle this. Where do we put it?");
\r
925 QFileDialog dialog = new QFileDialog();
\r
927 if (dialog.exec()!=0) {
\r
928 List<String> fileNames = dialog.selectedFiles(); //gets all selected filenames
\r
929 if (fileNames.size() == 0)
\r
931 String sf = fileNames.get(0);
\r
932 QFile saveFile = new QFile(sf);
\r
933 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
934 saveFile.open(mode);
\r
935 QDataStream saveOut = new QDataStream(saveFile);
\r
936 saveOut.writeBytes(binData.toByteArray());
\r
944 logger.log(logger.EXTREME, "Launching URL");
\r
945 QDesktopServices.openUrl(url);
\r
948 // Listener for when BOLD is clicked
\r
949 @SuppressWarnings("unused")
\r
950 private void undoClicked() {
\r
951 browser.page().triggerAction(WebAction.Undo);
\r
952 browser.setFocus();
\r
955 // Listener for when BOLD is clicked
\r
956 @SuppressWarnings("unused")
\r
957 private void redoClicked() {
\r
958 browser.page().triggerAction(WebAction.Redo);
\r
959 browser.setFocus();
\r
962 // Listener for when BOLD is clicked
\r
963 @SuppressWarnings("unused")
\r
964 private void boldClicked() {
\r
965 browser.page().triggerAction(WebAction.ToggleBold);
\r
966 microFocusChanged();
\r
967 browser.setFocus();
\r
970 // Listener for when Italics is clicked
\r
971 @SuppressWarnings("unused")
\r
972 private void italicClicked() {
\r
973 browser.page().triggerAction(WebAction.ToggleItalic);
\r
974 microFocusChanged();
\r
975 browser.setFocus();
\r
978 // Listener for when UNDERLINE is clicked
\r
979 @SuppressWarnings("unused")
\r
980 private void underlineClicked() {
\r
981 browser.page().triggerAction(WebAction.ToggleUnderline);
\r
982 microFocusChanged();
\r
983 browser.setFocus();
\r
986 // Listener for when Strikethrough is clicked
\r
987 @SuppressWarnings("unused")
\r
988 private void strikethroughClicked() {
\r
989 browser.page().mainFrame().evaluateJavaScript(
\r
990 "document.execCommand('strikeThrough', false, '');");
\r
991 browser.setFocus();
\r
994 // Listener for when cut is clicked
\r
995 @SuppressWarnings("unused")
\r
996 private void cutClicked() {
\r
997 browser.page().triggerAction(WebAction.Cut);
\r
998 browser.setFocus();
\r
1001 // Listener when COPY is clicked
\r
1002 @SuppressWarnings("unused")
\r
1003 private void copyClicked() {
\r
1004 browser.page().triggerAction(WebAction.Copy);
\r
1005 browser.setFocus();
\r
1008 // Listener when PASTE is clicked
\r
1009 public void pasteClicked() {
\r
1010 logger.log(logger.EXTREME, "Paste Clicked");
\r
1011 if (forceTextPaste) {
\r
1012 pasteWithoutFormattingClicked();
\r
1015 QClipboard clipboard = QApplication.clipboard();
\r
1016 QMimeData mime = clipboard.mimeData();
\r
1018 // String x = mime.html();
\r
1020 if (mime.hasImage()) {
\r
1021 logger.log(logger.EXTREME, "Image paste found");
\r
1022 browser.setFocus();
\r
1023 insertImage(mime);
\r
1024 browser.setFocus();
\r
1028 if (mime.hasUrls()) {
\r
1029 logger.log(logger.EXTREME, "URL paste found");
\r
1031 browser.setFocus();
\r
1035 String text = mime.html();
\r
1036 if (text.contains("en-tag") && mime.hasHtml()) {
\r
1037 logger.log(logger.EXTREME, "Intra-note paste found");
\r
1038 text = fixInternotePaste(text);
\r
1039 mime.setHtml(text);
\r
1040 clipboard.setMimeData(mime);
\r
1043 logger.log(logger.EXTREME, "Final paste choice encountered");
\r
1044 browser.page().triggerAction(WebAction.Paste);
\r
1045 browser.setFocus();
\r
1049 // Paste text without formatting
\r
1050 private void pasteWithoutFormattingClicked() {
\r
1051 logger.log(logger.EXTREME, "Paste without format clipped");
\r
1052 QClipboard clipboard = QApplication.clipboard();
\r
1053 QMimeData mime = clipboard.mimeData();
\r
1054 if (!mime.hasText())
\r
1056 String text = mime.text();
\r
1057 clipboard.clear();
\r
1058 clipboard.setText(text, Mode.Clipboard);
\r
1059 browser.page().triggerAction(WebAction.Paste);
\r
1061 // This is done because pasting into an encryption block
\r
1062 // can cause multiple cells (which can't happen). It
\r
1063 // just goes through the table, extracts the data, &
\r
1064 // puts it back as one table cell.
\r
1065 if (insideEncryption) {
\r
1066 String js = new String( "function fixEncryption() { "
\r
1067 +" var selObj = window.getSelection();"
\r
1068 +" var selRange = selObj.getRangeAt(0);"
\r
1069 +" var workingNode = window.getSelection().anchorNode;"
\r
1070 +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
\r
1071 +" workingNode = workingNode.parentNode;"
\r
1073 +" workingNode.innerHTML = window.jambi.fixEncryptionPaste(workingNode.innerHTML);"
\r
1074 +"} fixEncryption();");
\r
1075 browser.page().mainFrame().evaluateJavaScript(js);
\r
1079 // This basically removes all the table tags and returns just the contents.
\r
1080 // This is called by JavaScript to fix encryption pastes.
\r
1081 public String fixEncryptionPaste(String data) {
\r
1082 data = data.replace("<tbody>", "");
\r
1083 data = data.replace("</tbody>", "");
\r
1084 data = data.replace("<tr>", "");
\r
1085 data = data.replace("</tr>", "");
\r
1086 data = data.replace("<td>", "");
\r
1087 data = data.replace("</td>", "<br>");
\r
1088 data = data.replace("<br><br>", "<br>");
\r
1090 return "<tbody><tr><td>"+data+"</td></tr></tbody>";
\r
1093 // insert date/time
\r
1094 @SuppressWarnings("unused")
\r
1095 private void insertDateTime() {
\r
1096 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
\r
1097 String dateTimeFormat = new String(fmt);
\r
1098 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
\r
1099 Calendar cal = Calendar.getInstance();
\r
1101 browser.page().mainFrame().evaluateJavaScript(
\r
1102 "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');");
\r
1104 browser.setFocus();
\r
1108 // Listener when Left is clicked
\r
1109 @SuppressWarnings("unused")
\r
1110 private void justifyLeftClicked() {
\r
1111 browser.page().mainFrame().evaluateJavaScript(
\r
1112 "document.execCommand('JustifyLeft', false, '');");
\r
1113 browser.setFocus();
\r
1116 // Listener when Center is clicked
\r
1117 @SuppressWarnings("unused")
\r
1118 private void justifyCenterClicked() {
\r
1119 browser.page().mainFrame().evaluateJavaScript(
\r
1120 "document.execCommand('JustifyCenter', false, '');");
\r
1121 browser.setFocus();
\r
1124 // Listener when Left is clicked
\r
1125 @SuppressWarnings("unused")
\r
1126 private void justifyRightClicked() {
\r
1127 browser.page().mainFrame().evaluateJavaScript(
\r
1128 "document.execCommand('JustifyRight', false, '');");
\r
1129 browser.setFocus();
\r
1132 // Listener when HLINE is clicked
\r
1133 @SuppressWarnings("unused")
\r
1134 private void hlineClicked() {
\r
1135 browser.page().mainFrame().evaluateJavaScript(
\r
1136 "document.execCommand('insertHorizontalRule', false, '');");
\r
1137 browser.setFocus();
\r
1140 // Listener when outdent is clicked
\r
1141 private void outdentClicked() {
\r
1142 browser.page().mainFrame().evaluateJavaScript(
\r
1143 "document.execCommand('outdent', false, '');");
\r
1144 browser.setFocus();
\r
1147 // Listener when a bullet list is clicked
\r
1148 @SuppressWarnings("unused")
\r
1149 private void bulletListClicked() {
\r
1150 browser.page().mainFrame().evaluateJavaScript(
\r
1151 "document.execCommand('InsertUnorderedList', false, '');");
\r
1152 browser.setFocus();
\r
1155 // Listener when a bullet list is clicked
\r
1156 @SuppressWarnings("unused")
\r
1157 private void numberListClicked() {
\r
1158 browser.page().mainFrame().evaluateJavaScript(
\r
1159 "document.execCommand('InsertOrderedList', false, '');");
\r
1160 browser.setFocus();
\r
1163 // Listener when indent is clicked
\r
1164 private void indentClicked() {
\r
1165 browser.page().mainFrame().evaluateJavaScript(
\r
1166 "document.execCommand('indent', false, '');");
\r
1167 browser.setFocus();
\r
1170 // Listener when the font name is changed
\r
1171 @SuppressWarnings("unused")
\r
1172 private void fontChanged(String font) {
\r
1173 browser.page().mainFrame().evaluateJavaScript(
\r
1174 "document.execCommand('fontName',false,'" + font + "');");
\r
1175 browser.setFocus();
\r
1178 // Listener when a font size is changed
\r
1179 @SuppressWarnings("unused")
\r
1180 private void fontSizeChanged(String font) {
\r
1181 String text = browser.selectedText();
\r
1182 if (text.trim().equalsIgnoreCase(""))
\r
1185 String selectedText = browser.selectedText();
\r
1186 String url = "<span style=\"font-size:" +font +"pt; \">"+selectedText +"</a>";
\r
1187 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1188 browser.page().mainFrame().evaluateJavaScript(script);
\r
1189 /* browser.page().mainFrame().evaluateJavaScript(
\r
1190 "document.execCommand('fontSize',false,'"
\r
1193 browser.setFocus();
\r
1196 // Load the font combo box based upon the font selected
\r
1197 private void loadFontSize(String name) {
\r
1198 QFontDatabase db = new QFontDatabase();
\r
1200 List<Integer> points = db.pointSizes(name);
\r
1201 for (int i=0; i<points.size(); i++) {
\r
1202 fontSize.addItem(points.get(i).toString());
\r
1205 fontSize.addItem("x-small");
\r
1206 fontSize.addItem("small");
\r
1207 fontSize.addItem("medium");
\r
1208 fontSize.addItem("large");
\r
1209 fontSize.addItem("x-large");
\r
1210 fontSize.addItem("xx-large");
\r
1211 fontSize.addItem("xxx-large");
\r
1215 // Listener when a font size is changed
\r
1216 @SuppressWarnings("unused")
\r
1217 private void fontColorClicked() {
\r
1218 // QColorDialog dialog = new QColorDialog();
\r
1219 // QColor color = QColorDialog.getColor();
\r
1220 QColor color = fontColorMenu.getColor();
\r
1221 if (color.isValid())
\r
1222 browser.page().mainFrame().evaluateJavaScript(
\r
1223 "document.execCommand('foreColor',false,'" + color.name()
\r
1225 browser.setFocus();
\r
1228 // Listener for when a background color change is requested
\r
1229 @SuppressWarnings("unused")
\r
1230 private void fontHilightClicked() {
\r
1231 // QColorDialog dialog = new QColorDialog();
\r
1232 // QColor color = QColorDialog.getColor();
\r
1233 QColor color = fontHilightColorMenu.getColor();
\r
1234 if (color.isValid())
\r
1235 browser.page().mainFrame().evaluateJavaScript(
\r
1236 "document.execCommand('backColor',false,'" + color.name()
\r
1238 browser.setFocus();
\r
1241 // Listener for when a background color change is requested
\r
1242 @SuppressWarnings("unused")
\r
1243 private void superscriptClicked() {
\r
1244 browser.page().mainFrame().evaluateJavaScript(
\r
1245 "document.execCommand('superscript');");
\r
1246 browser.setFocus();
\r
1249 // Listener for when a background color change is requested
\r
1250 @SuppressWarnings("unused")
\r
1251 private void subscriptClicked() {
\r
1252 browser.page().mainFrame().evaluateJavaScript(
\r
1253 "document.execCommand('subscript');");
\r
1254 browser.setFocus();
\r
1256 // Insert a to-do checkbox
\r
1257 @SuppressWarnings("unused")
\r
1258 private void todoClicked() {
\r
1259 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1260 String script_start = new String(
\r
1261 "document.execCommand('insertHtml', false, '");
\r
1262 String script_end = new String("');");
\r
1263 String todo = new String(
\r
1264 "<input TYPE=\"CHECKBOX\" value=\"false\" " +
\r
1265 "onMouseOver=\"style.cursor=\\'hand\\'\" " +
\r
1266 "onClick=\"value=checked; window.jambi.contentChanged(); \" />");
\r
1267 browser.page().mainFrame().evaluateJavaScript(
\r
1268 script_start + todo + script_end);
\r
1269 browser.setFocus();
\r
1272 // Encrypt the selected text
\r
1273 @SuppressWarnings("unused")
\r
1274 private void encryptText() {
\r
1275 String text = browser.selectedText();
\r
1276 if (text.trim().equalsIgnoreCase(""))
\r
1278 text = new String(text.replaceAll("\n", "<br/>"));
\r
1280 EnCryptDialog dialog = new EnCryptDialog();
\r
1282 if (!dialog.okPressed()) {
\r
1286 EnCrypt crypt = new EnCrypt();
\r
1287 String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);
\r
1288 String decrypted = crypt.decrypt(encrypted, dialog.getPassword().trim(), 64);
\r
1290 if (encrypted.trim().equals("")) {
\r
1291 QMessageBox.information(this, tr("Error"), tr("Error Encrypting String"));
\r
1294 StringBuffer buffer = new StringBuffer(encrypted.length() + 100);
\r
1295 buffer.append("<img en-tag=\"en-crypt\" cipher=\"RC2\" hint=\""
\r
1296 + dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");
\r
1297 buffer.append("contentEditable=\"false\" alt=\"");
\r
1298 buffer.append(encrypted);
\r
1299 buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png") +"\""));
\r
1300 Global.cryptCounter++;
\r
1301 buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");
\r
1302 buffer.append(" onMouseOver=\"style.cursor=\\'hand\\'\"");
\r
1303 buffer.append(" onClick=\"window.jambi.decryptText(\\'crypt"+Global.cryptCounter.toString()
\r
1304 +"\\', \\'"+encrypted+"\\', \\'"+dialog.getHint().replace("'", "\\&apos;")+"\\');\"");
\r
1305 buffer.append("style=\"display:block\" />");
\r
1307 String script_start = new String(
\r
1308 "document.execCommand('insertHtml', false, '");
\r
1309 String script_end = new String("');");
\r
1310 browser.page().mainFrame().evaluateJavaScript(
\r
1311 script_start + buffer.toString() + script_end);
\r
1315 // Insert a hyperlink
\r
1316 public void insertLink() {
\r
1317 logger.log(logger.EXTREME, "Inserting link");
\r
1318 String text = browser.selectedText();
\r
1319 if (text.trim().equalsIgnoreCase(""))
\r
1322 InsertLinkDialog dialog = new InsertLinkDialog(insertHyperlink);
\r
1323 if (currentHyperlink != null && currentHyperlink != "") {
\r
1324 dialog.setUrl(currentHyperlink);
\r
1327 if (!dialog.okPressed()) {
\r
1328 logger.log(logger.EXTREME, "Insert link canceled");
\r
1332 // Take care of inserting new links
\r
1333 if (insertHyperlink) {
\r
1334 String selectedText = browser.selectedText();
\r
1335 if (dialog.getUrl().trim().equals(""))
\r
1337 logger.log(logger.EXTREME, "Inserting link on text "+selectedText);
\r
1338 logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim());
\r
1339 String dUrl = StringUtils.replace(dialog.getUrl().trim(), "'", "\\'");
\r
1340 String url = "<a href=\"" +dUrl
\r
1341 +"\" title=" +dUrl
\r
1342 +" >"+selectedText +"</a>";
\r
1343 String script = "document.execCommand('insertHtml', false, '"+url+"');";
\r
1344 browser.page().mainFrame().evaluateJavaScript(script);
\r
1348 // Edit existing links
\r
1349 String js = new String( "function getCursorPos() {"
\r
1351 +"if (window.getSelection) {"
\r
1352 +" var selObj = window.getSelection();"
\r
1353 +" var selRange = selObj.getRangeAt(0);"
\r
1354 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1355 +" while(workingNode != null) { "
\r
1356 +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');"
\r
1357 +" workingNode = workingNode.parentNode;"
\r
1360 +"} getCursorPos();");
\r
1361 browser.page().mainFrame().evaluateJavaScript(js);
\r
1363 if (!dialog.getUrl().trim().equals("")) {
\r
1369 js = new String( "function getCursorPos() {"
\r
1371 +"if (window.getSelection) {"
\r
1372 +" var selObj = window.getSelection();"
\r
1373 +" var selRange = selObj.getRangeAt(0);"
\r
1374 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
1375 +" while(workingNode != null) { "
\r
1376 +" if (workingNode.nodeName.toLowerCase()=='a') { "
\r
1377 +" workingNode.removeAttribute('href');"
\r
1378 +" workingNode.removeAttribute('title');"
\r
1379 +" var text = document.createTextNode(workingNode.innerText);"
\r
1380 +" workingNode.parentNode.insertBefore(text, workingNode);"
\r
1381 +" workingNode.parentNode.removeChild(workingNode);"
\r
1383 +" workingNode = workingNode.parentNode;"
\r
1386 +"} getCursorPos();");
\r
1387 browser.page().mainFrame().evaluateJavaScript(js);
\r
1396 public void insertTable() {
\r
1397 TableDialog dialog = new TableDialog();
\r
1399 if (!dialog.okPressed()) {
\r
1403 int cols = dialog.getCols();
\r
1404 int rows = dialog.getRows();
\r
1405 int width = dialog.getWidth();
\r
1406 boolean percent = dialog.isPercent();
\r
1408 String newHTML = "<table border=\"1\" width=\"" +new Integer(width).toString();
\r
1410 newHTML = newHTML +"%";
\r
1411 newHTML = newHTML + "\"><tbody>";
\r
1413 for (int i=0; i<rows; i++) {
\r
1414 newHTML = newHTML +"<tr>";
\r
1415 for (int j=0; j<cols; j++) {
\r
1416 newHTML = newHTML +"<td> </td>";
\r
1418 newHTML = newHTML +"</tr>";
\r
1420 newHTML = newHTML+"</tbody></table>";
\r
1422 String script = "document.execCommand('insertHtml', false, '"+newHTML+"');";
\r
1423 browser.page().mainFrame().evaluateJavaScript(script);
\r
1427 // Text content changed
\r
1428 @SuppressWarnings("unused")
\r
1429 private void selectionChanged() {
\r
1430 browser.encryptAction.setEnabled(true);
\r
1431 browser.insertLinkAction.setEnabled(true);
\r
1432 String scriptStart = "var selection_text = (window.getSelection()).toString();"
\r
1433 + "var range = (window.getSelection()).getRangeAt(0);"
\r
1434 + "var parent_html = range.commonAncestorContainer.innerHTML;"
\r
1435 + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}"
\r
1436 + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);"
\r
1437 + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);"
\r
1438 + "var start = parent_html.indexOf(first_text);"
\r
1439 + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;"
\r
1440 + "var value = parent_html.substring(start,end);"
\r
1441 + "window.jambi.saveSelectedText(value);" ;
\r
1442 browser.page().mainFrame().evaluateJavaScript(scriptStart);
\r
1446 public void saveSelectedText(String text) {
\r
1447 boolean enabled = true;
\r
1448 if (text.trim().length() == 0)
\r
1450 if (text.indexOf("en-tag=\"en-crypt\"") >= 0)
\r
1452 if (text.indexOf("<img en-tag=\"en-media\"") >= 0)
\r
1454 if (text.indexOf("<a en-tag=\"en-media\"") >= 0)
\r
1456 if (text.indexOf("<input ") >= 0)
\r
1459 browser.encryptAction.setEnabled(enabled);
\r
1460 browser.insertLinkAction.setEnabled(enabled);
\r
1461 // selectedText = text;
\r
1464 // Decrypt clicked text
\r
1465 public void decryptText(String id, String text, String hint) {
\r
1466 EnCrypt crypt = new EnCrypt();
\r
1467 String plainText = null;
\r
1468 Calendar currentTime = new GregorianCalendar();
\r
1469 Long l = new Long(currentTime.getTimeInMillis());
\r
1470 String slot = new String(Long.toString(l));
\r
1472 // First, try to decrypt with any keys we already have
\r
1473 for (int i=0; i<Global.passwordRemember.size(); i++) {
\r
1474 plainText = crypt.decrypt(text, Global.passwordRemember.get(i).getFirst(), 64);
\r
1475 if (plainText != null) {
\r
1476 slot = new String(Long.toString(l));
\r
1477 Global.passwordSafe.put(slot, Global.passwordRemember.get(i));
\r
1478 removeEncryption(id, plainText, false, slot);
\r
1484 EnDecryptDialog dialog = new EnDecryptDialog();
\r
1485 dialog.setHint(hint);
\r
1486 while (plainText == null || !dialog.okPressed()) {
\r
1488 if (!dialog.okPressed()) {
\r
1491 plainText = crypt.decrypt(text, dialog.getPassword().trim(), 64);
\r
1492 if (plainText == null) {
\r
1493 QMessageBox.warning(this, "Incorrect Password", "The password entered is not correct");
\r
1496 Pair<String,String> passwordPair = new Pair<String,String>();
\r
1497 passwordPair.setFirst(dialog.getPassword());
\r
1498 passwordPair.setSecond(dialog.getHint());
\r
1499 Global.passwordSafe.put(slot, passwordPair);
\r
1500 // removeEncryption(id, plainText.replaceAll("\n", "<br/>"), dialog.permanentlyDecrypt(), slot);
\r
1501 removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);
\r
1502 if (dialog.rememberPassword()) {
\r
1503 Pair<String, String> pair = new Pair<String,String>();
\r
1504 pair.setFirst(dialog.getPassword());
\r
1505 pair.setSecond(dialog.getHint());
\r
1506 Global.passwordRemember.add(pair);
\r
1511 // Get the editor tag line
\r
1512 public TagLineEdit getTagLine() {
\r
1516 // Modify a note's tags
\r
1517 @SuppressWarnings("unused")
\r
1518 private void modifyTags() {
\r
1519 TagAssign tagWindow = new TagAssign(allTags, currentTags, !conn.getNotebookTable().isLinked(currentNote.getNotebookGuid()));
\r
1521 if (tagWindow.okClicked()) {
\r
1522 currentTags.clear();
\r
1523 StringBuffer tagDisplay = new StringBuffer();
\r
1525 List<QListWidgetItem> newTags = tagWindow.getTagList()
\r
1527 for (int i = 0; i < newTags.size(); i++) {
\r
1528 currentTags.add(newTags.get(i).text());
\r
1529 tagDisplay.append(newTags.get(i).text());
\r
1530 if (i < newTags.size() - 1) {
\r
1531 tagDisplay.append(Global.tagDelimeter + " ");
\r
1534 tagEdit.setText(tagDisplay.toString());
\r
1535 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1539 // Tag line has been modified by typing text
\r
1540 @SuppressWarnings("unused")
\r
1541 private void modifyTagsTyping() {
\r
1542 String completionText = "";
\r
1543 if (tagEdit.currentCompleterSelection != null && !tagEdit.currentCompleterSelection.equals("")) {
\r
1544 completionText = tagEdit.currentCompleterSelection;
\r
1545 tagEdit.currentCompleterSelection = "";
\r
1548 if (tagEdit.text().equalsIgnoreCase(saveTagList))
\r
1551 // We know something has changed...
\r
1552 String oldTagArray[] = saveTagList.split(Global.tagDelimeter);
\r
1553 String newTagArray[];
\r
1554 if (!completionText.equals("")) {
\r
1555 String before = tagEdit.text().substring(0,tagEdit.cursorPosition());
\r
1556 int lastDelimiter = before.lastIndexOf(Global.tagDelimeter);
\r
1557 if (lastDelimiter > 0)
\r
1558 before = before.substring(0,before.lastIndexOf(Global.tagDelimeter));
\r
1561 String after = tagEdit.text().substring(tagEdit.cursorPosition());
\r
1562 newTagArray = (before+Global.tagDelimeter+completionText+Global.tagDelimeter+after).split(Global.tagDelimeter);
\r
1565 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1568 // Remove any traling or leading blanks
\r
1569 for (int i=0; i<newTagArray.length; i++)
\r
1570 newTagArray[i] = newTagArray[i].trim().replaceAll("^\\s+", "");;
\r
1572 // Remove any potential duplicates from the new list
\r
1573 for (int i=0; i<newTagArray.length; i++) {
\r
1574 boolean foundOnce = false;
\r
1575 for (int j=0; j<newTagArray.length; j++) {
\r
1576 if (newTagArray[j].equalsIgnoreCase(newTagArray[i])) {
\r
1580 newTagArray[j] = "";
\r
1585 List<String> newTagList = new ArrayList<String>();
\r
1586 List<String> oldTagList = new ArrayList<String>();
\r
1588 for (int i = 0; i < oldTagArray.length; i++)
\r
1589 if (!oldTagArray[i].trim().equals(""))
\r
1590 oldTagList.add(oldTagArray[i]);
\r
1591 for (int i = 0; i < newTagArray.length; i++)
\r
1592 if (!newTagArray[i].trim().equals(""))
\r
1593 newTagList.add(newTagArray[i]);
\r
1595 if (conn.getNotebookTable().isLinked(currentNote.getNotebookGuid())) {
\r
1596 for (int i=newTagList.size()-1; i>=0; i--) {
\r
1597 boolean found = false;
\r
1598 for (int j=0; j<allTags.size(); j++) {
\r
1599 if (allTags.get(j).getName().equalsIgnoreCase(newTagList.get(i))) {
\r
1605 newTagList.remove(i);
\r
1609 // Let's cleanup the appearance of the tag list
\r
1610 Collections.sort(newTagList);
\r
1611 String newDisplay = "";
\r
1612 for (int i=0; i<newTagList.size(); i++) {
\r
1613 newDisplay = newDisplay+newTagList.get(i);
\r
1614 if (i<newTagList.size()-1)
\r
1615 newDisplay = newDisplay+Global.tagDelimeter +" ";
\r
1617 tagEdit.blockSignals(true);
\r
1618 tagEdit.setText(newDisplay);
\r
1619 tagEdit.blockSignals(false);
\r
1621 // We now have lists of the new & old. Remove duplicates. If all
\r
1622 // are removed from both then nothing has really changed
\r
1623 for (int i = newTagList.size() - 1; i >= 0; i--) {
\r
1624 String nTag = newTagList.get(i);
\r
1625 for (int j = oldTagList.size() - 1; j >= 0; j--) {
\r
1626 String oTag = oldTagList.get(j);
\r
1627 if (oTag.equalsIgnoreCase(nTag)) {
\r
1628 oldTagList.remove(j);
\r
1629 newTagList.remove(i);
\r
1635 if (oldTagList.size() != 0 || newTagList.size() != 0) {
\r
1636 currentTags.clear();
\r
1637 newTagArray = tagEdit.text().split(Global.tagDelimeter);
\r
1638 for (int i = 0; i < newTagArray.length; i++)
\r
1639 if (!newTagArray[i].trim().equals(""))
\r
1640 currentTags.add(newTagArray[i].trim());
\r
1642 noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags);
\r
1647 // Tab button was pressed
\r
1648 public void tabPressed() {
\r
1649 if (insideEncryption)
\r
1651 if (!insideList && !insideTable) {
\r
1652 String script_start = new String(
\r
1653 "document.execCommand('insertHtml', false, ' ');");
\r
1654 browser.page().mainFrame().evaluateJavaScript(script_start);
\r
1660 if (insideTable) {
\r
1661 String js = new String( "function getCursorPosition() { "
\r
1662 +" var selObj = window.getSelection();"
\r
1663 +" var selRange = selObj.getRangeAt(0);"
\r
1664 +" var workingNode = window.getSelection().anchorNode;"
\r
1665 +" var rowCount = 0;"
\r
1666 +" var colCount = 0;"
\r
1667 +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
\r
1668 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
1669 +" rowCount = rowCount+1;"
\r
1671 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
1672 +" colCount = colCount+1;"
\r
1674 +" if (workingNode.previousSibling != null)"
\r
1675 +" workingNode = workingNode.previousSibling;"
\r
1677 +" workingNode = workingNode.parentNode;"
\r
1679 +" var nodes = workingNode.getElementsByTagName('tr');"
\r
1680 +" var tableRows = nodes.length;"
\r
1681 +" nodes = nodes[0].getElementsByTagName('td');"
\r
1682 +" var tableColumns = nodes.length;"
\r
1683 +" window.jambi.setTableCursorPositionTab(rowCount, colCount, tableRows, tableColumns);"
\r
1684 +"} getCursorPosition();");
\r
1685 browser.page().mainFrame().evaluateJavaScript(js);
\r
1689 // If a user presses tab from within a table
\r
1690 public void setTableCursorPositionTab(int currentRow, int currentCol, int tableRows, int tableColumns) {
\r
1691 if (tableRows == currentRow && currentCol == tableColumns) {
\r
1694 KeyboardModifiers modifiers = new KeyboardModifiers(KeyboardModifier.NoModifier);
\r
1695 QKeyEvent right = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Right.value(), modifiers);
\r
1696 QKeyEvent end = new QKeyEvent(Type.KeyPress, Qt.Key.Key_End.value(), modifiers);
\r
1697 QKeyEvent end2 = new QKeyEvent(Type.KeyPress, Qt.Key.Key_End.value(), modifiers);
\r
1698 getBrowser().focusWidget();
\r
1699 QCoreApplication.postEvent(getBrowser(), end);
\r
1700 QCoreApplication.postEvent(getBrowser(), right);
\r
1701 QCoreApplication.postEvent(getBrowser(), end2);
\r
1704 public void backtabPressed() {
\r
1705 if (insideEncryption)
\r
1709 if (insideTable) {
\r
1710 String js = new String( "function getCursorPosition() { "
\r
1711 +" var selObj = window.getSelection();"
\r
1712 +" var selRange = selObj.getRangeAt(0);"
\r
1713 +" var workingNode = window.getSelection().anchorNode;"
\r
1714 +" var rowCount = 0;"
\r
1715 +" var colCount = 0;"
\r
1716 +" while(workingNode != null && workingNode.nodeName.toLowerCase() != 'table') { "
\r
1717 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
1718 +" rowCount = rowCount+1;"
\r
1720 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
1721 +" colCount = colCount+1;"
\r
1723 +" if (workingNode.previousSibling != null)"
\r
1724 +" workingNode = workingNode.previousSibling;"
\r
1726 +" workingNode = workingNode.parentNode;"
\r
1728 +" var nodes = workingNode.getElementsByTagName('tr');"
\r
1729 +" var tableRows = nodes.length;"
\r
1730 +" nodes = nodes[0].getElementsByTagName('td');"
\r
1731 +" var tableColumns = nodes.length;"
\r
1732 +" window.jambi.setTableCursorPositionBackTab(rowCount, colCount, tableRows, tableColumns);"
\r
1733 +"} getCursorPosition();");
\r
1734 browser.page().mainFrame().evaluateJavaScript(js);
\r
1739 // If a user presses backtab from within a table
\r
1740 public void setTableCursorPositionBackTab(int currentRow, int currentCol, int tableRows, int tableColumns) {
\r
1741 if (currentRow == 1 && currentCol == 1) {
\r
1744 KeyboardModifiers modifiers = new KeyboardModifiers(KeyboardModifier.NoModifier);
\r
1745 QKeyEvent left = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Left.value(), modifiers);
\r
1746 QKeyEvent home = new QKeyEvent(Type.KeyPress, Qt.Key.Key_Home.value(), modifiers);
\r
1747 getBrowser().focusWidget();
\r
1748 QCoreApplication.postEvent(getBrowser(), home);
\r
1749 QCoreApplication.postEvent(getBrowser(), left);
\r
1753 public void setInsideList() {
\r
1754 insideList = true;
\r
1757 // The title has been edited
\r
1758 @SuppressWarnings("unused")
\r
1759 private void titleEdited() {
\r
1760 // If we don't have a good note, or if the current title
\r
1761 // matches the old title then we don't need to do anything
\r
1762 if (currentNote == null)
\r
1764 if (currentNote.getTitle().trim().equals(titleLabel.text().trim()))
\r
1767 // If we have a real change, we need to save it.
\r
1768 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text());
\r
1769 currentNote.setTitle(titleLabel.text());
\r
1770 saveNoteTitle = titleLabel.text();
\r
1774 // Set the list of note tags
\r
1775 public void setAllTags(List<Tag> l) {
\r
1777 tagEdit.setTagList(l);
\r
1780 // Setter for the current tags
\r
1781 public void setCurrentTags(List<String> s) {
\r
1785 // Save the list of notebooks
\r
1786 public void setNotebookList(List<Notebook> n) {
\r
1788 loadNotebookList();
\r
1791 // Load the notebook list and select the current notebook
\r
1792 private void loadNotebookList() {
\r
1793 if (notebookBox.count() != 0)
\r
1794 notebookBox.clear();
\r
1795 if (notebookList == null)
\r
1798 for (int i = 0; i < notebookList.size(); i++) {
\r
1799 notebookBox.addItem(notebookList.get(i).getName());
\r
1800 if (currentNote != null) {
\r
1801 if (currentNote.getNotebookGuid().equals(
\r
1802 notebookList.get(i).getGuid())) {
\r
1803 notebookBox.setCurrentIndex(i);
\r
1810 // Set the notebook for a note
\r
1811 public void setNotebook(String notebook) {
\r
1812 currentNote.setNotebookGuid(notebook);
\r
1813 loadNotebookList();
\r
1816 // Get the contents of the editor
\r
1817 public String getContent() {
\r
1818 return browser.page().currentFrame().toHtml();
\r
1821 // The note contents have changed
\r
1822 public void contentChanged() {
\r
1823 String content = getContent();
\r
1825 noteSignal.noteChanged.emit(currentNote.getGuid(), content);
\r
1828 // The notebook selection has changed
\r
1829 @SuppressWarnings("unused")
\r
1830 private void notebookChanged() {
\r
1831 boolean changed = false;
\r
1832 String n = notebookBox.currentText();
\r
1833 for (int i = 0; i < notebookList.size(); i++) {
\r
1834 if (n.equals(notebookList.get(i).getName())) {
\r
1835 if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) {
\r
1836 String guid = conn.getNotebookTable().findNotebookByName(n);
\r
1837 if (conn.getNotebookTable().isLinked(guid)) {
\r
1838 tagEdit.setText("");
\r
1839 noteSignal.tagsChanged.emit(currentNote.getGuid(), new ArrayList<String>());
\r
1840 FilterEditorTags t = new FilterEditorTags(conn, logger);
\r
1841 setAllTags(t.getValidTags(currentNote));
\r
1843 currentNote.setNotebookGuid(notebookList.get(i).getGuid());
\r
1846 i = notebookList.size();
\r
1850 // If the notebook changed, signal the update
\r
1852 noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote
\r
1853 .getNotebookGuid());
\r
1856 // Check the note title
\r
1857 private void checkNoteTitle() {
\r
1858 String text = browser.page().currentFrame().toPlainText();
\r
1859 if (saveNoteTitle.trim().equals("") || saveNoteTitle.trim().equals("Untitled Note")) {
\r
1860 int newLine = text.indexOf("\n");
\r
1861 if (newLine > 0) {
\r
1862 text = text.substring(0, newLine);
\r
1863 if (text.trim().equals(""))
\r
1864 text = tr("Untitled Note");
\r
1865 titleLabel.setText(text);
\r
1867 if (text.length() > Constants.EDAM_NOTE_TITLE_LEN_MAX)
\r
1868 titleLabel.setText(text.substring(0, Constants.EDAM_NOTE_TITLE_LEN_MAX));
\r
1870 titleLabel.blockSignals(true);
\r
1871 if (text.trim().equals(""))
\r
1872 titleLabel.setText(tr("Untitled Note"));
\r
1874 titleLabel.setText(text);
\r
1875 titleLabel.blockSignals(false);
\r
1878 noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel
\r
1883 // Return the note contents so we can email them
\r
1884 public String getContentsToEmail() {
\r
1885 return browser.page().currentFrame().toPlainText().trim();
\r
1887 * int body = browser.page().currentFrame().toHtml().indexOf("<body>");
\r
1888 * String temp = browser.page().currentFrame().toHtml(); if (body == -1)
\r
1889 * temp = "<html><body><b>Test</b></body></html>"; else temp =
\r
1890 * "<html>"+temp.substring(body); return temp; // return
\r
1891 * urlEncode(browser.page().currentFrame().toHtml());
\r
1895 // Insert an image into the editor
\r
1896 private void insertImage(QMimeData mime) {
\r
1897 logger.log(logger.EXTREME, "Entering insertImage");
\r
1898 QImage img = (QImage) mime.imageData();
\r
1899 String script_start = new String(
\r
1900 "document.execCommand('insertHTML', false, '");
\r
1901 String script_end = new String("');");
\r
1903 long now = new Date().getTime();
\r
1904 String path = Global.getFileManager().getResDirPath(
\r
1905 (new Long(now).toString()) + ".jpg");
\r
1907 // This block is just a hack to make sure we wait at least 1ms so we
\r
1909 // have collisions on image names
\r
1910 long i = new Date().getTime();
\r
1912 i = new Date().getTime();
\r
1914 // Open the file & write the data
\r
1915 QFile tfile = new QFile(path);
\r
1916 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
1917 if (!img.save(tfile)) {
\r
1923 Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false);
\r
1924 if (newRes == null)
\r
1926 currentNote.getResources().add(newRes);
\r
1928 // do the actual insert into the note
\r
1929 StringBuffer buffer = new StringBuffer(100);
\r
1930 buffer.append("<img src=\"");
\r
1931 buffer.append(tfile.fileName());
\r
1932 buffer.append("\" en-tag=en-media type=\"image/jpeg\""
\r
1933 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
1934 +" guid=\"" +newRes.getGuid() +"\""
\r
1935 // +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
1936 +" onContextMenu=\"window.jambi.imageContextMenu(&." +tfile.fileName() +"&.);\""
\r
1939 browser.page().mainFrame().evaluateJavaScript(
\r
1940 script_start + buffer + script_end);
\r
1945 // Handle URLs that are trying to be pasted
\r
1946 public void handleUrls(QMimeData mime) {
\r
1947 logger.log(logger.EXTREME, "Starting handleUrls");
\r
1948 FileNameMap fileNameMap = URLConnection.getFileNameMap();
\r
1950 List<QUrl> urlList = mime.urls();
\r
1951 String url = new String();
\r
1952 String script_start = new String(
\r
1953 "document.execCommand('createLink', false, '");
\r
1954 String script_end = new String("');");
\r
1956 for (int i = 0; i < urlList.size(); i++) {
\r
1957 url = urlList.get(i).toString();
\r
1958 // Find out what type of file we have
\r
1959 String mimeType = fileNameMap.getContentTypeFor(url);
\r
1961 // If null returned, we need to guess at the file type
\r
1962 if (mimeType == null)
\r
1963 mimeType = "application/"
\r
1964 + url.substring(url.lastIndexOf(".") + 1);
\r
1966 // Check if we have an image or some other type of file
\r
1967 if (url.substring(0, 5).equalsIgnoreCase("file:")
\r
1968 && mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1969 handleLocalImageURLPaste(mime, mimeType);
\r
1972 String[] type = mimeType.split("/");
\r
1973 boolean valid = validAttachment(type[1]);
\r
1974 boolean smallEnough = checkFileAttachmentSize(url);
\r
1975 if (smallEnough && valid
\r
1976 && url.substring(0, 5).equalsIgnoreCase("file:")
\r
1977 && !mimeType.substring(0, 5).equalsIgnoreCase("image")) {
\r
1978 handleLocalAttachment(mime, mimeType);
\r
1981 browser.page().mainFrame().evaluateJavaScript(
\r
1982 script_start + url + script_end);
\r
1987 // If a URL being pasted is an image URL, then attach the image
\r
1988 private void handleLocalImageURLPaste(QMimeData mime, String mimeType) {
\r
1989 List<QUrl> urlList = mime.urls();
\r
1990 String url = new String();
\r
1991 String script_start_image = new String(
\r
1992 "document.execCommand('insertHtml', false, '");
\r
1993 String script_end = new String("');");
\r
1994 StringBuffer buffer;
\r
1996 // Copy the image over into the resource directory and create a new resource
\r
1997 // record for each url pasted
\r
1998 for (int i = 0; i < urlList.size(); i++) {
\r
1999 url = urlList.get(i).toString();
\r
2001 Resource newRes = createResource(url, i, mimeType, false);
\r
2002 if (newRes == null)
\r
2004 currentNote.getResources().add(newRes);
\r
2005 buffer = new StringBuffer(100);
\r
2007 // Open the file & write the data
\r
2008 String fileName = Global.getFileManager().getResDirPath(newRes.getGuid());
\r
2009 QFile tfile = new QFile(fileName);
\r
2010 tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
\r
2011 tfile.write(newRes.getData().getBody());
\r
2013 buffer.append(script_start_image);
\r
2014 buffer.append("<img src=\"" + FileUtils.toForwardSlashedPath(fileName));
\r
2015 // if (mimeType.equalsIgnoreCase("image/jpg"))
\r
2016 // mimeType = "image/jpeg";
\r
2017 buffer.append("\" en-tag=\"en-media\" type=\"" + mimeType +"\""
\r
2018 +" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\""
\r
2019 +" guid=\"" +newRes.getGuid() +"\""
\r
2020 +" onContextMenu=\"window.jambi.imageContextMenu('" +tfile.fileName() +"');\""
\r
2022 buffer.append(script_end);
\r
2023 browser.page().mainFrame().evaluateJavaScript(buffer.toString());
\r
2029 // If a URL being pasted is a local file URL, then attach the file
\r
2030 private void handleLocalAttachment(QMimeData mime, String mimeType) {
\r
2031 logger.log(logger.EXTREME, "Attaching local file");
\r
2032 List<QUrl> urlList = mime.urls();
\r
2033 String script_start = new String(
\r
2034 "document.execCommand('insertHtml', false, '");
\r
2035 String script_end = new String("');");
\r
2036 StringBuffer buffer;
\r
2038 String[] type = mimeType.split("/");
\r
2039 String icon = findIcon(type[1]);
\r
2040 if (icon.equals("attachment.png"))
\r
2041 icon = findIcon(type[0]);
\r
2042 buffer = new StringBuffer(100);
\r
2044 for (int i = 0; i < urlList.size(); i++) {
\r
2045 String url = urlList.get(i).toString();
\r
2047 // Start building the HTML
\r
2048 if (icon.equals("attachment.png"))
\r
2049 icon = findIcon(url.substring(url.lastIndexOf(".")+1));
\r
2050 String imageURL = FileUtils.toFileURLString(Global.getFileManager().getImageDirFile(icon));
\r
2052 logger.log(logger.EXTREME, "Creating resource ");
\r
2053 Resource newRes = createResource(url, i, mimeType, true);
\r
2054 if (newRes == null)
\r
2056 logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize());
\r
2057 currentNote.getResources().add(newRes);
\r
2059 String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName();
\r
2060 // If we have a PDF, we need to setup the preview.
\r
2061 if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) {
\r
2062 logger.log(logger.EXTREME, "Setting up PDF preview");
\r
2063 if (newRes.getAttributes() != null &&
\r
2064 newRes.getAttributes().getFileName() != null &&
\r
2065 !newRes.getAttributes().getFileName().trim().equals(""))
\r
2066 fileName = newRes.getGuid()+Global.attachmentNameDelimeter+
\r
2067 newRes.getAttributes().getFileName();
\r
2069 fileName = newRes.getGuid()+".pdf";
\r
2070 QFile file = new QFile(Global.getFileManager().getResDirPath(fileName));
\r
2071 QFile.OpenMode mode = new QFile.OpenMode();
\r
2072 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2074 QDataStream out = new QDataStream(file);
\r
2075 // Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(newRes.getGuid(), true);
\r
2076 QByteArray binData = new QByteArray(newRes.getData().getBody());
\r
2077 // resBinary = null;
\r
2078 out.writeBytes(binData.toByteArray());
\r
2081 PDFPreview pdfPreview = new PDFPreview();
\r
2082 if (pdfPreview.setupPreview(Global.getFileManager().getResDirPath(fileName), "pdf",0)) {
\r
2083 imageURL = file.fileName() + ".png";
\r
2087 logger.log(logger.EXTREME, "Generating link tags");
\r
2088 buffer.delete(0, buffer.length());
\r
2089 buffer.append("<a en-tag=\"en-media\" guid=\"" +newRes.getGuid()+"\" ");
\r
2090 buffer.append(" onContextMenu=\"window.jambi.imageContextMenu('")
\r
2091 .append(Global.getFileManager().getResDirPath(fileName))
\r
2092 .append("');\" "); buffer.append("type=\"" + mimeType + "\" href=\"nnres://" + fileName +"\" hash=\""+Global.byteArrayToHexString(newRes.getData().getBodyHash()) +"\" >");
\r
2093 buffer.append("<img src=\"" + imageURL + "\" title=\"" +newRes.getAttributes().getFileName());
\r
2094 buffer.append("\"></img>");
\r
2095 buffer.append("</a>");
\r
2096 browser.page().mainFrame().evaluateJavaScript(
\r
2097 script_start + buffer.toString() + script_end);
\r
2102 private Resource createResource(String url, int sequence, String mime, boolean attachment) {
\r
2103 logger.log(logger.EXTREME, "Inside create resource");
\r
2104 QFile resourceFile;
\r
2105 String urlTest = new QUrl(url).toLocalFile();
\r
2106 if (!urlTest.equals(""))
\r
2108 url = url.replace("/", File.separator);
\r
2109 resourceFile = new QFile(url);
\r
2110 resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly));
\r
2111 byte[] fileData = resourceFile.readAll().toByteArray();
\r
2112 resourceFile.close();
\r
2113 if (fileData.length == 0)
\r
2117 md = MessageDigest.getInstance("MD5");
\r
2118 md.update(fileData);
\r
2119 byte[] hash = md.digest();
\r
2121 Resource r = new Resource();
\r
2122 Calendar time = new GregorianCalendar();
\r
2123 long prevTime = time.getTimeInMillis();
\r
2124 while (prevTime == time.getTimeInMillis()) {
\r
2125 time = new GregorianCalendar();
\r
2127 r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString());
\r
2128 r.setNoteGuid(currentNote.getGuid());
\r
2130 r.setActive(true);
\r
2131 r.setUpdateSequenceNum(0);
\r
2132 r.setWidth((short) 0);
\r
2133 r.setHeight((short) 0);
\r
2134 r.setDuration((short) 0);
\r
2136 Data d = new Data();
\r
2137 d.setBody(fileData);
\r
2138 d.setBodyIsSet(true);
\r
2139 d.setBodyHash(hash);
\r
2140 d.setBodyHashIsSet(true);
\r
2142 d.setSize(fileData.length);
\r
2144 int fileNamePos = url.lastIndexOf(File.separator);
\r
2145 if (fileNamePos == -1)
\r
2146 fileNamePos = url.lastIndexOf("/");
\r
2147 String fileName = url.substring(fileNamePos+1);
\r
2148 ResourceAttributes a = new ResourceAttributes();
\r
2150 a.setAltitudeIsSet(false);
\r
2151 a.setLongitude(0);
\r
2152 a.setLongitudeIsSet(false);
\r
2154 a.setLatitudeIsSet(false);
\r
2155 a.setCameraMake("");
\r
2156 a.setCameraMakeIsSet(false);
\r
2157 a.setCameraModel("");
\r
2158 a.setCameraModelIsSet(false);
\r
2159 a.setAttachment(attachment);
\r
2160 a.setAttachmentIsSet(true);
\r
2161 a.setClientWillIndex(false);
\r
2162 a.setClientWillIndexIsSet(true);
\r
2163 a.setRecoType("");
\r
2164 a.setRecoTypeIsSet(false);
\r
2165 a.setSourceURL(url);
\r
2166 a.setSourceURLIsSet(true);
\r
2167 a.setTimestamp(0);
\r
2168 a.setTimestampIsSet(false);
\r
2169 a.setFileName(fileName);
\r
2170 a.setFileNameIsSet(true);
\r
2171 r.setAttributes(a);
\r
2173 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
2175 } catch (NoSuchAlgorithmException e1) {
\r
2176 e1.printStackTrace();
\r
2182 // find the appropriate icon for an attachment
\r
2183 private String findIcon(String appl) {
\r
2184 appl = appl.toLowerCase();
\r
2185 File f = Global.getFileManager().getImageDirFile(appl + ".png");
\r
2187 return appl+".png";
\r
2188 return "attachment.png";
\r
2191 // Check if the account supports this type of attachment
\r
2192 private boolean validAttachment(String type) {
\r
2193 if (Global.isPremium())
\r
2195 if (type.equalsIgnoreCase("JPG"))
\r
2197 if (type.equalsIgnoreCase("PNG"))
\r
2199 if (type.equalsIgnoreCase("GIF"))
\r
2201 if (type.equalsIgnoreCase("MP3"))
\r
2203 if (type.equalsIgnoreCase("WAV"))
\r
2205 if (type.equalsIgnoreCase("AMR"))
\r
2207 if (type.equalsIgnoreCase("PDF"))
\r
2209 String error = tr("Non-premium accounts can only attach JPG, PNG, GIF, MP3, WAV, AMR, or PDF files.");
\r
2210 QMessageBox.information(this, tr("Non-Premium Account"), error);
\r
2215 // Check the file attachment to be sure it isn't over 25 mb
\r
2216 private boolean checkFileAttachmentSize(String url) {
\r
2217 String fileName = url.substring(8);
\r
2218 QFile resourceFile = new QFile(fileName);
\r
2219 resourceFile.open(new QIODevice.OpenMode(
\r
2220 QIODevice.OpenModeFlag.ReadOnly));
\r
2221 long size = resourceFile.size();
\r
2222 resourceFile.close();
\r
2223 size = size / 1024 / 1024;
\r
2224 if (size < 50 && Global.isPremium())
\r
2229 String error = tr("A file attachment may not exceed 25MB.");
\r
2230 QMessageBox.information(this, tr("Attachment Size"), error);
\r
2235 @SuppressWarnings("unused")
\r
2236 private void createdChanged() {
\r
2237 QDateTime dt = new QDateTime();
\r
2238 dt.setDate(createdDate.date());
\r
2239 dt.setTime(createdTime.time());
\r
2240 noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt);
\r
2244 @SuppressWarnings("unused")
\r
2245 private void alteredChanged() {
\r
2246 QDateTime dt = new QDateTime();
\r
2247 dt.setDate(alteredDate.date());
\r
2248 dt.setTime(alteredTime.time());
\r
2249 noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt);
\r
2252 @SuppressWarnings("unused")
\r
2253 private void subjectDateTimeChanged() {
\r
2254 QDateTime dt = new QDateTime();
\r
2255 dt.setDate(subjectDate.date());
\r
2256 dt.setTime(subjectTime.time());
\r
2257 noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt);
\r
2261 @SuppressWarnings("unused")
\r
2262 private void sourceUrlChanged() {
\r
2263 noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text());
\r
2266 @SuppressWarnings("unused")
\r
2267 private void authorChanged() {
\r
2268 noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text());
\r
2271 @SuppressWarnings("unused")
\r
2272 private void geoBoxChanged() {
\r
2273 int index = geoBox.currentIndex();
\r
2274 geoBox.setCurrentIndex(0);
\r
2276 GeoDialog box = new GeoDialog();
\r
2277 box.setLongitude(currentNote.getAttributes().getLongitude());
\r
2278 box.setLatitude(currentNote.getAttributes().getLatitude());
\r
2279 box.setAltitude(currentNote.getAttributes().getAltitude());
\r
2281 if (!box.okPressed())
\r
2283 double alt = box.getAltitude();
\r
2284 double lat = box.getLatitude();
\r
2285 double lon = box.getLongitude();
\r
2286 if (alt != currentNote.getAttributes().getAltitude() ||
\r
2287 lon != currentNote.getAttributes().getLongitude() ||
\r
2288 lat != currentNote.getAttributes().getLatitude()) {
\r
2289 noteSignal.geoChanged.emit(currentNote.getGuid(), lon, lat, alt);
\r
2290 currentNote.getAttributes().setAltitude(alt);
\r
2291 currentNote.getAttributes().setLongitude(lon);
\r
2292 currentNote.getAttributes().setLatitude(lat);
\r
2297 noteSignal.geoChanged.emit(currentNote.getGuid(), 0.0, 0.0, 0.0);
\r
2298 currentNote.getAttributes().setAltitude(0.0);
\r
2299 currentNote.getAttributes().setLongitude(0.0);
\r
2300 currentNote.getAttributes().setLatitude(0.0);
\r
2303 if (index == 3 || index == 0) {
\r
2304 QDesktopServices.openUrl(new QUrl("http://maps.google.com/maps?z=6&q="+currentNote.getAttributes().getLatitude() +"," +currentNote.getAttributes().getLongitude()));
\r
2308 // ************************************************************
\r
2309 // * User chose to save an attachment. Pares out the request *
\r
2310 // * into a guid & file. Save the result. *
\r
2311 // ************************************************************
\r
2312 public void downloadAttachment(QNetworkRequest request) {
\r
2314 QFileDialog fd = new QFileDialog(this);
\r
2315 fd.setFileMode(FileMode.AnyFile);
\r
2316 fd.setConfirmOverwrite(true);
\r
2317 fd.setWindowTitle(tr("Save File"));
\r
2318 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2319 fd.setDirectory(System.getProperty("user.home"));
\r
2320 String name = request.url().toString();
\r
2322 int pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2324 guid = name.substring(0, pos).replace("nnres://", "");
\r
2325 name = name.substring(pos +Global.attachmentNameDelimeter.length());
\r
2326 fd.selectFile(name);
\r
2327 pos = name.lastIndexOf('.');
\r
2329 String mimeType = "(*." + name.substring(pos + 1)
\r
2330 + ");; All Files (*)";
\r
2331 fd.setFilter(tr(mimeType));
\r
2337 // Strip URL prefix and base dir
\r
2338 guid = guid.replace("nnres://", "")
\r
2339 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2340 guid = guid.replace("file://", "").replace("/", "")
\r
2341 .replace(FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()), "");
\r
2343 pos = guid.lastIndexOf('.');
\r
2345 guid = guid.substring(0,pos);
\r
2346 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2347 name = name.replace('\\', '/');
\r
2348 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2349 QFile saveFile = new QFile(fd.selectedFiles().get(0));
\r
2350 QFile.OpenMode mode = new QFile.OpenMode();
\r
2351 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2352 saveFile.open(mode);
\r
2353 QDataStream saveOut = new QDataStream(saveFile);
\r
2354 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2355 saveOut.writeBytes(binData.toByteArray());
\r
2362 // ************************************************************
\r
2363 // * User chose to save an attachment. Pares out the request *
\r
2364 // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!!
\r
2365 // ************************************************************
\r
2366 public void downloadImage(QNetworkRequest request) {
\r
2367 QFileDialog fd = new QFileDialog(this);
\r
2368 fd.setFileMode(FileMode.AnyFile);
\r
2369 fd.setConfirmOverwrite(true);
\r
2370 fd.setWindowTitle(tr("Save File"));
\r
2371 fd.setAcceptMode(AcceptMode.AcceptSave);
\r
2372 fd.setDirectory(System.getProperty("user.home"));
\r
2373 String name = request.url().toString();
\r
2374 name = name.replace("nnres://", "");
\r
2375 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
\r
2376 name = name.replace(dPath, "");
\r
2377 int pos = name.lastIndexOf('.');
\r
2378 String guid = name;
\r
2380 String mimeType = "(*." + name.substring(pos + 1)
\r
2381 + ");; All Files (*)";
\r
2382 fd.setFilter(tr(mimeType));
\r
2383 guid = guid.substring(0,pos);
\r
2385 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
\r
2387 guid = name.substring(0, pos);
\r
2388 fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length()));
\r
2390 if (fd.exec() != 0 && fd.selectedFiles().size() > 0) {
\r
2391 Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2392 String fileName = fd.selectedFiles().get(0);
\r
2393 QFile saveFile = new QFile(fileName);
\r
2394 QFile.OpenMode mode = new QFile.OpenMode();
\r
2395 mode.set(QFile.OpenModeFlag.WriteOnly);
\r
2396 saveFile.open(mode);
\r
2397 QDataStream saveOut = new QDataStream(saveFile);
\r
2398 QByteArray binData = new QByteArray(resBinary.getData().getBody());
\r
2399 saveOut.writeBytes(binData.toByteArray());
\r
2405 // *************************************************************
\r
2406 // * decrypt any hidden text. We could do an XML parse, but
\r
2407 // * it is quicker here just to scan for an <img tag & do the fix
\r
2408 // * the manual way
\r
2409 // *************************************************************
\r
2410 private void removeEncryption(String id, String plainText, boolean permanent, String slot) {
\r
2412 plainText = " <table class=\"en-crypt-temp\" slot=\""
\r
2415 +"border=1 width=100%><tbody><tr><td>"
\r
2416 +plainText+"</td></tr></tbody></table>";
\r
2419 String html = browser.page().mainFrame().toHtml();
\r
2420 String text = html;
\r
2421 int imagePos = html.indexOf("<img");
\r
2423 for ( ;imagePos>0; ) {
\r
2424 // Find the end tag
\r
2425 endPos = text.indexOf(">", imagePos);
\r
2426 String tag = text.substring(imagePos-1,endPos);
\r
2427 if (tag.indexOf("id=\""+id+"\"") > -1) {
\r
2428 text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);
\r
2429 QTextCodec codec = QTextCodec.codecForName("UTF-8");
\r
2430 QByteArray unicode = codec.fromUnicode(text);
\r
2431 browser.setContent(unicode);
\r
2435 imagePos = text.indexOf("<img", imagePos+1);
\r
2440 //****************************************************************
\r
2441 //* Focus shortcuts
\r
2442 //****************************************************************
\r
2443 @SuppressWarnings("unused")
\r
2444 private void focusTitle() {
\r
2445 titleLabel.setFocus();
\r
2447 @SuppressWarnings("unused")
\r
2448 private void focusTag() {
\r
2449 tagEdit.setFocus();
\r
2451 @SuppressWarnings("unused")
\r
2452 private void focusNote() {
\r
2453 browser.setFocus();
\r
2455 @SuppressWarnings("unused")
\r
2456 private void focusAuthor() {
\r
2457 authorLabel.setFocus();
\r
2459 @SuppressWarnings("unused")
\r
2460 private void focusUrl() {
\r
2461 urlLabel.setFocus();
\r
2465 //*****************************************************************
\r
2466 //* Set the document background color
\r
2467 //*****************************************************************
\r
2468 public void setBackgroundColor(String color) {
\r
2469 String js = "function changeBackground(color) {"
\r
2470 +"document.body.style.background = color;"
\r
2472 +"changeBackground('" +color+"');";
\r
2473 browser.page().mainFrame().evaluateJavaScript(js);
\r
2478 //****************************************************************
\r
2479 //* MicroFocus changed
\r
2480 //****************************************************************
\r
2481 private void microFocusChanged() {
\r
2482 boldButton.setDown(false);
\r
2483 italicButton.setDown(false);
\r
2484 underlineButton.setDown(false);
\r
2485 browser.openAction.setEnabled(false);
\r
2486 browser.downloadAttachment.setEnabled(false);
\r
2487 browser.downloadImage.setEnabled(false);
\r
2488 browser.rotateImageLeft.setEnabled(false);
\r
2489 browser.rotateImageRight.setEnabled(false);
\r
2490 browser.insertTableAction.setEnabled(true);
\r
2491 browser.deleteTableColumnAction.setEnabled(false);
\r
2492 browser.insertTableRowAction.setEnabled(false);
\r
2493 browser.insertTableColumnAction.setEnabled(false);
\r
2494 browser.deleteTableRowAction.setEnabled(false);
\r
2495 browser.insertLinkAction.setText(tr("Insert Hyperlink"));
\r
2496 insertHyperlink = true;
\r
2497 currentHyperlink ="";
\r
2498 insideList = false;
\r
2499 insideTable = false;
\r
2500 insideEncryption = false;
\r
2501 forceTextPaste = false;
\r
2503 String js = new String( "function getCursorPos() {"
\r
2505 +"if (window.getSelection) {"
\r
2506 +" var selObj = window.getSelection();"
\r
2507 +" var selRange = selObj.getRangeAt(0);"
\r
2508 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2509 +" while(workingNode != null) { "
\r
2510 // +" window.jambi.printNode(workingNode.nodeName);"
\r
2511 +" if (workingNode.nodeName=='TABLE') { if (workingNode.getAttribute('class').toLowerCase() == 'en-crypt-temp') window.jambi.insideEncryption(); }"
\r
2512 +" if (workingNode.nodeName=='B') window.jambi.boldActive();"
\r
2513 +" if (workingNode.nodeName=='I') window.jambi.italicActive();"
\r
2514 +" if (workingNode.nodeName=='U') window.jambi.underlineActive();"
\r
2515 +" if (workingNode.nodeName=='UL') window.jambi.setInsideList();"
\r
2516 +" if (workingNode.nodeName=='OL') window.jambi.setInsideList();"
\r
2517 +" if (workingNode.nodeName=='LI') window.jambi.setInsideList();"
\r
2518 +" if (workingNode.nodeName=='TBODY') window.jambi.setInsideTable();"
\r
2519 +" 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
2520 +" if (workingNode.nodeName=='SPAN') {"
\r
2521 +" if (workingNode.getAttribute('style') == 'text-decoration: underline;') window.jambi.underlineActive();"
\r
2523 +" workingNode = workingNode.parentNode;"
\r
2526 +"} getCursorPos();");
\r
2527 browser.page().mainFrame().evaluateJavaScript(js);
\r
2530 public void printNode(String n) {
\r
2531 System.out.println("Node Vaule: " +n);
\r
2534 public void insideEncryption() {
\r
2535 insideEncryption = true;
\r
2539 //****************************************************************
\r
2540 //* Insert a table row
\r
2541 //****************************************************************
\r
2542 public void insertTableRow() {
\r
2544 String js = new String( "function insertTableRow() {"
\r
2545 +" var selObj = window.getSelection();"
\r
2546 +" var selRange = selObj.getRangeAt(0);"
\r
2547 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2548 +" var cellCount = 0;"
\r
2549 +" while(workingNode != null) { "
\r
2550 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2551 +" row = document.createElement('TR');"
\r
2552 +" var nodes = workingNode.getElementsByTagName('td');"
\r
2553 +" for (j=0; j<nodes.length; j=j+1) {"
\r
2554 +" cell = document.createElement('TD');"
\r
2555 +" cell.innerHTML=' ';"
\r
2556 +" row.appendChild(cell);"
\r
2558 +" workingNode.parentNode.insertBefore(row,workingNode.nextSibling);"
\r
2561 +" workingNode = workingNode.parentNode;"
\r
2563 +"} insertTableRow();");
\r
2564 browser.page().mainFrame().evaluateJavaScript(js);
\r
2568 public void insertTableColumn() {
\r
2569 String js = new String( "function insertTableColumn() {"
\r
2570 +" var selObj = window.getSelection();"
\r
2571 +" var selRange = selObj.getRangeAt(0);"
\r
2572 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2573 +" var current = 0;"
\r
2574 +" while (workingNode.nodeName.toLowerCase() != 'table' && workingNode != null) {"
\r
2575 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
2576 +" var td = workingNode;"
\r
2577 +" while (td.previousSibling != null) { "
\r
2578 +" current = current+1; td = td.previousSibling;"
\r
2581 +" workingNode = workingNode.parentNode; "
\r
2583 +" if (workingNode == null) return;"
\r
2584 +" for (var i=0; i<workingNode.rows.length; i++) { "
\r
2585 +" var cell = workingNode.rows[i].insertCell(current+1); "
\r
2586 +" cell.innerHTML = ' '; "
\r
2588 +"} insertTableColumn();");
\r
2589 browser.page().mainFrame().evaluateJavaScript(js);
\r
2593 //****************************************************************
\r
2594 //* Delete a table row
\r
2595 //****************************************************************
\r
2596 public void deleteTableRow() {
\r
2598 String js = new String( "function deleteTableRow() {"
\r
2599 +" var selObj = window.getSelection();"
\r
2600 +" var selRange = selObj.getRangeAt(0);"
\r
2601 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2602 +" var cellCount = 0;"
\r
2603 +" while(workingNode != null) { "
\r
2604 +" if (workingNode.nodeName.toLowerCase()=='tr') {"
\r
2605 +" workingNode.parentNode.removeChild(workingNode);"
\r
2608 +" workingNode = workingNode.parentNode;"
\r
2610 +"} deleteTableRow();");
\r
2611 browser.page().mainFrame().evaluateJavaScript(js);
\r
2615 public void deleteTableColumn() {
\r
2616 String js = new String( "function deleteTableColumn() {"
\r
2617 +" var selObj = window.getSelection();"
\r
2618 +" var selRange = selObj.getRangeAt(0);"
\r
2619 +" var workingNode = window.getSelection().anchorNode.parentNode;"
\r
2620 +" var current = 0;"
\r
2621 +" while (workingNode.nodeName.toLowerCase() != 'table' && workingNode != null) {"
\r
2622 +" if (workingNode.nodeName.toLowerCase() == 'td') {"
\r
2623 +" var td = workingNode;"
\r
2624 +" while (td.previousSibling != null) { "
\r
2625 +" current = current+1; td = td.previousSibling;"
\r
2628 +" workingNode = workingNode.parentNode; "
\r
2630 +" if (workingNode == null) return;"
\r
2631 +" for (var i=0; i<workingNode.rows.length; i++) { "
\r
2632 +" workingNode.rows[i].deleteCell(current); "
\r
2634 +"} deleteTableColumn();");
\r
2635 browser.page().mainFrame().evaluateJavaScript(js);
\r
2640 public void setInsideTable() {
\r
2641 browser.insertTableRowAction.setEnabled(true);
\r
2642 browser.insertTableColumnAction.setEnabled(true);
\r
2643 browser.deleteTableRowAction.setEnabled(true);
\r
2644 browser.deleteTableColumnAction.setEnabled(true);
\r
2645 browser.insertTableAction.setEnabled(false);
\r
2646 browser.encryptAction.setEnabled(false);
\r
2647 insideTable = true;
\r
2650 public void setInsideLink(String link) {
\r
2651 browser.insertLinkAction.setText(tr("Edit Hyperlink"));
\r
2652 currentHyperlink = link;
\r
2653 insertHyperlink = false;
\r
2656 public void italicActive() {
\r
2657 italicButton.setDown(true);
\r
2659 public void boldActive() {
\r
2660 boldButton.setDown(true);
\r
2662 public void underlineActive() {
\r
2663 underlineButton.setDown(true);
\r
2665 public void forceTextPaste() {
\r
2666 forceTextPaste = true;
\r
2668 public void imageContextMenu(String f) {
\r
2669 browser.downloadImage.setEnabled(true);
\r
2670 browser.rotateImageRight.setEnabled(true);
\r
2671 browser.rotateImageLeft.setEnabled(true);
\r
2672 browser.openAction.setEnabled(true);
\r
2675 public void rotateImageRight() {
\r
2676 QWebSettings.setMaximumPagesInCache(0);
\r
2677 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2678 QImage image = new QImage(selectedFile);
\r
2679 QMatrix matrix = new QMatrix();
\r
2680 matrix.rotate( 90.0 );
\r
2681 image = image.transformed(matrix);
\r
2682 image.save(selectedFile);
\r
2683 QWebSettings.setMaximumPagesInCache(0);
\r
2684 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2685 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2688 // resourceSignal.contentChanged.emit(selectedFile);
\r
2691 public void rotateImageLeft() {
\r
2692 QImage image = new QImage(selectedFile);
\r
2693 QMatrix matrix = new QMatrix();
\r
2694 matrix.rotate( -90.0 );
\r
2695 image = image.transformed(matrix);
\r
2696 image.save(selectedFile);
\r
2697 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2700 // resourceSignal.contentChanged.emit(selectedFile);
\r
2702 public void resourceContextMenu(String f) {
\r
2703 browser.downloadAttachment.setEnabled(true);
\r
2704 browser.openAction.setEnabled(true);
\r
2709 //****************************************************************
\r
2710 //* Apply CSS style to specified word
\r
2711 //****************************************************************
\r
2712 /* public void applyStyleToWords(String word, String style) {
\r
2713 QFile script = new QFile("D:\\NeverNote\\js\\hilight1.js");
\r
2714 script.open(OpenModeFlag.ReadOnly);
\r
2715 String s = script.readAll().toString();
\r
2716 String js = new String(s +" findit('"+word+"', '"+style+"');");
\r
2717 browser.page().mainFrame().evaluateJavaScript(js);
\r
2718 System.out.println(getContent());
\r
2721 //****************************************************************
\r
2722 //* Someone tried to paste a resource between notes, so we need *
\r
2723 //* to do some special handling. *
\r
2724 //****************************************************************
\r
2725 private String fixInternotePaste(String text) {
\r
2726 logger.log(logger.EXTREME, "Fixing internote paste");
\r
2727 String returnValue = fixInternotePasteSearch(text, "<img", "src=\"");
\r
2728 return fixInternotePasteSearch(returnValue, "<a", "href=\"nnres://");
\r
2730 private String fixInternotePasteSearch(String text, String type, String locTag) {
\r
2732 // First, let's fix the images.
\r
2733 int startPos = text.indexOf(type);
\r
2735 for (; startPos>=0;) {
\r
2736 endPos = text.indexOf(">", startPos+1);
\r
2737 String segment = text.substring(startPos, endPos);
\r
2738 if (segment.indexOf("en-tag") > -1) {
\r
2739 String newSegment = segment;
\r
2741 int guidStartPos = segment.indexOf("guid=\"");
\r
2742 int guidEndPos = segment.indexOf("\"", guidStartPos+7);
\r
2743 String guid = segment.substring(guidStartPos+6,guidEndPos);
\r
2745 int mimeStartPos = segment.indexOf("type");
\r
2746 int mimeEndPos = segment.indexOf("\"", mimeStartPos+7);
\r
2747 String mime = segment.substring(mimeStartPos+6,mimeEndPos);
\r
2749 int srcStartPos = segment.indexOf("src");
\r
2750 int srcEndPos = segment.indexOf("\"", srcStartPos+6);
\r
2751 String src = segment.substring(srcStartPos+5,srcEndPos);
\r
2753 Calendar currentTime = new GregorianCalendar();
\r
2754 Long l = new Long(currentTime.getTimeInMillis());
\r
2755 long prevTime = l;
\r
2756 while (l==prevTime) {
\r
2757 currentTime = new GregorianCalendar();
\r
2758 l= new Long(currentTime.getTimeInMillis());
\r
2761 Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
\r
2762 // if r==null, then the image doesn't exist (it was probably cut out of another note, so
\r
2763 // we need to recereate it
\r
2765 r = createResource(src, 1, mime, false);
\r
2769 String randint = new String(Long.toString(l));
\r
2770 String extension = null;
\r
2771 if (r.getMime()!= null) {
\r
2772 extension = r.getMime().toLowerCase();
\r
2773 if (extension.indexOf("/")>-1)
\r
2774 extension = extension.substring(extension.indexOf("/")+1);
\r
2776 String newFile = randint;
\r
2777 if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "")
\r
2778 if (!locTag.startsWith("src"))
\r
2779 newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName();
\r
2780 r.setNoteGuid(currentNote.getGuid());
\r
2782 r.setGuid(randint);
\r
2783 conn.getNoteTable().noteResourceTable.saveNoteResource(r, true);
\r
2784 QFile f = new QFile(Global.getFileManager().getResDirPath(newFile));
\r
2785 QByteArray bin = new QByteArray(r.getData().getBody());
\r
2786 f.open(QFile.OpenModeFlag.WriteOnly);
\r
2789 newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint);
\r
2790 currentNote.getResources().add(r);
\r
2792 int startSrcPos = newSegment.indexOf(locTag);
\r
2793 int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1);
\r
2795 if (locTag.startsWith("src")) {
\r
2796 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2797 newSegment = newSegment.replace(source,
\r
2798 FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath(newFile)));
\r
2800 source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos);
\r
2801 newSegment = newSegment.replace(source, newFile);
\r
2804 text = text.substring(0,startPos) + newSegment + text.substring(endPos);
\r
2806 startPos = text.indexOf(type, startPos+1);
\r
2812 public void nextPage(String file) {
\r
2813 logger.log(logger.EXTREME, "Starting nextPage()");
\r
2815 Integer pageNumber;
\r
2816 if (previewPageList.containsKey(file))
\r
2817 pageNumber = previewPageList.get(file)+1;
\r
2820 previewPageList.remove(file);
\r
2821 previewPageList.put(file, pageNumber);
\r
2822 PDFPreview pdfPreview = new PDFPreview();
\r
2823 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2824 if (goodPreview) {
\r
2826 // String html = getContent();
\r
2827 QWebSettings.setMaximumPagesInCache(0);
\r
2828 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2829 // browser.setContent(new QByteArray());
\r
2830 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2832 // browser.setContent(new QByteArray(html));
\r
2833 // browser.triggerPageAction(WebAction.Reload);
\r
2834 // pdfMouseOver(selectedFile);
\r
2838 public void previousPage(String file) {
\r
2839 logger.log(logger.EXTREME, "Starting previousPage()");
\r
2841 Integer pageNumber;
\r
2842 if (previewPageList.containsKey(file))
\r
2843 pageNumber = previewPageList.get(file)-1;
\r
2846 previewPageList.remove(file);
\r
2847 previewPageList.put(file, pageNumber);
\r
2848 PDFPreview pdfPreview = new PDFPreview();
\r
2849 boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber);
\r
2850 if (goodPreview) {
\r
2852 // String html = getContent();
\r
2853 QWebSettings.setMaximumPagesInCache(0);
\r
2854 QWebSettings.setObjectCacheCapacities(0, 0, 0);
\r
2855 browser.setHtml(browser.page().mainFrame().toHtml());
\r
2857 // browser.setContent(new QByteArray(html));
\r
2858 // browser.triggerPageAction(WebAction.Reload);
\r
2862 /* public void pdfMouseOver(String name) {
\r
2864 if (previewPageList.containsKey(selectedFile))
\r
2865 pageNumber = previewPageList.get(selectedFile)+1;
\r
2869 if (pageNumber <= 1)
\r
2870 browser.previousPageAction.setEnabled(false);
\r
2872 browser.previousPageAction.setEnabled(true);
\r
2874 PDFPreview pdf = new PDFPreview();
\r
2875 int totalPages = pdf.getPageCount(name);
\r
2876 if (previewPageList.containsKey(selectedFile))
\r
2877 pageNumber = previewPageList.get(selectedFile)+1;
\r
2880 if (totalPages > pageNumber)
\r
2881 browser.nextPageAction.setEnabled(true);
\r
2883 browser.nextPageAction.setEnabled(false);
\r
2887 public void pdfMouseOut() {
\r
2888 // browser.nextPageAction.setVisible(false);
\r
2889 // browser.previousPageAction.setVisible(false);
\r
2893 @SuppressWarnings("unused")
\r
2894 private void toggleUndoVisible(Boolean toggle) {
\r
2895 undoAction.setVisible(toggle);
\r
2896 Global.saveEditorButtonsVisible("undo", toggle);
\r
2898 @SuppressWarnings("unused")
\r
2899 private void toggleRedoVisible(Boolean toggle) {
\r
2900 redoAction.setVisible(toggle);
\r
2901 Global.saveEditorButtonsVisible("redo", toggle);
\r
2903 @SuppressWarnings("unused")
\r
2904 private void toggleCutVisible(Boolean toggle) {
\r
2905 cutAction.setVisible(toggle);
\r
2906 Global.saveEditorButtonsVisible("cut", toggle);
\r
2908 @SuppressWarnings("unused")
\r
2909 private void toggleCopyVisible(Boolean toggle) {
\r
2910 copyAction.setVisible(toggle);
\r
2911 Global.saveEditorButtonsVisible("copy", toggle);
\r
2913 @SuppressWarnings("unused")
\r
2914 private void togglePasteVisible(Boolean toggle) {
\r
2915 pasteAction.setVisible(toggle);
\r
2916 Global.saveEditorButtonsVisible("paste", toggle);
\r
2918 @SuppressWarnings("unused")
\r
2919 private void toggleBoldVisible(Boolean toggle) {
\r
2920 boldAction.setVisible(toggle);
\r
2921 Global.saveEditorButtonsVisible("bold", toggle);
\r
2923 @SuppressWarnings("unused")
\r
2924 private void toggleItalicVisible(Boolean toggle) {
\r
2925 italicAction.setVisible(toggle);
\r
2926 Global.saveEditorButtonsVisible("italic", toggle);
\r
2928 @SuppressWarnings("unused")
\r
2929 private void toggleUnderlineVisible(Boolean toggle) {
\r
2930 underlineAction.setVisible(toggle);
\r
2931 Global.saveEditorButtonsVisible("underline", toggle);
\r
2933 @SuppressWarnings("unused")
\r
2934 private void toggleStrikethroughVisible(Boolean toggle) {
\r
2935 strikethroughAction.setVisible(toggle);
\r
2936 Global.saveEditorButtonsVisible("strikethrough", toggle);
\r
2938 @SuppressWarnings("unused")
\r
2939 private void toggleLeftAlignVisible(Boolean toggle) {
\r
2940 leftAlignAction.setVisible(toggle);
\r
2941 Global.saveEditorButtonsVisible("alignLeft", toggle);
\r
2943 @SuppressWarnings("unused")
\r
2944 private void toggleRightAlignVisible(Boolean toggle) {
\r
2945 rightAlignAction.setVisible(toggle);
\r
2946 Global.saveEditorButtonsVisible("alignRight", toggle);
\r
2948 @SuppressWarnings("unused")
\r
2949 private void toggleCenterAlignVisible(Boolean toggle) {
\r
2950 centerAlignAction.setVisible(toggle);
\r
2951 Global.saveEditorButtonsVisible("alignCenter", toggle);
\r
2953 @SuppressWarnings("unused")
\r
2954 private void toggleHLineVisible(Boolean toggle) {
\r
2955 hlineAction.setVisible(toggle);
\r
2956 Global.saveEditorButtonsVisible("hline", toggle);
\r
2958 @SuppressWarnings("unused")
\r
2959 private void toggleIndentVisible(Boolean toggle) {
\r
2960 indentAction.setVisible(toggle);
\r
2961 Global.saveEditorButtonsVisible("indent", toggle);
\r
2963 @SuppressWarnings("unused")
\r
2964 private void toggleTodoVisible(Boolean toggle) {
\r
2965 todoAction.setVisible(toggle);
\r
2966 Global.saveEditorButtonsVisible("todo", toggle);
\r
2968 @SuppressWarnings("unused")
\r
2969 private void toggleOutdentVisible(Boolean toggle) {
\r
2970 outdentAction.setVisible(toggle);
\r
2971 Global.saveEditorButtonsVisible("outdent", toggle);
\r
2973 @SuppressWarnings("unused")
\r
2974 private void toggleBulletListVisible(Boolean toggle) {
\r
2975 bulletListAction.setVisible(toggle);
\r
2976 Global.saveEditorButtonsVisible("bulletList", toggle);
\r
2978 @SuppressWarnings("unused")
\r
2979 private void toggleNumberListVisible(Boolean toggle) {
\r
2980 numberListAction.setVisible(toggle);
\r
2981 Global.saveEditorButtonsVisible("numberList", toggle);
\r
2983 @SuppressWarnings("unused")
\r
2984 private void toggleFontListVisible(Boolean toggle) {
\r
2985 fontListAction.setVisible(toggle);
\r
2986 Global.saveEditorButtonsVisible("font", toggle);
\r
2988 @SuppressWarnings("unused")
\r
2989 private void toggleFontColorVisible(Boolean toggle) {
\r
2990 fontColorAction.setVisible(toggle);
\r
2991 Global.saveEditorButtonsVisible("fontColor", toggle);
\r
2993 @SuppressWarnings("unused")
\r
2994 private void toggleFontSizeVisible(Boolean toggle) {
\r
2995 fontSizeAction.setVisible(toggle);
\r
2996 Global.saveEditorButtonsVisible("fontSize", toggle);
\r
2998 @SuppressWarnings("unused")
\r
2999 private void toggleFontHilightVisible(Boolean toggle) {
\r
3000 fontHilightAction.setVisible(toggle);
\r
3001 Global.saveEditorButtonsVisible("fontHilight", toggle);
\r
3003 @SuppressWarnings("unused")
\r
3004 private void toggleSpellCheckVisible(Boolean toggle) {
\r
3005 spellCheckAction.setVisible(toggle);
\r
3006 Global.saveEditorButtonsVisible("spellCheck", toggle);
\r
3010 private void setupDictionary() {
\r
3011 File wordList = new File(Global.getFileManager().getSpellDirPath()+Locale.getDefault()+".dic");
\r
3013 dictionary = new SpellDictionaryHashMap(wordList);
\r
3014 spellChecker = new SpellChecker(dictionary);
\r
3016 File userWordList;
\r
3017 userWordList = new File(Global.getFileManager().getSpellDirPathUser()+"user.dic");
\r
3019 // Get the local user spell dictionary
\r
3021 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
3022 } catch (FileNotFoundException e) {
\r
3023 userWordList.createNewFile();
\r
3024 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
3025 } catch (IOException e) {
\r
3026 userWordList.createNewFile();
\r
3027 userDictionary = new SpellDictionaryHashMap(userWordList);
\r
3030 spellListener = new SuggestionListener(this, spellChecker);
\r
3032 // Add the user dictionary
\r
3033 spellChecker.addSpellCheckListener(spellListener);
\r
3034 spellChecker.setUserDictionary(userDictionary);
\r
3036 } catch (FileNotFoundException e) {
\r
3037 QMessageBox.critical(this, tr("Spell Check Error"),
\r
3038 tr("Dictionary "+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
3039 ".dic was not found."));
\r
3040 } catch (IOException e) {
\r
3041 QMessageBox.critical(this, tr("Spell Check Error"),
\r
3042 tr("Dictionary "+ Global.getFileManager().getSpellDirPath()+Locale.getDefault()+
\r
3043 ".dic is invalid."));
\r
3048 // Invoke spell checker dialog
\r
3049 @SuppressWarnings("unused")
\r
3050 private void spellCheckClicked() {
\r
3052 if (spellChecker == null) {
\r
3053 setupDictionary();
\r
3056 // Read user settings
\r
3057 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREDIGITWORDS,
\r
3058 Global.getSpellSetting(Configuration.SPELL_IGNOREDIGITWORDS));
\r
3059 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREINTERNETADDRESSES,
\r
3060 Global.getSpellSetting(Configuration.SPELL_IGNOREINTERNETADDRESSES));
\r
3061 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREMIXEDCASE,
\r
3062 Global.getSpellSetting(Configuration.SPELL_IGNOREMIXEDCASE));
\r
3063 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNOREUPPERCASE,
\r
3064 Global.getSpellSetting(Configuration.SPELL_IGNOREUPPERCASE));
\r
3065 spellChecker.getConfiguration().setBoolean(Configuration.SPELL_IGNORESENTENCECAPITALIZATION,
\r
3066 Global.getSpellSetting(Configuration.SPELL_IGNORESENTENCECAPITALIZATION));
\r
3068 spellListener.abortSpellCheck = false;
\r
3069 spellListener.errorsFound = false;
\r
3070 String content = getBrowser().page().mainFrame().toPlainText();
\r
3071 StringWordTokenizer tokenizer = new StringWordTokenizer(content);
\r
3072 if (!tokenizer.hasMoreWords())
\r
3074 getBrowser().page().action(WebAction.MoveToStartOfDocument);
\r
3076 getBrowser().setFocus();
\r
3079 // Move to the start of page
\r
3080 KeyboardModifiers ctrl = new KeyboardModifiers(KeyboardModifier.ControlModifier.value());
\r
3081 QKeyEvent home = new QKeyEvent(Type.KeyPress, Key.Key_Home.value(), ctrl);
\r
3082 browser.keyPressEvent(home);
\r
3083 getBrowser().setFocus();
\r
3085 tokenizer = new StringWordTokenizer(content);
\r
3088 while(tokenizer.hasMoreWords()) {
\r
3089 word = tokenizer.nextWord();
\r
3090 found = getBrowser().page().findText(word);
\r
3091 if (found && !spellListener.abortSpellCheck) {
\r
3092 spellChecker.checkSpelling(new StringWordTokenizer(word));
\r
3093 getBrowser().setFocus();
\r
3097 // Go to the end of the document & finish up.
\r
3098 home = new QKeyEvent(Type.KeyPress, Key.Key_End.value(), ctrl);
\r
3099 browser.keyPressEvent(home);
\r
3100 if (!spellListener.errorsFound)
\r
3101 QMessageBox.information(this, tr("Spell Check Complete"),
\r
3102 tr("No Errors Found"));
\r