- Notes can now be edited in a separate window by double clicking it from the list.
- You can specify a default font & size for new notes.
- Added additional time & date formats.
- Added an "All Notes" button to the button bar.
- The default notebook can now be changed (although there still isn't a visual indicator on which is the default notebook).
- You can now move the note list to be between the note editor and the left hand items (notebook, tags, etc). This is by request for wider screens to improve space usage.
- Images are now limited to the maximum width of the window to make viewing easier.
- Added a popup to give an error if NeverNote can't connect to the database because another process is using it.
- Corrected a bug in the save note process that could result in the save thread to crash.
- Corrected numerous issues with encrypting & decrypting text in notes.
- Corrected note import where resources could be lost.
- Corrected an error where note columns would be resized back to the startup values after entering preferences.
- Corrected error when editing a note with a PDF where the PDF could be lost when doing a PDF preview and editing the content.
- Corrected an issue where the online note history may not work due to a null pointer.
- Corrected problem where changing the note status wasn't displayed properly.
- Corrected where threads may not terminate in a timely manor during shutdown.
- Corrected a bug where the note title wasn't being displayed as unsynchronized properly when updated.
-/* empty stylesheet */
+/* Default stylesheet */
+
+ QTreeView::branch:has-siblings:!adjoins-item {
+ border-image: url(qss/vline.png) 0;
+ }
+
+ QTreeView::branch:has-siblings:adjoins-item {
+ border-image: url(qss/branch-more.png) 0;
+ }
+
+
+ QTreeView::branch:!has-children:!has-siblings:adjoins-item {
+ border-image: url(qss/branch-end.png) 0;
+ }
+
+ QTreeView::branch:has-children:!has-siblings:closed,
+ QTreeView::branch:closed:has-children:has-siblings {
+ border-image: none;
+ image: url(qss/branch-closed.png);
+ }
+
+ QTreeView::branch:open:has-children:!has-siblings,
+ QTreeView::branch:open:has-children:has-siblings {
+ border-image: none;
+ image: url(qss/branch-open.png);
+ }
+ QTreeView::item {
+ padding: 1px 1px 1px 1px;
+ }
+
+ QTreeView[hideTree="true"]::branch:!has-chlidren:hasSiblings {
+ border-image: none;
+ image: none;
+ }
+
+
+
+/*
+ QProgressBar {
+ border: 1px solid gray;
+ border-radius: 1em ;
+ text-align: center;
+ padding: 2px;
+ }
+*/
+
+QProgressBar {
+ text-align: center;
+}
+
+QSpinBox {
+ padding-right: 15px; /* make room for the arrows */
+ border-width: 3;
+ text-align: center;
+ }
\ No newline at end of file
import com.swabunga.spell.engine.Configuration;\r
import com.trolltech.qt.core.QByteArray;\r
import com.trolltech.qt.core.QSettings;\r
+import com.trolltech.qt.core.QSize;\r
import com.trolltech.qt.gui.QPalette;\r
\r
import cx.fbn.nevernote.config.FileManager;\r
import cx.fbn.nevernote.gui.DateAttributeFilterTable;\r
import cx.fbn.nevernote.gui.ShortcutKeys;\r
import cx.fbn.nevernote.utilities.ApplicationLogger;\r
+import cx.fbn.nevernote.utilities.Pair;\r
\r
public class Global {\r
- public static String version = "0.92.1";\r
+ public static String version = "0.94";\r
public static String username = ""; \r
public static String password = ""; \r
\r
\r
public static final int mainThreadId=0;\r
- \r
public static final int syncThreadId=1;\r
- \r
public static final int tagCounterThreadId=2;\r
- \r
public static final int trashCounterThreadId=3; // This should always be the highest thread ID\r
-\r
public static final int indexThreadId=4; // Thread for indexing words\r
-\r
public static final int saveThreadId=5; // Thread used for processing data to saving content\r
-\r
public static final int notebookCounterThreadId=6; // Notebook Thread\r
-\r
public static final int indexThread03Id=7; // unused\r
-\r
public static final int indexThread04Id=8; // unused\r
- \r
public static final int dbThreadId=9; // This should always be the highest thread ID\r
\r
\r
- public static HashMap<String,String> passwordSafe = new HashMap<String, String>();\r
- public static List<String> passwordRemember = new ArrayList<String>();\r
+ public static int View_List_Wide = 1;\r
+ public static int View_List_Narrow = 2;\r
+ public static QSize smallThumbnailSize = new QSize(50,50);\r
+ public static QSize largeThumbnailSize = new QSize(160,160);\r
+ public static boolean listView = true;\r
+ \r
+ public static HashMap<String,Pair> passwordSafe = new HashMap<String, Pair>();\r
+ public static List<Pair<String,String>> passwordRemember = new ArrayList<Pair<String,String>>();\r
public static String currentNotebookGuid;\r
public static User user; \r
public static long authTimeRemaining;\r
public static int noteTableSourceUrlPosition = 7;\r
public static int noteTableSubjectDatePosition = 8;\r
public static int noteTableSynchronizedPosition = 9;\r
- public static int noteTableColumnCount = 10;\r
+ public static int noteTableThumbnailPosition = 10;\r
+ public static int noteTableColumnCount = 11;\r
public static Integer cryptCounter = 0;\r
\r
public static int minimumWordCount = 2;\r
settings.endGroup();\r
}\r
public static boolean isColumnVisible(String window) {\r
+ String defaultValue = "true";\r
settings.beginGroup("ColumnsVisible");\r
- String text = (String)settings.value(window, "true");\r
+ if (window.equalsIgnoreCase("thumbnail"))\r
+ defaultValue = "false";\r
+ if (window.equalsIgnoreCase("Guid"))\r
+ defaultValue = "false";\r
+ String text = (String)settings.value(window, defaultValue);\r
settings.endGroup();\r
if (text.equalsIgnoreCase("true"))\r
return true;\r
try {\r
value = (Integer)settings.value("autoSaveInterval", 5);\r
} catch (Exception e1) {\r
- value = 0;\r
+ value = 5;\r
}\r
}\r
settings.endGroup();\r
public static boolean getDisableViewing() {\r
return disableViewing;\r
}\r
+\r
+ \r
+ //**********************\r
+ //* List View settings \r
+ //**********************\r
+ public static void setListView(int view) {\r
+ settings.beginGroup("General");\r
+ settings.setValue("listView", view);\r
+ settings.endGroup();\r
+ }\r
+ public static int getListView() {\r
+ settings.beginGroup("General");\r
+ Integer value;\r
+ try {\r
+ String val = (String)settings.value("listView", View_List_Wide);\r
+ value = new Integer(val.trim());\r
+ } catch (Exception e) {\r
+ try {\r
+ value = (Integer)settings.value("listView", View_List_Wide);\r
+ } catch (Exception e1) {\r
+ value = View_List_Wide;\r
+ }\r
+ }\r
+ settings.endGroup();\r
+ return value;\r
+ }\r
+\r
+ \r
+ \r
+ //*******************\r
+ // Font Settings\r
+ //*******************\r
+ public static boolean overrideDefaultFont() {\r
+ settings.beginGroup("Font");\r
+ String text = (String)settings.value("overrideFont", "false");\r
+ settings.endGroup();\r
+ if (text.equalsIgnoreCase("true"))\r
+ return true;\r
+ else\r
+ return false; \r
+ }\r
+ public static void setOverrideDefaultFont(boolean value) {\r
+ settings.beginGroup("Font");\r
+ settings.setValue("overrideFont", value);\r
+ settings.endGroup(); \r
+ }\r
+ public static String getDefaultFont() {\r
+ settings.beginGroup("Font");\r
+ String val = (String)settings.value("font", "");\r
+ settings.endGroup();\r
+ return val;\r
+ }\r
+ public static void setDefaultFont(String value) {\r
+ settings.beginGroup("Font");\r
+ settings.setValue("font", value);\r
+ settings.endGroup();\r
+ }\r
+ public static String getDefaultFontSize() {\r
+ settings.beginGroup("Font");\r
+ String val = (String)settings.value("fontSize", "");\r
+ settings.endGroup();\r
+ return val;\r
+ }\r
+ public static void setDefaultFontSize(String value) {\r
+ settings.beginGroup("Font");\r
+ settings.setValue("fontSize", value);\r
+ settings.endGroup();\r
+ }\r
\r
\r
}\r
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.SortedMap;
import java.util.Vector;
import com.evernote.edam.type.User;
import com.trolltech.qt.QThread;
import com.trolltech.qt.core.QByteArray;
-import com.trolltech.qt.core.QDataStream;
import com.trolltech.qt.core.QDateTime;
import com.trolltech.qt.core.QDir;
import com.trolltech.qt.core.QEvent;
import com.trolltech.qt.core.QTranslator;
import com.trolltech.qt.core.QUrl;
import com.trolltech.qt.core.Qt;
+import com.trolltech.qt.core.Qt.BGMode;
import com.trolltech.qt.core.Qt.ItemDataRole;
import com.trolltech.qt.core.Qt.SortOrder;
import com.trolltech.qt.core.Qt.WidgetAttribute;
import com.trolltech.qt.gui.QMenu;
import com.trolltech.qt.gui.QMessageBox;
import com.trolltech.qt.gui.QMessageBox.StandardButton;
+import com.trolltech.qt.gui.QPainter;
+import com.trolltech.qt.gui.QPalette.ColorRole;
import com.trolltech.qt.gui.QPixmap;
import com.trolltech.qt.gui.QPrintDialog;
import com.trolltech.qt.gui.QPrinter;
import com.trolltech.qt.gui.QTreeWidgetItem;
import com.trolltech.qt.webkit.QWebPage.WebAction;
import com.trolltech.qt.webkit.QWebSettings;
-import com.trolltech.qt.xml.QDomAttr;
-import com.trolltech.qt.xml.QDomDocument;
-import com.trolltech.qt.xml.QDomElement;
-import com.trolltech.qt.xml.QDomNodeList;
-import cx.fbn.nevernote.config.FileManager;
import cx.fbn.nevernote.config.InitializationException;
import cx.fbn.nevernote.config.StartupConfig;
import cx.fbn.nevernote.dialog.AccountDialog;
import cx.fbn.nevernote.dialog.TagEdit;
import cx.fbn.nevernote.dialog.ThumbnailViewer;
import cx.fbn.nevernote.dialog.WatchFolder;
-import cx.fbn.nevernote.filters.EnSearch;
import cx.fbn.nevernote.gui.AttributeTreeWidget;
import cx.fbn.nevernote.gui.BrowserWindow;
import cx.fbn.nevernote.gui.DateAttributeFilterTable;
+import cx.fbn.nevernote.gui.ExternalBrowse;
import cx.fbn.nevernote.gui.MainMenuBar;
import cx.fbn.nevernote.gui.NotebookTreeWidget;
-import cx.fbn.nevernote.gui.PDFPreview;
import cx.fbn.nevernote.gui.SavedSearchTreeWidget;
import cx.fbn.nevernote.gui.TableView;
import cx.fbn.nevernote.gui.TagTreeWidget;
import cx.fbn.nevernote.sql.WatchFolderRecord;
import cx.fbn.nevernote.threads.IndexRunner;
import cx.fbn.nevernote.threads.SyncRunner;
+import cx.fbn.nevernote.threads.ThumbnailRunner;
import cx.fbn.nevernote.utilities.AESEncrypter;
import cx.fbn.nevernote.utilities.ApplicationLogger;
import cx.fbn.nevernote.utilities.FileImporter;
import cx.fbn.nevernote.utilities.SyncTimes;
import cx.fbn.nevernote.xml.ExportData;
import cx.fbn.nevernote.xml.ImportData;
-import cx.fbn.nevernote.xml.XMLInsertHilight;
+import cx.fbn.nevernote.xml.NoteFormatter;
public class NeverNote extends QMainWindow{
List<String> selectedTagGUIDs; // List of selected tag GUIDs
List<String> selectedNoteGUIDs; // List of selected notes
String selectedSavedSearchGUID; // Currently selected saved searches
+ private final HashMap<String, ExternalBrowse> externalWindows; // Notes being edited by an external window;
NoteFilter filter; // Note filter
String currentNoteGuid; // GUID of the current note
QTimer syncTimer; // Sync on an interval
QTimer syncDelayTimer; // Sync delay to free up database
SyncRunner syncRunner; // thread to do a sync.
- QThread syncThread;
+ QThread syncThread; // Thread which talks to evernote
+ ThumbnailRunner thumbnailRunner; // Runner for thumbnail thread
+ QThread thumbnailThread; // Thread that generates pretty pictures
QTimer saveTimer; // Timer to save note contents
QTimer authTimer; // Refresh authentication
QTimer externalFileSaveTimer; // Save files altered externally
+ QTimer thumbnailTimer; // Wakeup & scan for thumbnails
List<String> externalFiles; // External files to save later
List<String> importFilesKeep; // Auto-import files to save later
List<String> importFilesDelete; // Auto-import files to save later
QAction downButton; // Go to the next item in the list
QAction upButton; // Go to the prev. item in the list;
QAction synchronizeButton; // Synchronize with Evernote
- List<QIcon> synchronizeAnimation; // Synchronize movie
+ QAction allNotesButton; // Reset & view all notes
QTimer synchronizeAnimationTimer; // Timer to change animation button
- int synchronizeFrame; // Current frame being viewed
+ double synchronizeIconAngle; // Used to rotate sync icon
QAction printButton; // Print Button
QAction tagButton; // Tag edit button
QAction attributeButton; // Attribute information button
int historyPosition; // Position within the viewed items
boolean fromHistory; // Is this from the history queue?
String trashNoteGuid; // Guid to restore / set into or out of trash to save position
- Thumbnailer preview; // generate preview image
+ List<Thumbnailer> previewList; // generate preview image
ThumbnailViewer thumbnailViewer; // View preview thumbnail;
boolean encryptOnShutdown; // should I encrypt when I close?
boolean decryptOnShutdown; // should I decrypt on shutdown;
String encryptCipher; // What cipher should I use?
Signal0 minimizeToTray;
boolean windowMaximized = false; // Keep track of the window state for restores
+ List<String> pdfReadyQueue; // Queue of PDFs that are ready to be rendered.
+
String iconPath = new String("classpath:cx/fbn/nevernote/icons/");
// Application Constructor
public NeverNote(DatabaseConnection dbConn) {
conn = dbConn;
+ if (conn.getConnection() == null) {
+ String msg = "Unable to connect to the database.\n\nThe most probable reason is that some other process\n" +
+ "is accessing the database or NeverNote is already running.\n\n" +
+ "Please end any other process or shutdown the other NeverNote before starting.\n\nExiting program.";
+
+ QMessageBox.critical(null, "Database Connection Error",msg);
+ System.exit(16);
+ }
thread().setPriority(Thread.MAX_PRIORITY);
syncThread.start();
+ logger.log(logger.EXTREME, "Starting thumnail thread");
+ pdfReadyQueue = new ArrayList<String>();
+ thumbnailRunner = new ThumbnailRunner("thumbnailRunner.log", Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
+ thumbnailThread = new QThread(thumbnailRunner, "Thumbnail Thread");
+ thumbnailRunner.noteSignal.thumbnailPageReady.connect(this, "thumbnailHTMLReady(String,String)");
+// thumbnailThread.start();
+ previewList = new ArrayList<Thumbnailer>();
+ thumbnailTimer = new QTimer();
+ thumbnailTimer.timeout.connect(this, "thumbnailTimer()");
+ thumbnailTimer();
+ thumbnailTimer.setInterval(30*1000);
+// thumbnailTimer.start();
+
logger.log(logger.EXTREME, "Starting authentication timer");
authTimer = new QTimer();
authTimer.timeout.connect(this, "authTimer()");
saveTimer.timeout.connect(this, "saveNote()");
if (Global.getAutoSaveInterval() > 0) {
saveTimer.setInterval(1000*60*Global.getAutoSaveInterval());
-// saveTimer.setInterval(1000*10); // auto save every 20 seconds;
+// saveTimer.setInterval(1000*10); // auto save every 10 seconds;
saveTimer.start();
}
listManager.saveRunner.noteSignals.noteSaveRunnerError.connect(this, "saveRunnerError(String, String)");
noteCache = new HashMap<String,String>();
browserWindow = new BrowserWindow(conn);
- browserIndexSplitter.addWidget(noteTableView);
- browserIndexSplitter.addWidget(browserWindow);
+ if (Global.getListView() == Global.View_List_Wide) {
+ browserIndexSplitter.addWidget(noteTableView);
+ browserIndexSplitter.addWidget(browserWindow);
+ }
mainLeftRightSplitter.addWidget(leftSplitter1);
mainLeftRightSplitter.addWidget(browserIndexSplitter);
+ if (Global.getListView() == Global.View_List_Narrow) {
+ mainLeftRightSplitter.addWidget(noteTableView);
+ mainLeftRightSplitter.addWidget(browserWindow);
+ }
+
+
searchField = new QComboBox();
searchField.setEditable(true);
searchField.activatedIndex.connect(this, "searchFieldChanged()");
thumbnailViewer.downArrow.connect(this, "downAction()");
thumbnailViewer.leftArrow.connect(this, "nextViewedAction()");
thumbnailViewer.rightArrow.connect(this, "previousViewedAction()");
+
+ //Setup external browser manager
+ externalWindows = new HashMap<String, ExternalBrowse>();
listManager.loadNotesIndex();
initializeNotebookTree();
trashTree.setVisible(Global.isWindowVisible("trashTree"));
menuBar.hideTrash.setChecked(Global.isWindowVisible("trashTree"));
trashTree.updateCounts(listManager.getTrashCount());
-
attributeTree.setVisible(Global.isWindowVisible("attributeTree"));
menuBar.hideAttributes.setChecked(Global.isWindowVisible("attributeTree"));
showColumns();
menuBar.showEditorBar.setChecked(Global.isWindowVisible("editorButtonBar"));
if (menuBar.showEditorBar.isChecked())
- showEditorButtons();
+ showEditorButtons(browserWindow);
tagIndexUpdated(true);
savedSearchIndexUpdated();
notebookIndexUpdated();
historyGuids.add(currentNoteGuid);
historyPosition = 1;
+ if (Global.getListView() == Global.View_List_Narrow) {
+ menuBar.narrowListView.setChecked(true);
+ narrowListView();
+ }
+ else{
+ menuBar.wideListView.setChecked(true);
+ wideListView();
+ }
+
+
int sortCol = Global.getSortColumn();
int sortOrder = Global.getSortOrder();
noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder));
+
+ /*
+ for (int i=0; i<listManager.getNoteIndex().size(); i++) {
+ Note n = listManager.getNoteIndex().get(i);
+ if (n.getNotebookGuid().equalsIgnoreCase("2")) {
+ conn.getNoteTable().updateNoteSequence(n.getGuid(), 0);
+ n = conn.getNoteTable().getNote(n.getGuid(), false, true, false, false, true);
+ for (int j=0; j<n.getResourcesSize(); j++) {
+ conn.getNoteTable().noteResourceTable.resetUpdateSequenceNumber(n.getResources().get(j).getGuid(), true);
+ }
+ }
+ } */
}
}
saveNote();
setMessage(tr("Beginning shutdown."));
-
+
+ // Close down external windows
+ Collection<ExternalBrowse> windows = externalWindows.values();
+ Iterator<ExternalBrowse> iterator = windows.iterator();
+ while (iterator.hasNext()) {
+ ExternalBrowse browser = iterator.next();
+ browser.windowClosing.disconnect();
+ browser.close();
+ }
+
+
externalFileEditedSaver();
if (Global.isConnected && Global.synchronizeOnClose()) {
setMessage(tr("Performing synchronization before closing."));
threadMonitorTimer.stop();
syncRunner.addWork("STOP");
+ syncRunner.keepRunning = false;
+ thumbnailRunner.addWork("STOP");
+ syncRunner.keepRunning = false;
indexRunner.addWork("STOP");
+ syncRunner.keepRunning = false;
saveNote();
listManager.stop();
saveWindowState();
Global.setColumnPosition("noteTableTitlePosition", position);
position = noteTableView.header.visualIndex(Global.noteTableSynchronizedPosition);
Global.setColumnPosition("noteTableSynchronizedPosition", position);
+ position = noteTableView.header.visualIndex(Global.noteTableGuidPosition);
+ Global.setColumnPosition("noteTableGuidPosition", position);
+ position = noteTableView.header.visualIndex(Global.noteTableThumbnailPosition);
+ Global.setColumnPosition("noteTableThumbnailPosition", position);
if (isVisible())
Global.saveWindowVisible("toolBar", toolBar.isVisible());
}
private void setupBrowserSignalListeners() {
-
- browserWindow.fileWatcher.fileChanged.connect(this, "externalFileEdited(String)");
- browserWindow.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)");
- browserWindow.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)");
- //browserWindow.noteSignal.noteChanged.connect(this, "invalidateNoteCache(String, String)");
- browserWindow.noteSignal.noteChanged.connect(this, "setNoteDirty()");
- browserWindow.noteSignal.titleChanged.connect(listManager, "updateNoteTitle(String, String)");
- browserWindow.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
- browserWindow.noteSignal.createdDateChanged.connect(listManager, "updateNoteCreatedDate(String, QDateTime)");
- browserWindow.noteSignal.alteredDateChanged.connect(listManager, "updateNoteAlteredDate(String, QDateTime)");
- browserWindow.noteSignal.subjectDateChanged.connect(listManager, "updateNoteSubjectDate(String, QDateTime)");
- browserWindow.noteSignal.authorChanged.connect(listManager, "updateNoteAuthor(String, String)");
- browserWindow.noteSignal.geoChanged.connect(listManager, "updateNoteGeoTag(String, Double,Double,Double)");
- browserWindow.noteSignal.geoChanged.connect(this, "setNoteDirty()");
- browserWindow.noteSignal.sourceUrlChanged.connect(listManager, "updateNoteSourceUrl(String, String)");
- browserWindow.focusLost.connect(this, "saveNote()");
- browserWindow.resourceSignal.contentChanged.connect(this, "externalFileEdited(String)");
+ setupBrowserWindowListeners(browserWindow, true);
}
-
+ private void setupBrowserWindowListeners(BrowserWindow browser, boolean master) {
+ browser.fileWatcher.fileChanged.connect(this, "externalFileEdited(String)");
+ browser.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)");
+ browser.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)");
+ if (master) browser.noteSignal.noteChanged.connect(this, "setNoteDirty()");
+ browser.noteSignal.titleChanged.connect(listManager, "updateNoteTitle(String, String)");
+ browser.noteSignal.titleChanged.connect(this, "updateNoteTitle(String, String)");
+ browser.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
+ browser.noteSignal.createdDateChanged.connect(listManager, "updateNoteCreatedDate(String, QDateTime)");
+ browser.noteSignal.alteredDateChanged.connect(listManager, "updateNoteAlteredDate(String, QDateTime)");
+ browser.noteSignal.subjectDateChanged.connect(listManager, "updateNoteSubjectDate(String, QDateTime)");
+ browser.noteSignal.authorChanged.connect(listManager, "updateNoteAuthor(String, String)");
+ browser.noteSignal.geoChanged.connect(listManager, "updateNoteGeoTag(String, Double,Double,Double)");
+ browser.noteSignal.geoChanged.connect(this, "setNoteDirty()");
+ browser.noteSignal.sourceUrlChanged.connect(listManager, "updateNoteSourceUrl(String, String)");
+ if (master) browser.focusLost.connect(this, "saveNote()");
+ browser.resourceSignal.contentChanged.connect(this, "externalFileEdited(String)");
+ }
//***************************************************************
//***************************************************************
@SuppressWarnings("unused")
private void settings() {
logger.log(logger.HIGH, "Entering NeverNote.settings");
+ saveNoteIndexWidth();
ConfigDialog settings = new ConfigDialog(this);
String dateFormat = Global.getDateFormat();
String timeFormat = Global.getTimeFormat();
trayIcon.hide();
showColumns();
if (menuBar.showEditorBar.isChecked())
- showEditorButtons();
+ showEditorButtons(browserWindow);
// Reset the save timer
if (Global.getAutoSaveInterval() > 0)
Global.setColumnWidth("noteTableSubjectDatePosition", width);
width = noteTableView.getColumnWidth(Global.noteTableSynchronizedPosition);
Global.setColumnWidth("noteTableSynchronizedPosition", width);
+ width = noteTableView.getColumnWidth(Global.noteTableThumbnailPosition);
+ Global.setColumnWidth("noteTableThumbnailPosition", width);
+ width = noteTableView.getColumnWidth(Global.noteTableGuidPosition);
+ Global.setColumnWidth("noteTableGuidPosition", width);
}
currentSelection = selections.get(0);
edit.setNotebook(currentSelection.text(0));
edit.setNotebooks(listManager.getNotebookIndex());
+
+ String guid = currentSelection.text(2);
+ for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
+ if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
+ edit.setDefaultNotebook(listManager.getNotebookIndex().get(i).isDefaultNotebook());
+ i=listManager.getNotebookIndex().size();
+ }
+ }
edit.exec();
if (!edit.okPressed())
return;
- String guid = currentSelection.text(2);
updateListNotebookName(currentSelection.text(0), edit.getNotebook());
currentSelection.setText(0, edit.getNotebook());
for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
listManager.getNotebookIndex().get(i).setName(edit.getNotebook());
+ if (!listManager.getNotebookIndex().get(i).isDefaultNotebook() && edit.isDefaultNotebook()) {
+ for (int j=0; j<listManager.getNotebookIndex().size(); j++)
+ listManager.getNotebookIndex().get(j).setDefaultNotebook(false);
+ listManager.getNotebookIndex().get(i).setDefaultNotebook(true);
+ conn.getNotebookTable().setDefaultNotebook(listManager.getNotebookIndex().get(i).getGuid());
+ }
conn.getNotebookTable().updateNotebook(listManager.getNotebookIndex().get(i), true);
i=listManager.getNotebookIndex().size();
}
toggleDownArrowButton(Global.isToolbarButtonVisible("downArrow"));
synchronizeButton = toolBar.addAction("Synchronize");
- synchronizeAnimation = new ArrayList<QIcon>();
- synchronizeAnimation.add(new QIcon(iconPath+"synchronize-0.png"));
- synchronizeAnimation.add(new QIcon(iconPath+"synchronize-1.png"));
- synchronizeAnimation.add(new QIcon(iconPath+"synchronize-2.png"));
- synchronizeAnimation.add(new QIcon(iconPath+"synchronize-3.png"));
- synchronizeButton.setIcon(synchronizeAnimation.get(0));
- synchronizeFrame = 0;
+ synchronizeButton.setIcon(new QIcon(iconPath+"synchronize.png"));
+ synchronizeIconAngle = 0;
synchronizeButton.triggered.connect(this, "evernoteSync()");
toggleSynchronizeButton(Global.isToolbarButtonVisible("synchronize"));
-
printButton = toolBar.addAction("Print");
QIcon printIcon = new QIcon(iconPath+"print.png");
newButton.setIcon(newIcon);
toggleNewButton(Global.isToolbarButtonVisible("new"));
+ allNotesButton = toolBar.addAction("All Notes");
+ QIcon allIcon = new QIcon(iconPath+"allNotes3.png");
+ allNotesButton.triggered.connect(this, "allNotes()");
+ allNotesButton.setIcon(allIcon);
+ toggleAllNotesButton(Global.isToolbarButtonVisible("allNotes"));
+
toolBar.addSeparator();
toolBar.addWidget(new QLabel(tr("Quota:")));
toolBar.addWidget(quotaBar);
//quotaBar.setSizePolicy(Policy.Minimum, Policy.Minimum);
updateQuotaBar();
+ toolBar.addSeparator();
// Setup the zoom
zoomSpinner = new QSpinBox();
QAction newAction = addContextAction("new", tr("Add"));
contextMenu.addAction(newAction);
newAction.triggered.connect(this, "toggleNewButton(Boolean)");
-
+
+ QAction allNotesAction = addContextAction("allNotes", tr("All Notes"));
+ contextMenu.addAction(allNotesAction);
+ allNotesAction.triggered.connect(this, "toggleAllNotesButton(Boolean)");
+
QAction searchClearAction = addContextAction("searchClear", tr("Search Clear"));
contextMenu.addAction(searchClearAction);
searchClearAction.triggered.connect(this, "toggleSearchClearButton(Boolean)");
newButton.setVisible(toggle);
Global.saveToolbarButtonsVisible("new", toggle);
}
+ private void toggleAllNotesButton(Boolean toggle) {
+ allNotesButton.setVisible(toggle);
+ Global.saveToolbarButtonsVisible("allNotes", toggle);
+ }
private void toggleSearchClearButton(Boolean toggle) {
searchClearButton.setVisible(toggle);
Global.saveToolbarButtonsVisible("searchClear", toggle);
@SuppressWarnings("unused")
private void updateSyncButton() {
- synchronizeFrame++;
+ /* synchronizeFrame++;
if (synchronizeFrame == 4)
synchronizeFrame = 0;
synchronizeButton.setIcon(synchronizeAnimation.get(synchronizeFrame));
+ */
+/*
+ QPixmap pix = new QPixmap(iconPath+"synchronize.png");
+ QMatrix matrix = new QMatrix();
+ synchronizeIconAngle = synchronizeIconAngle + 1.0;
+ if (synchronizeIconAngle >= 365.0)
+ synchronizeIconAngle = 0.0;
+ matrix.translate(pix.size().width()/2, pix.size().height()/2);
+ matrix.rotate( synchronizeIconAngle );
+ matrix.translate(-pix.size().width()/2, -pix.size().height()/2);
+ pix = pix.transformed(matrix, TransformationMode.SmoothTransformation);
+ synchronizeButton.setIcon(pix);
+*/
+
+
+ QPixmap pix = new QPixmap(iconPath+"synchronize.png");
+ QPixmap rotatedPix = new QPixmap(pix.size());
+ QPainter p = new QPainter(rotatedPix);
+
+ rotatedPix.fill(toolBar.palette().color(ColorRole.Button));
+ QSize size = pix.size();
+ p.translate(size.width()/2, size.height()/2);
+ synchronizeIconAngle = synchronizeIconAngle+1.0;
+ if (synchronizeIconAngle >= 359.0)
+ synchronizeIconAngle = 0.0;
+ p.rotate(synchronizeIconAngle);
+ p.setBackgroundMode(BGMode.OpaqueMode);
+ p.translate(-size.width()/2, -size.height()/2);
+ p.drawPixmap(0,0, pix);
+ p.end();
+ synchronizeButton.setIcon(rotatedPix);
+
}
// Synchronize with Evernote
@SuppressWarnings("unused")
if (!Global.isConnected)
remoteConnect();
if (Global.isConnected)
- synchronizeAnimationTimer.start(200);
+ synchronizeAnimationTimer.start(10);
+// synchronizeAnimationTimer.start(200);
syncTimer();
logger.log(logger.HIGH, "Leaving NeverNote.evernoteSync");
}
noteTableView.showColumn(Global.noteTableGuidPosition);
List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
- noteTableView.hideColumn(Global.noteTableGuidPosition);
+ if (!Global.isColumnVisible("guid"))
+ noteTableView.hideColumn(Global.noteTableGuidPosition);
if (selections.size() > 0) {
QModelIndex index;
if (tableGuid.equals(guid)) {
listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition,tagBuffer.toString());
listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
+ noteTableView.proxyModel.invalidate();
return;
}
}
//QModelIndex modelIndex = noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
if (modelIndex != null) {
-// SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex);
SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
String tableGuid = (String)ix.values().toArray()[0];
if (tableGuid.equals(guid)) {
listManager.getNoteTableModel().setData(i, Global.noteTableAuthorPosition,author);
listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
+ noteTableView.proxyModel.invalidate();
return;
}
}
}
+
logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
}
private void updateListNoteNotebook(String guid, String notebook) {
if (tableGuid.equals(guid)) {
listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
listManager.getNoteTableModel().setData(i, Global.noteTableSourceUrlPosition,url);
+ noteTableView.proxyModel.invalidate();
return;
}
}
String noteGuid = (String)ix.values().toArray()[0];
if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) {
listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition, newName);
- //listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
i=listManager.getNoteTableModel().rowCount();
}
}
String noteGuid = (String)ix.values().toArray()[0];
if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) {
listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition, newName);
-// listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
i=listManager.getNoteTableModel().rowCount();
}
}
SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
String tableName = (String)ix.values().toArray()[0];
if (tableName.equalsIgnoreCase(oldName)) {
-// listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
listManager.getNoteTableModel().setData(i, Global.noteTableNotebookPosition, newName);
}
}
String tableGuid = (String)ix.values().toArray()[0];
if (tableGuid.equals(guid)) {
listManager.getNoteTableModel().setData(i, Global.noteTableCreationPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
+ noteTableView.proxyModel.invalidate();
return;
}
}
if (tableGuid.equals(guid)) {
listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
listManager.getNoteTableModel().setData(i, Global.noteTableSubjectDatePosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
+ noteTableView.proxyModel.invalidate();
return;
}
}
}
private void updateListDateChanged() {
logger.log(logger.HIGH, "Entering NeverNote.updateListDateChanged");
- QDateTime date = new QDateTime(QDateTime.currentDateTime());
- for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
- QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
- if (modelIndex != null) {
- SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
- String tableGuid = (String)ix.values().toArray()[0];
- if (tableGuid.equals(currentNoteGuid)) {
- listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
- listManager.getNoteTableModel().setData(i, Global.noteTableChangedPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
- return;
- }
- }
- }
+ QDateTime date = new QDateTime(QDateTime.currentDateTime());
+ updateListDateChanged(currentNoteGuid, date);
logger.log(logger.HIGH, "Leaving NeverNote.updateListDateChanged");
}
// Redo scroll
noteTableView.setColumnHidden(Global.noteTableTagPosition, !Global.isColumnVisible("tags"));
noteTableView.setColumnHidden(Global.noteTableNotebookPosition, !Global.isColumnVisible("notebook"));
noteTableView.setColumnHidden(Global.noteTableSynchronizedPosition, !Global.isColumnVisible("synchronized"));
- }
- // Open a separate window
- @SuppressWarnings("unused")
- private void listDoubleClick() {
-
+ noteTableView.setColumnHidden(Global.noteTableGuidPosition, !Global.isColumnVisible("guid"));
+ noteTableView.setColumnHidden(Global.noteTableThumbnailPosition, !Global.isColumnVisible("thumbnail"));
}
// Title color has changed
@SuppressWarnings("unused")
}
logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
}
+ // Wide list was chosen
+ public void narrowListView() {
+ if (!menuBar.narrowListView.isChecked()) {
+ wideListView();
+ return;
+ }
+ menuBar.wideListView.blockSignals(true);
+ menuBar.narrowListView.blockSignals(true);
+
+ menuBar.wideListView.setChecked(false);
+ menuBar.narrowListView.setChecked(true);
+
+ menuBar.wideListView.blockSignals(false);
+ menuBar.narrowListView.blockSignals(false);
+// browserIndexSplitter.setVisible(false);
+
+ Global.setListView(Global.View_List_Narrow);
+ mainLeftRightSplitter.addWidget(noteTableView);
+ mainLeftRightSplitter.addWidget(browserWindow);
+ }
+ public void wideListView() {
+ if (!menuBar.wideListView.isChecked()) {
+ narrowListView();
+ return;
+ }
+ menuBar.wideListView.blockSignals(true);
+ menuBar.narrowListView.blockSignals(true);
+
+ menuBar.wideListView.setChecked(true);
+ menuBar.narrowListView.setChecked(false);
+
+ menuBar.wideListView.blockSignals(false);
+ menuBar.narrowListView.blockSignals(false);
+ browserIndexSplitter.setVisible(true);
+ Global.setListView(Global.View_List_Wide);
+// browserIndexSplitter.setVisible(true);
+ browserIndexSplitter.addWidget(noteTableView);
+ browserIndexSplitter.addWidget(browserWindow);
+ }
+
+
+ //***************************************************************
+ //***************************************************************
+ //** External editor window functions
+ //***************************************************************
+ //***************************************************************
+ @SuppressWarnings("unused")
+ private void listDoubleClick() {
+ saveNote();
+ if (externalWindows.containsKey(currentNoteGuid)) {
+ externalWindows.get(currentNoteGuid).raise();
+ return;
+ }
+
+ // We have a new external editor to create
+ QIcon appIcon = new QIcon(iconPath+"nevernote.png");
+ ExternalBrowse newBrowser = new ExternalBrowse(conn);
+ newBrowser.setWindowIcon(appIcon);
+ externalWindows.put(currentNoteGuid, newBrowser);
+ showEditorButtons(newBrowser.getBrowserWindow());
+ loadNoteBrowserInformation(newBrowser.getBrowserWindow());
+ setupBrowserWindowListeners(newBrowser.getBrowserWindow(), false);
+ newBrowser.windowClosing.connect(this, "externalWindowClosing(String)");
+ newBrowser.getBrowserWindow().noteSignal.titleChanged.connect(this, "externalWindowTitleEdited(String, String)");
+ newBrowser.getBrowserWindow().noteSignal.tagsChanged.connect(this, "externalWindowTagsEdited(String, List)");
+ newBrowser.contentsChanged.connect(this, "saveNoteExternalBrowser(String, String, Boolean, BrowserWindow)");
+
+ browserWindow.noteSignal.tagsChanged.connect(newBrowser, "updateTags(String, List)");
+ browserWindow.noteSignal.titleChanged.connect(newBrowser, "updateTitle(String, String)");
+ browserWindow.noteSignal.notebookChanged.connect(newBrowser, "updateNotebook(String, String)");
+
+ newBrowser.show();
+ }
+ @SuppressWarnings("unused")
+ private void externalWindowTitleEdited(String guid, String text) {
+ if (guid.equals(currentNoteGuid)) {
+ browserWindow.setTitle(text);
+ }
+ }
+ @SuppressWarnings("unused")
+ private void externalWindowTagsEdited(String guid, List values) {
+ StringBuffer line = new StringBuffer(100);
+ for (int i=0; i<values.size(); i++) {
+ if (i>0)
+ line.append(Global.tagDelimeter+" ");
+ line.append(values.get(i));
+ }
+ if (guid.equals(currentNoteGuid)) {
+ browserWindow.setTag(line.toString());
+ }
+ }
+ @SuppressWarnings("unused")
+ private void externalWindowClosing(String guid) {
+ externalWindows.remove(guid);
+ }
+
//***************************************************************
@SuppressWarnings("unused")
private void setNoteDirty() {
logger.log(logger.EXTREME, "Entering NeverNote.setNoteDirty()");
+ // Find if the note is being edited externally. If it is, update it.
+ if (externalWindows.containsKey(currentNoteGuid)) {
+ QTextCodec codec = QTextCodec.codecForName("UTF-8");
+ QByteArray unicode = codec.fromUnicode(browserWindow.getContent());
+ ExternalBrowse window = externalWindows.get(currentNoteGuid);
+ window.getBrowserWindow().getBrowser().setContent(unicode);
+ }
// If the note is dirty, then it is unsynchronized by default.
if (noteDirty)
*/
logger.log(logger.EXTREME, "Leaving NeverNote.setNoteDirty()");
}
+ @SuppressWarnings("unused")
+ private void saveNoteExternalBrowser(String guid, String content, Boolean save, BrowserWindow browser) {
+ QTextCodec codec = QTextCodec.codecForName("UTF-8");
+ QByteArray unicode = codec.fromUnicode(content);
+ noteCache.remove(guid);
+ noteCache.put(guid, unicode.toString());
+ if (guid.equals(currentNoteGuid)) {
+ noteDirty = true;
+ browserWindow.getBrowser().setContent(unicode);
+ }
+ if (save) {
+ saveNote(guid, browser);
+ }
+
+ }
private void saveNote() {
- logger.log(logger.EXTREME, "Inside NeverNote.saveNote()");
if (noteDirty) {
- logger.log(logger.EXTREME, "Note is dirty.");
- waitCursor(true);
-
- preview = new Thumbnailer(currentNoteGuid, new QSize(1024,768));
- preview.finished.connect(this, "saveThumbnail(String)");
- preview.setContent(browserWindow.getContent());
+ saveNote(currentNoteGuid, browserWindow);
+ noteDirty = false;
+ }
+ }
+ private void saveNote(String guid, BrowserWindow window) {
+ logger.log(logger.EXTREME, "Inside NeverNote.saveNote()");
+ logger.log(logger.EXTREME, "Note is dirty.");
+ waitCursor(true);
- logger.log(logger.EXTREME, "Saving to cache");
- QTextCodec codec = QTextCodec.codecForLocale();
+ logger.log(logger.EXTREME, "Saving to cache");
+ QTextCodec codec = QTextCodec.codecForLocale();
// QTextDecoder decoder = codec.makeDecoder();
- codec = QTextCodec.codecForName("UTF-8");
- QByteArray unicode = codec.fromUnicode(browserWindow.getContent());
- noteCache.put(currentNoteGuid, unicode.toString());
+ codec = QTextCodec.codecForName("UTF-8");
+ QByteArray unicode = codec.fromUnicode(window.getContent());
+ noteCache.put(guid, unicode.toString());
- logger.log(logger.EXTREME, "updating list manager");
- listManager.updateNoteContent(currentNoteGuid, browserWindow.getContent());
-// noteCache.put(currentNoteGuid, browserWindow.getContent());
- logger.log(logger.EXTREME, "Updating title");
- listManager.updateNoteTitle(currentNoteGuid, browserWindow.getTitle());
- updateListDateChanged();
+ logger.log(logger.EXTREME, "updating list manager");
+ listManager.updateNoteContent(guid, window.getContent());
+ logger.log(logger.EXTREME, "Updating title");
+ listManager.updateNoteTitle(guid, window.getTitle());
+ updateListDateChanged();
- logger.log(logger.EXTREME, "Looking through note index for refreshed note");
- for (int i=0; i<listManager.getNoteIndex().size(); i++) {
- if (listManager.getNoteIndex().get(i).getGuid().equals(currentNoteGuid)) {
- currentNote = listManager.getNoteIndex().get(i);
- i = listManager.getNoteIndex().size();
- }
+ logger.log(logger.EXTREME, "Looking through note index for refreshed note");
+ for (int i=0; i<listManager.getNoteIndex().size(); i++) {
+ if (listManager.getNoteIndex().get(i).getGuid().equals(guid)) {
+ currentNote = listManager.getNoteIndex().get(i);
+ i = listManager.getNoteIndex().size();
}
- noteDirty = false;
- waitCursor(false);
}
+ waitCursor(false);
}
// Get a note from Evernote (and put it in the browser)
private void refreshEvernoteNote(boolean reload) {
currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true);
if (currentNote == null)
return;
-
+
+ loadNoteBrowserInformation(browserWindow);
+ }
+ private void loadNoteBrowserInformation(BrowserWindow browser) {
+ NoteFormatter formatter = new NoteFormatter(logger, conn, tempFiles);
+ formatter.setNote(currentNote, Global.pdfPreview());
+ formatter.setHighlight(listManager.getEnSearch());
if (!noteCache.containsKey(currentNoteGuid) || conn.getNoteTable().isThumbnailNeeded(currentNoteGuid)) {
QByteArray js = new QByteArray();
// We need to prepend the note with <HEAD></HEAD> or encoded characters are ugly
js.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
- js.append("<style type=\"text/css\">en-crypt-temp { border-style:solid; border-color:blue; padding:0.5mm 0.5mm 0.5mm 0.5mm; }</style>");
+ js.append("<style type=\"text/css\">.en-crypt-temp { border-collapse:collapse; border-style:solid; border-color:blue; padding:0.0mm 0.0mm 0.0mm 0.0mm; }</style>");
js.append("<style type=\"text/css\">en-hilight { background-color: rgb(255,255,0) }</style>");
+ js.append("<style> img { max-width:100%; }</style>");
js.append("<style type=\"text/css\">en-spell { text-decoration: none; border-bottom: dotted 1px #cc0000; }</style>");
js.append("</head>");
- js.append(rebuildNoteHTML(currentNoteGuid, currentNote.getContent()));
+ formatter.setNote(currentNote, Global.pdfPreview());
+ js.append(formatter.rebuildNoteHTML());
js.append("</HTML>");
js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml.dtd'>", "");
js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml2.dtd'>", "");
js.replace("<?xml version='1.0' encoding='UTF-8'?>", "");
- browserWindow.getBrowser().setContent(js);
+ browser.getBrowser().setContent(js);
noteCache.put(currentNoteGuid, js.toString());
if (conn.getNoteTable().isThumbnailNeeded(currentNoteGuid)) {
- preview = new Thumbnailer(currentNoteGuid, new QSize(1024,768));
- preview.finished.connect(this, "saveThumbnail(String)");
- preview.setContent(js.toString());
+ thumbnailRunner.addWork("GENERATE " +currentNoteGuid);
}
} else {
logger.log(logger.HIGH, "Note content is being pulled from the cache");
- String cachedContent = modifyCachedTodoTags(noteCache.get(currentNoteGuid));
- browserWindow.getBrowser().setContent(new QByteArray(cachedContent));
+ String cachedContent = formatter.modifyCachedTodoTags(noteCache.get(currentNoteGuid));
+ browser.getBrowser().setContent(new QByteArray(cachedContent));
}
+
+ if (formatter.resourceError)
+ resourceErrorMessage();
+ inkNote = formatter.readOnly;
- browserWindow.getBrowser().page().setContentEditable(!inkNote); // We don't allow editing of ink notes
- browserWindow.setNote(currentNote);
+ browser.getBrowser().page().setContentEditable(!inkNote); // We don't allow editing of ink notes
+ browser.setNote(currentNote);
// Build a list of non-closed notebooks
List<Notebook> nbooks = new ArrayList<Notebook>();
nbooks.add(listManager.getNotebookIndex().get(i));
}
- browserWindow.setNotebookList(nbooks);
- browserWindow.setTitle(currentNote.getTitle());
- browserWindow.setTag(getTagNamesForNote(currentNote));
- browserWindow.setAuthor(currentNote.getAttributes().getAuthor());
+ browser.setNotebookList(nbooks);
+ browser.setTitle(currentNote.getTitle());
+ browser.setTag(getTagNamesForNote(currentNote));
+ browser.setAuthor(currentNote.getAttributes().getAuthor());
- browserWindow.setAltered(currentNote.getUpdated());
- browserWindow.setCreation(currentNote.getCreated());
+ browser.setAltered(currentNote.getUpdated());
+ browser.setCreation(currentNote.getCreated());
if (currentNote.getAttributes().getSubjectDate() > 0)
- browserWindow.setSubjectDate(currentNote.getAttributes().getSubjectDate());
+ browser.setSubjectDate(currentNote.getAttributes().getSubjectDate());
else
- browserWindow.setSubjectDate(currentNote.getCreated());
- browserWindow.setUrl(currentNote.getAttributes().getSourceURL());
- browserWindow.setAllTags(listManager.getTagIndex());
- browserWindow.setCurrentTags(currentNote.getTagNames());
+ browser.setSubjectDate(currentNote.getCreated());
+ browser.setUrl(currentNote.getAttributes().getSourceURL());
+ browser.setAllTags(listManager.getTagIndex());
+ browser.setCurrentTags(currentNote.getTagNames());
noteDirty = false;
scrollToGuid(currentNoteGuid);
- browserWindow.loadingData(false);
+ browser.loadingData(false);
if (thumbnailViewer.isActiveWindow())
thumbnailView();
waitCursor(false);
logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNote");
}
// Save a generated thumbnail
- @SuppressWarnings("unused")
- private void saveThumbnail(String guid) {
- QFile tFile = new QFile(Global.getFileManager().getResDirPath("thumbnail-" + guid + ".png"));
- tFile.open(OpenModeFlag.ReadOnly);
- QByteArray imgBytes = tFile.readAll();
- tFile.close();
- conn.getNoteTable().setThumbnail(guid, imgBytes);
- conn.getNoteTable().setThumbnailNeeded(guid, false);
- thumbnailViewer.setThumbnail(QImage.fromData(imgBytes));
- if (thumbnailViewer.isVisible())
- thumbnailViewer.showFullScreen();
-
- /*
- QByteArray img2 = new QByteArray(conn.getNoteTable().getThumbnail(guid));
- QFile file = new QFile(Global.currentDir+"res/aaaa.png");
- file.open(OpenModeFlag.WriteOnly);
- file.write(img2);
- file.close();
- */
- }
- // Show/Hide note information
- @SuppressWarnings("unused")
private void toggleNoteInformation() {
logger.log(logger.HIGH, "Entering NeverNote.toggleNoteInformation");
browserWindow.toggleInformation();
browserWindow.setReadOnly(false);
saveNote();
Calendar currentTime = new GregorianCalendar();
- String noteString = new String("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ StringBuffer noteString = new StringBuffer(100);
+ noteString.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">\n" +
- "<en-note>\n<br clear=\"none\" /></en-note>");
+ "<en-note>\n");
+
+ if (Global.overrideDefaultFont()) {
+ noteString.append("<font face=\"" +Global.getDefaultFont() +"\" >");
+ noteString.append("<span style=\"font-size:" +Global.getDefaultFontSize() +"pt;\">");
+ noteString.append("<br clear=\"none\" />\n");
+ noteString.append("</span>\n</font>\n");
+ } else
+ noteString.append("<br clear=\"none\" />\n");
+ noteString.append("</en-note>");
Long l = new Long(currentTime.getTimeInMillis());
String randint = new String(Long.toString(l));
newNote.setGuid(randint);
newNote.setNotebookGuid(notebook);
newNote.setTitle("");
- newNote.setContent(noteString);
+ newNote.setContent(noteString.toString());
newNote.setDeleted(0);
newNote.setCreated(System.currentTimeMillis());
newNote.setUpdated(System.currentTimeMillis());
browserWindow.getBrowser().page().findText(find.getText(), find.getFlags());
find.setFocus();
}
+ private void updateNoteTitle(String guid, String title) {
+ listManager.setNoteSynchronized(guid, false);
+ }
// Signal received that note content has changed. Normally we just need the guid to remove
// it from the cache.
@SuppressWarnings("unused")
currentNote.setGuid(newGuid);
currentNoteGuid = newGuid;
}
+ if (externalWindows.containsKey(oldGuid)) {
+ ExternalBrowse b = externalWindows.get(oldGuid);
+ externalWindows.remove(oldGuid);
+ b.getBrowserWindow().getNote().setGuid(newGuid);
+ externalWindows.put(newGuid, b);
+ }
for (int i=0; i<listManager.getNoteIndex().size(); i++) {
if (listManager.getNoteIndex().get(i).getGuid().equals(newGuid)) {
noteTableView.proxyModel.addGuid(newGuid);
// Global.saveWindowVisible("editorButtonBar", browserWindow.buttonsVisible);
} else {
browserWindow.buttonsVisible = true;
- showEditorButtons();
+ showEditorButtons(browserWindow);
}
Global.saveWindowVisible("editorButtonBar", browserWindow.buttonsVisible);
}
// Show editor buttons
- private void showEditorButtons() {
- browserWindow.buttonLayout.setVisible(true);
- browserWindow.undoAction.setVisible(false);
+ private void showEditorButtons(BrowserWindow browser) {
+ browser.buttonLayout.setVisible(true);
+ browser.undoAction.setVisible(false);
- browserWindow.undoButton.setVisible(false);
+ browser.undoButton.setVisible(false);
- browserWindow.undoAction.setVisible(Global.isEditorButtonVisible("undo"));
- browserWindow.redoAction.setVisible(Global.isEditorButtonVisible("redo"));
- browserWindow.cutAction.setVisible(Global.isEditorButtonVisible("cut"));
- browserWindow.copyAction.setVisible(Global.isEditorButtonVisible("copy"));
- browserWindow.pasteAction.setVisible(Global.isEditorButtonVisible("paste"));
- browserWindow.strikethroughAction.setVisible(Global.isEditorButtonVisible("strikethrough"));
- browserWindow.underlineAction.setVisible(Global.isEditorButtonVisible("underline"));
- browserWindow.boldAction.setVisible(Global.isEditorButtonVisible("bold"));
- browserWindow.italicAction.setVisible(Global.isEditorButtonVisible("italic"));
- browserWindow.hlineAction.setVisible(Global.isEditorButtonVisible("hline"));
- browserWindow.indentAction.setVisible(Global.isEditorButtonVisible("indent"));
- browserWindow.outdentAction.setVisible(Global.isEditorButtonVisible("outdent"));
- browserWindow.bulletListAction.setVisible(Global.isEditorButtonVisible("bulletList"));
- browserWindow.numberListAction.setVisible(Global.isEditorButtonVisible("numberList"));
- browserWindow.fontListAction.setVisible(Global.isEditorButtonVisible("font"));
- browserWindow.fontSizeAction.setVisible(Global.isEditorButtonVisible("fontSize"));
- browserWindow.fontColorAction.setVisible(Global.isEditorButtonVisible("fontColor"));
- browserWindow.fontHilightAction.setVisible(Global.isEditorButtonVisible("fontHilight"));
- browserWindow.leftAlignAction.setVisible(Global.isEditorButtonVisible("alignLeft"));
- browserWindow.centerAlignAction.setVisible(Global.isEditorButtonVisible("alignCenter"));
- browserWindow.rightAlignAction.setVisible(Global.isEditorButtonVisible("alignRight"));
- browserWindow.spellCheckAction.setVisible(Global.isEditorButtonVisible("spellCheck"));
- browserWindow.todoAction.setVisible(Global.isEditorButtonVisible("todo"));
+ browser.undoAction.setVisible(Global.isEditorButtonVisible("undo"));
+ browser.redoAction.setVisible(Global.isEditorButtonVisible("redo"));
+ browser.cutAction.setVisible(Global.isEditorButtonVisible("cut"));
+ browser.copyAction.setVisible(Global.isEditorButtonVisible("copy"));
+ browser.pasteAction.setVisible(Global.isEditorButtonVisible("paste"));
+ browser.strikethroughAction.setVisible(Global.isEditorButtonVisible("strikethrough"));
+ browser.underlineAction.setVisible(Global.isEditorButtonVisible("underline"));
+ browser.boldAction.setVisible(Global.isEditorButtonVisible("bold"));
+ browser.italicAction.setVisible(Global.isEditorButtonVisible("italic"));
+ browser.hlineAction.setVisible(Global.isEditorButtonVisible("hline"));
+ browser.indentAction.setVisible(Global.isEditorButtonVisible("indent"));
+ browser.outdentAction.setVisible(Global.isEditorButtonVisible("outdent"));
+ browser.bulletListAction.setVisible(Global.isEditorButtonVisible("bulletList"));
+ browser.numberListAction.setVisible(Global.isEditorButtonVisible("numberList"));
+ browser.fontListAction.setVisible(Global.isEditorButtonVisible("font"));
+ browser.fontSizeAction.setVisible(Global.isEditorButtonVisible("fontSize"));
+ browser.fontColorAction.setVisible(Global.isEditorButtonVisible("fontColor"));
+ browser.fontHilightAction.setVisible(Global.isEditorButtonVisible("fontHilight"));
+ browser.leftAlignAction.setVisible(Global.isEditorButtonVisible("alignLeft"));
+ browser.centerAlignAction.setVisible(Global.isEditorButtonVisible("alignCenter"));
+ browser.rightAlignAction.setVisible(Global.isEditorButtonVisible("alignRight"));
+ browser.spellCheckAction.setVisible(Global.isEditorButtonVisible("spellCheck"));
+ browser.todoAction.setVisible(Global.isEditorButtonVisible("todo"));
}
private void duplicateNote(String guid) {
listManager.countNotebookResults(listManager.getNoteIndex());
waitCursor(false);
}
+ // View all notes
+ private void allNotes() {
+ clearAttributeFilter();
+ clearNotebookFilter();
+ clearSavedSearchFilter();
+ clearTrashFilter();
+ clearTagFilter();
+ searchField.clear();
+ if (Global.mimicEvernoteInterface) {
+ notebookTree.selectGuid("");
+ }
+ notebookTreeSelection();
+ }
// Merge notes
@SuppressWarnings("unused")
private void mergeNotes() {
i=listManager.getMasterNoteIndex().size();
}
}
- msg = "An error has happened saving the note \"" +title+
- "\". \nThis is probably due to a document that is too complex for Nevernote to process. "+
- "As a result, changes to the note may not be saved.\n\nPlease review the note for any potential problems.";
+ msg = "An error has happened while saving the note \"" +title+
+ "\".\n\nThis is probably due to a document that is too complex for Nevernote to process. "+
+ "As a result, changes to the note may not be saved properly in the database."+
+ "\n\nA cached copy is being preserved so you can recover any data, but data may" +
+ "\nbe lost. Please review the note to recover any critical data before restarting.";
QMessageBox.information(this, tr("Error Saving Note"), tr(msg));
}
}
+ private void thumbnailHTMLReady(String guid,String file) {
+ Thumbnailer preview = null;
+ // Find an idle preview object
+ for (int i=0; i<previewList.size(); i++) {
+ if (previewList.get(i).idle) {
+ preview = previewList.get(i);
+ i=previewList.size();
+ }
+ }
+ if (preview == null) {
+ preview = new Thumbnailer(conn, listManager);
+ previewList.add(preview);
+ }
+ preview.loadContent(guid, file);
+ }
//**********************************************************
//**********************************************************
// If we've gotten this far, we have a good note.
if (historyWindow == null) {
- historyWindow = new OnlineNoteHistory(conn);
+ historyWindow = new OnlineNoteHistory(logger, conn);
historyWindow.historyCombo.activated.connect(this, "reloadHistoryWindow(String)");
historyWindow.restoreAsNew.clicked.connect(this, "restoreHistoryNoteAsNew()");
historyWindow.restore.clicked.connect(this, "restoreHistoryNote()");
//* XML Modifying methods
//**********************************************************
//**********************************************************
- // find the appropriate icon for an attachment
- private String findIcon(String appl) {
- logger.log(logger.HIGH, "Entering NeverNote.findIcon");
- appl = appl.toLowerCase();
- String relativePath = appl + ".png";
- File f = Global.getFileManager().getImageDirFile(relativePath);
- if (f.exists()) {
- return relativePath;
- }
- if (f.exists())
- return appl+".png";
- logger.log(logger.HIGH, "Leaving NeverNote.findIcon");
- return "attachment.png";
- }
- // Modify the en-media tag into an attachment
- private void modifyApplicationTags(QDomDocument doc, QDomElement docElem, QDomElement enmedia, QDomAttr hash, String appl) {
- logger.log(logger.HIGH, "Entering NeverNote.modifyApplicationTags");
- if (appl.equalsIgnoreCase("vnd.evernote.ink"))
- inkNote = true;
- String resGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(currentNote.getGuid(), hash.value());
- Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, false);
- if (r == null || r.getData() == null)
- resourceErrorMessage();
- if (r!= null) {
- if (r.getData()!=null) {
- // Did we get a generic applicaiton? Then look at the file name to
- // try and find a good application type for the icon
- if (appl.equalsIgnoreCase("octet-stream")) {
- if (r.getAttributes() != null && r.getAttributes().getFileName() != null) {
- String fn = r.getAttributes().getFileName();
- int pos = fn.lastIndexOf(".");
- if (pos > -1) {
- appl = fn.substring(pos+1);
- }
- }
- }
-
- String fileDetails = null;
- if (r.getAttributes() != null && r.getAttributes().getFileName() != null && !r.getAttributes().getFileName().equals(""))
- fileDetails = r.getAttributes().getFileName();
- String contextFileName;
- FileManager fileManager = Global.getFileManager();
- if (fileDetails != null && !fileDetails.equals("")) {
- enmedia.setAttribute("href", "nnres://" +r.getGuid() +Global.attachmentNameDelimeter +fileDetails);
- contextFileName = fileManager.getResDirPath(r.getGuid() + Global.attachmentNameDelimeter + fileDetails);
- } else {
- enmedia.setAttribute("href", "nnres://" +r.getGuid() +Global.attachmentNameDelimeter +appl);
- contextFileName = fileManager.getResDirPath(r.getGuid() + Global.attachmentNameDelimeter + appl);
- }
- contextFileName = contextFileName.replace("\\", "/");
- enmedia.setAttribute("onContextMenu", "window.jambi.resourceContextMenu('" +contextFileName +"');");
- if (fileDetails == null || fileDetails.equals(""))
- fileDetails = "";
- enmedia.setAttribute("en-tag", "en-media");
- enmedia.setAttribute("guid", r.getGuid());
- enmedia.setTagName("a");
- QDomElement newText = doc.createElement("img");
- boolean goodPreview = false;
- String filePath = "";
- if (appl.equalsIgnoreCase("pdf") && Global.pdfPreview()) {
- String fileName;
- Resource res = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), true);
- if (res.getAttributes() != null &&
- res.getAttributes().getFileName() != null &&
- !res.getAttributes().getFileName().trim().equals(""))
- fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();
- else
- fileName = res.getGuid()+".pdf";
- QFile file = new QFile(fileManager.getResDirPath(fileName));
- QFile.OpenMode mode = new QFile.OpenMode();
- mode.set(QFile.OpenModeFlag.WriteOnly);
- file.open(mode);
- QDataStream out = new QDataStream(file);
- Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);
- QByteArray binData = new QByteArray(resBinary.getData().getBody());
- resBinary = null;
- out.writeBytes(binData.toByteArray());
- file.close();
- PDFPreview pdfPreview = new PDFPreview();
- goodPreview = pdfPreview.setupPreview(file.fileName(), appl,0);
- if (goodPreview) {
- QDomElement span = doc.createElement("span");
- QDomElement table = doc.createElement("table");
- span.setAttribute("pdfNavigationTable", "true");
- QDomElement tr = doc.createElement("tr");
- QDomElement td = doc.createElement("td");
- QDomElement left = doc.createElement("img");
- left.setAttribute("onMouseDown", "window.jambi.nextPage('" +file.fileName() +"')");
- left.setAttribute("onMouseDown", "window.jambi.nextPage('" +file.fileName() +"')");
- left.setAttribute("onMouseOver", "style.cursor='hand'");
- QDomElement right = doc.createElement("img");
- right.setAttribute("onMouseDown", "window.jambi.nextPage('" +file.fileName() +"')");
- left.setAttribute("onMouseDown", "window.jambi.previousPage('" +file.fileName() +"')");
- // NFC TODO: should these be file:// URLs?
- left.setAttribute("src", Global.getFileManager().getImageDirPath("small_left.png"));
- right.setAttribute("src", Global.getFileManager().getImageDirPath("small_right.png"));
- right.setAttribute("onMouseOver", "style.cursor='hand'");
-
- table.appendChild(tr);
- tr.appendChild(td);
- td.appendChild(left);
- td.appendChild(right);
- span.appendChild(table);
- enmedia.parentNode().insertBefore(span, enmedia);
- }
- filePath = fileName+".png";
- }
- String icon = findIcon(appl);
- if (icon.equals("attachment.png"))
- icon = findIcon(fileDetails.substring(fileDetails.indexOf(".")+1));
- // NFC TODO: should this be a 'file://' URL?
- newText.setAttribute("src", Global.getFileManager().getImageDirPath(icon));
- if (goodPreview) {
- // NFC TODO: should this be a 'file://' URL?
- newText.setAttribute("src", fileManager.getResDirPath(filePath));
- newText.setAttribute("style", "border-style:solid; border-color:green; padding:0.5mm 0.5mm 0.5mm 0.5mm;");
- }
- newText.setAttribute("title", fileDetails);
- enmedia.removeChild(enmedia.firstChild());
-
- enmedia.appendChild(newText);
- }
- }
- logger.log(logger.HIGH, "Leaving NeverNote.modifyApplicationTags");
- }
- // Modify the en-to tag into an input field
- private void modifyTodoTags(QDomElement todo) {
- logger.log(logger.HIGH, "Entering NeverNote.modifyTodoTags");
- todo.setAttribute("type", "checkbox");
- String checked = todo.attribute("checked");
- todo.removeAttribute("checked");
- if (checked.equalsIgnoreCase("true"))
- todo.setAttribute("checked", "");
- else
- todo.setAttribute("unchecked","");
- todo.setAttribute("value", checked);
- todo.setAttribute("onClick", "value=checked;window.jambi.contentChanged(); ");
- todo.setTagName("input");
- logger.log(logger.HIGH, "Leaving NeverNote.modifyTodoTags");
- }
- // Modify any cached todo tags that may have changed
- private String modifyCachedTodoTags(String note) {
- logger.log(logger.HIGH, "Entering NeverNote.modifyCachedTodoTags");
- StringBuffer html = new StringBuffer(note);
- for (int i=html.indexOf("<input", 0); i>-1; i=html.indexOf("<input", i)) {
- int endPos =html.indexOf(">",i+1);
- String input = html.substring(i,endPos);
- if (input.indexOf("value=\"true\"") > 0)
- input = input.replace(" unchecked=\"\"", " checked=\"\"");
- else
- input = input.replace(" checked=\"\"", " unchecked=\"\"");
- html.replace(i, endPos, input);
- i++;
- }
- logger.log(logger.HIGH, "Leaving NeverNote.modifyCachedTodoTags");
- return html.toString();
- }
- // Modify the en-media tag into an image tag so it can be displayed.
- private void modifyImageTags(QDomElement docElem, QDomElement enmedia, QDomAttr hash) {
- logger.log(logger.HIGH, "Entering NeverNote.modifyImageTags");
- String type = enmedia.attribute("type");
- if (type.startsWith("image/"))
- type = "."+type.substring(6);
- else
- type="";
-
- String resGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(currentNoteGuid, hash.value());
- QFile tfile = new QFile(Global.getFileManager().getResDirPath(resGuid + type));
- if (!tfile.exists()) {
- Resource r = null;
- if (resGuid != null)
- r = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid,true);
- if (r==null || r.getData() == null || r.getData().getBody().length == 0)
- resourceErrorMessage();
- if (r!= null && r.getData() != null && r.getData().getBody().length > 0) {
- tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));
- QByteArray binData = new QByteArray(r.getData().getBody());
- tfile.write(binData);
- tfile.close();
- enmedia.setAttribute("src", QUrl.fromLocalFile(tfile.fileName()).toString());
- enmedia.setAttribute("en-tag", "en-media");
- enmedia.setNodeValue("");
- enmedia.setAttribute("guid", r.getGuid());
- enmedia.setTagName("img");
- }
- }
- enmedia.setAttribute("src", QUrl.fromLocalFile(tfile.fileName()).toString());
- enmedia.setAttribute("en-tag", "en-media");
- enmedia.setAttribute("onContextMenu", "window.jambi.imageContextMenu('" +tfile.fileName() +"');");
- enmedia.setNodeValue("");
- enmedia.setAttribute("guid", resGuid);
- enmedia.setTagName("img");
-
- logger.log(logger.HIGH, "Leaving NeverNote.modifyImageTags");
- }
- // Modify tags from Evernote specific things to XHTML tags.
- private QDomDocument modifyTags(QDomDocument doc) {
- logger.log(logger.HIGH, "Entering NeverNote.modifyTags");
- if (tempFiles == null)
- tempFiles = new ArrayList<QTemporaryFile>();
- tempFiles.clear();
- QDomElement docElem = doc.documentElement();
-
- // Modify en-media tags
- QDomNodeList anchors = docElem.elementsByTagName("en-media");
- int enMediaCount = anchors.length();
- for (int i=enMediaCount-1; i>=0; i--) {
- QDomElement enmedia = anchors.at(i).toElement();
- if (enmedia.hasAttribute("type")) {
- QDomAttr attr = enmedia.attributeNode("type");
- QDomAttr hash = enmedia.attributeNode("hash");
- String[] type = attr.nodeValue().split("/");
- String appl = type[1];
-
- if (type[0] != null) {
- if (type[0].equals("image")) {
- modifyImageTags(docElem, enmedia, hash);
- }
- if (!type[0].equals("image")) {
- modifyApplicationTags(doc, docElem, enmedia, hash, appl);
- }
- }
- }
- }
-
- // Modify todo tags
- anchors = docElem.elementsByTagName("en-todo");
- int enTodoCount = anchors.length();
- for (int i=enTodoCount-1; i>=0; i--) {
- QDomElement enmedia = anchors.at(i).toElement();
- modifyTodoTags(enmedia);
- }
-
- // Modify en-crypt tags
- anchors = docElem.elementsByTagName("en-crypt");
- int enCryptLen = anchors.length();
- for (int i=enCryptLen-1; i>=0; i--) {
- QDomElement enmedia = anchors.at(i).toElement();
- enmedia.setAttribute("contentEditable","false");
- enmedia.setAttribute("src", Global.getFileManager().getImageDirPath("encrypt.png"));
- enmedia.setAttribute("en-tag","en-crypt");
- enmedia.setAttribute("alt", enmedia.text());
- Global.cryptCounter++;
- enmedia.setAttribute("id", "crypt"+Global.cryptCounter.toString());
- String encryptedText = enmedia.text();
-
- // If the encryption string contains crlf at the end, remove them because they mess up the javascript.
- if (encryptedText.endsWith("\n"))
- encryptedText = encryptedText.substring(0,encryptedText.length()-1);
- if (encryptedText.endsWith("\r"))
- encryptedText = encryptedText.substring(0,encryptedText.length()-1);
-
- // Add the commands
- String hint = enmedia.attribute("hint");
- hint = hint.replace("'","'");
- enmedia.setAttribute("onClick", "window.jambi.decryptText('crypt"+Global.cryptCounter.toString()+"', '"+encryptedText+"', '"+hint+"');");
- enmedia.setAttribute("onMouseOver", "style.cursor='hand'");
- enmedia.setTagName("img");
- enmedia.removeChild(enmedia.firstChild()); // Remove the actual encrypted text
- }
-
-
- // Modify link tags
- anchors = docElem.elementsByTagName("a");
- enCryptLen = anchors.length();
- for (int i=0; i<anchors.length(); i++) {
- QDomElement element = anchors.at(i).toElement();
- element.setAttribute("title", element.attribute("href"));
- }
-
- logger.log(logger.HIGH, "Leaving NeverNote.modifyTags");
- return doc;
- }
- // Rebuild the note HTML to something usable
- private String rebuildNoteHTML(String noteGuid, String note) {
- logger.log(logger.HIGH, "Entering NeverNote.rebuildNoteHTML");
- logger.log(logger.EXTREME, "Note guid: " +noteGuid);
- logger.log(logger.EXTREME, "Note Text:" +note);
- QDomDocument doc = new QDomDocument();
- QDomDocument.Result result = doc.setContent(note);
- if (!result.success) {
- logger.log(logger.MEDIUM, "Parse error when rebuilding HTML");
- logger.log(logger.MEDIUM, "Note guid: " +noteGuid);
- logger.log(logger.EXTREME, "Start of unmodified note HTML");
- logger.log(logger.EXTREME, note);
- logger.log(logger.EXTREME, "End of unmodified note HTML");
- return note;
- }
-
- if (tempFiles == null)
- tempFiles = new ArrayList<QTemporaryFile>();
- tempFiles.clear();
-
- doc = modifyTags(doc);
- doc = addHilight(doc);
- QDomElement docElem = doc.documentElement();
- docElem.setTagName("Body");
-// docElem.setAttribute("bgcolor", "green");
- logger.log(logger.EXTREME, "Rebuilt HTML:");
- logger.log(logger.EXTREME, doc.toString());
- logger.log(logger.HIGH, "Leaving NeverNote.rebuildNoteHTML");
- // Fix the stupid problem where inserting an <img> tag after an <a> tag (which is done
- // to get the <en-media> application tag to work properly) causes spaces to be inserted
- // between the <a> & <img>. This messes things up later. This is an ugly hack.
- StringBuffer html = new StringBuffer(doc.toString());
- for (int i=html.indexOf("<a en-tag=\"en-media\" ", 0); i>-1; i=html.indexOf("<a en-tag=\"en-media\" ", i)) {
- i=html.indexOf(">\n",i+1);
- int z = html.indexOf("<img",i);
- for (int j=z-1; j>i; j--)
- html.deleteCharAt(j);
- i=html.indexOf("/>", z+1);
- z = html.indexOf("</a>",i);
- for (int j=z-1; j>i+1; j--)
- html.deleteCharAt(j);
- }
- return html.toString();
- }
- // Scan and do hilighting of words
- private QDomDocument addHilight(QDomDocument doc) {
- EnSearch e = listManager.getEnSearch();
- if (e.hilightWords == null || e.hilightWords.size() == 0)
- return doc;
- XMLInsertHilight hilight = new XMLInsertHilight(doc, listManager.getEnSearch().hilightWords);
- return hilight.getDoc();
- }
-
// An error has happended fetching a resource. let the user know
private void resourceErrorMessage() {
if (inkNote)
"this note on the Evernote servers. Sorry."+
"\n\nP.S. You might want to re-synchronize to see if it corrects this problem.\nWho knows, you might get lucky."));
inkNote = true;
-//// browserWindow.setEnabled(false);
browserWindow.setReadOnly(true);
}
syncRunning = false;
syncRunner.syncNeeded = false;
synchronizeAnimationTimer.stop();
- synchronizeButton.setIcon(synchronizeAnimation.get(0));
+ synchronizeButton.setIcon(new QIcon(iconPath+"synchronize.png"));
saveNote();
if (currentNote == null) {
currentNote = conn.getNoteTable().getNote(currentNoteGuid, false, false, false, false, true);
}
-
+ private void thumbnailTimer() {
+ thumbnailRunner.addWork("SCAN");
+ }
//**************************************************
//* Backup & Restore
byte[] hash = md.digest();
String newHash = Global.byteArrayToHexString(hash);
if (r.getNoteGuid().equalsIgnoreCase(currentNoteGuid)) {
- updateResourceContentHash(r.getGuid(), oldHash, newHash);
+ updateResourceContentHash(browserWindow, r.getGuid(), oldHash, newHash);
+ }
+ if (externalWindows.containsKey(r.getNoteGuid())) {
+ updateResourceContentHash(externalWindows.get(r.getNoteGuid()).getBrowserWindow(),
+ r.getGuid(), oldHash, newHash);
}
conn.getNoteTable().updateResourceContentHash(r.getNoteGuid(), oldHash, newHash);
Data data = r.getData();
browserWindow.getBrowser().triggerPageAction(WebAction.Reload);
}
+ if (externalWindows.containsKey(r.getNoteGuid())) {
+ QWebSettings.setMaximumPagesInCache(0);
+ QWebSettings.setObjectCacheCapacities(0, 0, 0);
+ externalWindows.get(r.getNoteGuid()).getBrowserWindow().getBrowser().triggerPageAction(WebAction.Reload);
+
+ }
+
logger.log(logger.HIGH, "Exiting externalFielEdited");
}
// This is a timer event that tries to save any external files that were edited. This
// If an attachment on the current note was edited, we need to update the current notes's hash
// Update a note content's hash. This happens if a resource is edited outside of NN
- public void updateResourceContentHash(String guid, String oldHash, String newHash) {
+ public void updateResourceContentHash(BrowserWindow browser, String guid, String oldHash, String newHash) {
int position = browserWindow.getContent().indexOf("en-tag=\"en-media\" guid=\""+guid+"\" type=");
int endPos;
for (;position>-1;) {
- endPos = browserWindow.getContent().indexOf(">", position+1);
- String oldSegment = browserWindow.getContent().substring(position,endPos);
+ endPos = browser.getContent().indexOf(">", position+1);
+ String oldSegment = browser.getContent().substring(position,endPos);
int hashPos = oldSegment.indexOf("hash=\"");
int hashEnd = oldSegment.indexOf("\"", hashPos+7);
String hash = oldSegment.substring(hashPos+6, hashEnd);
if (hash.equalsIgnoreCase(oldHash)) {
String newSegment = oldSegment.replace(oldHash, newHash);
- String content = browserWindow.getContent().substring(0,position) +
+ String content = browser.getContent().substring(0,position) +
newSegment +
- browserWindow.getContent().substring(endPos);
- browserWindow.getBrowser().setContent(new QByteArray(content));;
+ browser.getContent().substring(endPos);
+ browser.getBrowser().setContent(new QByteArray(content));;
}
- position = browserWindow.getContent().indexOf("en-tag=\"en-media\" guid=\""+guid+"\" type=", position+1);
+ position = browser.getContent().indexOf("en-tag=\"en-media\" guid=\""+guid+"\" type=", position+1);
}
}
dformats = new ArrayList<String>();\r
tformats = new ArrayList<String>();\r
\r
- dformats.add("MM/dd/yy - 12/31/09");\r
- dformats.add("MM/dd/yyyy - 12/31/2009");\r
- dformats.add("dd/MM/yy - 31/12/09");\r
- dformats.add("dd/MM/yyyy - 31/12/2009");\r
- dformats.add("yyyy/MM/dd - 2009/12/31");\r
- dformats.add("yy/MM/dd - 9/12/31");\r
+ dformats.add("MM/dd/yy - 02/03/09");\r
+ dformats.add("MM/dd/yyyy - 02/03/2009");\r
+ dformats.add("M/dd/yyyy - 2/03/2009");\r
+ dformats.add("M/d/yyyy - 2/3/2009");\r
+ dformats.add("dd/MM/yy - 03/02/09");\r
+ dformats.add("d/M/yy - 3/2/09");\r
+ dformats.add("dd/MM/yyyy - 03/02/2009");\r
+ dformats.add("d/M/yyyy - 3/2/2009");\r
+ dformats.add("yyyy/MM/dd - 2009/02/03");\r
+ dformats.add("yy/MM/dd - 09/02/03");\r
\r
- tformats.add("HH:mm:ss - 2:13:01");\r
- tformats.add("HH:mm:ss a - 2:13:01 am");\r
- tformats.add("HH:mm - 2:13");\r
- tformats.add("HH:mm a - 2:13 am");\r
+ tformats.add("HH:mm:ss - 18:13:01");\r
+ tformats.add("HH:mm:ss a - 18:13:01 pm");\r
+ tformats.add("HH:mm - 18:13");\r
+ tformats.add("HH:mm a - 18:13 pm");\r
+ tformats.add("hh:mm:ss - 06:13:01");\r
+ tformats.add("hh:mm:ss a - 06:13:01 pm");\r
+ tformats.add("h:mm:ss a - 6:13:01 pm");\r
+ tformats.add("hh:mm - 06:13");\r
+ tformats.add("hh:mm a - 06:13 pm");\r
+ tformats.add("h:mm a - 6:13 pm");\r
\r
\r
// Style sheet formats\r
\r
mimicEvernote = new QCheckBox(tr("Mimic Evernote Selection Behavior (Requires Restart)"));\r
showSplashScreen = new QCheckBox(tr("Show Splash Screen on Startup"));\r
- showTrayIcon = new QCheckBox(tr("Show Tray Icon"));\r
+ showTrayIcon = new QCheckBox(tr("Minimize To Tray"));\r
verifyDelete = new QCheckBox(tr("Verify Deletes"));\r
startMinimized = new QCheckBox(tr("Start Minimized"));\r
pdfPreview = new QCheckBox(tr("Display PDF Documents Inline"));\r
import cx.fbn.nevernote.utilities.AESEncrypter;\r
public class ConfigDialog extends QDialog {\r
private final QListWidget contentsWidget;\r
+ private final ConfigFontPage fontPage;\r
private final QStackedWidget pagesWidget;\r
private final ConfigConnectionPage connectionPage;\r
private final ConfigDebugPage debugPage;\r
contentsWidget.setSpacing(12);\r
\r
pagesWidget = new QStackedWidget(this);\r
+ fontPage = new ConfigFontPage(this);\r
connectionPage = new ConfigConnectionPage(this);\r
appearancePage = new ConfigAppearancePage(this);\r
indexPage = new ConfigIndexPage(this);\r
debugPage = new ConfigDebugPage(this);\r
spellPage = new ConfigSpellPage(this);\r
pagesWidget.addWidget(appearancePage);\r
+ pagesWidget.addWidget(fontPage);\r
pagesWidget.addWidget(indexPage);\r
pagesWidget.addWidget(spellPage);\r
pagesWidget.addWidget(connectionPage);\r
Global.setTimeFormat(timeFmt);\r
\r
Global.setSyncInterval(connectionPage.getSyncInterval());\r
+ \r
+ Global.setOverrideDefaultFont(fontPage.overrideFont());\r
+ Global.setDefaultFont(fontPage.getFont());\r
+ Global.setDefaultFontSize(fontPage.getFontSize());\r
\r
close();\r
}\r
formatsButton.setFlags(ItemFlag.ItemIsSelectable, ItemFlag.ItemIsEnabled);\r
formatsButton.setIcon(new QIcon(iconPath+"appearance.jpg"));\r
\r
+ QListWidgetItem fontButton = new QListWidgetItem(contentsWidget);\r
+ fontButton.setText(tr("Fonts"));\r
+ fontButton.setTextAlignment(AlignmentFlag.AlignHCenter.value());\r
+ fontButton.setFlags(ItemFlag.ItemIsSelectable, ItemFlag.ItemIsEnabled);\r
+ fontButton.setIcon(new QIcon(iconPath+"fontConfig.png"));\r
+ \r
QListWidgetItem indexButton = new QListWidgetItem(contentsWidget);\r
indexButton.setText(tr("Indexing"));\r
indexButton.setTextAlignment(AlignmentFlag.AlignHCenter.value());\r
--- /dev/null
+/*\r
+ * This file is part of NeverNote \r
+ * Copyright 2009 Randy Baumgarte\r
+ * \r
+ * This file may be licensed under the terms of of the\r
+ * GNU General Public License Version 2 (the ``GPL'').\r
+ *\r
+ * Software distributed under the License is distributed\r
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either\r
+ * express or implied. See the GPL for the specific language\r
+ * governing rights and limitations.\r
+ *\r
+ * You should have received a copy of the GPL along with this\r
+ * program. If not, go to http://www.gnu.org/licenses/gpl.html\r
+ * or write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+ *\r
+*/\r
+\r
+package cx.fbn.nevernote.dialog;\r
+\r
+import java.util.List;\r
+\r
+import com.trolltech.qt.gui.QCheckBox;\r
+import com.trolltech.qt.gui.QComboBox;\r
+import com.trolltech.qt.gui.QFontDatabase;\r
+import com.trolltech.qt.gui.QGridLayout;\r
+import com.trolltech.qt.gui.QGroupBox;\r
+import com.trolltech.qt.gui.QLabel;\r
+import com.trolltech.qt.gui.QVBoxLayout;\r
+import com.trolltech.qt.gui.QWidget;\r
+\r
+import cx.fbn.nevernote.Global;\r
+\r
+public class ConfigFontPage extends QWidget {\r
+ private final QCheckBox overrideFonts;\r
+ private final QComboBox fontList;\r
+ private final QComboBox fontSizeList;\r
+ private String font;\r
+ private String fontSize;\r
+ \r
+ public ConfigFontPage(QWidget parent) {\r
+ \r
+ font = Global.getDefaultFont();\r
+ fontSize = Global.getDefaultFontSize();\r
+ \r
+ // Group Box\r
+ QGroupBox fontGroup = new QGroupBox(tr("New Note Defaults"));\r
+ QGridLayout fontLayout = new QGridLayout();\r
+ overrideFonts = new QCheckBox(tr("Override Defaults")); \r
+ overrideFonts.setCheckable(true);\r
+ overrideFonts.setChecked(Global.overrideDefaultFont());\r
+ overrideFonts.clicked.connect(this, "toggleFontOverride(Boolean)");\r
+ fontLayout.addWidget(overrideFonts,1,2);\r
+ \r
+ \r
+ // Fonts\r
+ fontList = new QComboBox(); \r
+ fontList.activated.connect(this, "fontSelected(String)");\r
+ fontLayout.addWidget(new QLabel(tr("Font")),2,1);\r
+ fontLayout.addWidget(fontList,2,2);\r
+ \r
+ // Font Sizes\r
+ fontSizeList = new QComboBox(); \r
+ fontLayout.addWidget(fontSizeList,3,2);\r
+ fontSizeList.activated.connect(this, "fontSizeSelected(String)");\r
+ fontLayout.addWidget(new QLabel(tr("Size")),3,1);\r
+ fontGroup.setLayout(fontLayout);\r
+ fontLayout.setColumnStretch(2, 100);\r
+ toggleFontOverride(Global.overrideDefaultFont());\r
+ loadFonts();\r
+ loadSettings();\r
+ \r
+ \r
+ QVBoxLayout mainLayout = new QVBoxLayout();\r
+ mainLayout.addWidget(fontGroup);\r
+ mainLayout.addStretch(1);\r
+ setLayout(mainLayout);\r
+ }\r
+ \r
+ private void toggleFontOverride(Boolean value) {\r
+ fontList.setEnabled(value);\r
+ fontSizeList.setEnabled(value);\r
+ }\r
+ \r
+ private void loadFonts() {\r
+ QFontDatabase fonts = new QFontDatabase();\r
+ List<String> fontFamilies = fonts.families();\r
+ for (int i = 0; i < fontFamilies.size(); i++) {\r
+ if (font.equals(""))\r
+ font = fontFamilies.get(i);\r
+ fontList.addItem(fontFamilies.get(i));\r
+ if (i == 0) {\r
+ loadFontSize(fontFamilies.get(i));\r
+ }\r
+ }\r
+\r
+ }\r
+ \r
+ // Load the font combo box based upon the font selected\r
+ private void loadFontSize(String name) { \r
+ QFontDatabase db = new QFontDatabase(); \r
+ fontSizeList.clear();\r
+ List<Integer> points = db.pointSizes(name); \r
+ for (int i=0; i<points.size(); i++) { \r
+ if (fontSize.equals(""))\r
+ fontSize = points.get(i).toString();\r
+ fontSizeList.addItem(points.get(i).toString()); \r
+ }\r
+\r
+ }\r
+ \r
+ private void fontSelected(String font) {\r
+ this.font = font;\r
+ loadFontSize(font);\r
+ }\r
+ \r
+ private void fontSizeSelected(String size) {\r
+ this.fontSize = size;\r
+ }\r
+ \r
+ private void loadSettings() {\r
+ if (!Global.getDefaultFont().equals("")) {\r
+ int index = fontList.findText(Global.getDefaultFont());\r
+ fontList.setCurrentIndex(index);\r
+ }\r
+ if (!Global.getDefaultFontSize().equals("")) {\r
+ int index = fontSizeList.findText(Global.getDefaultFontSize());\r
+ fontSizeList.setCurrentIndex(index);\r
+ }\r
+ }\r
+ \r
+ public String getFont() {\r
+ return font;\r
+ }\r
+ public String getFontSize() {\r
+ return fontSize;\r
+ }\r
+ public boolean overrideFont() {\r
+ return overrideFonts.isChecked();\r
+ }\r
+ \r
+}\r
public void setHint(String h) {\r
hint.setText(h.replace("'", "'"));\r
}\r
+ public String getHint() {\r
+ return hint.text();\r
+ }\r
// Set the error message\r
public void setError(String e) {\r
error.setText(e);\r
private final QCheckBox localRemote;
private final QPushButton ok;
private List<Notebook> currentNotebooks;
+ private final QCheckBox isDefault;
+ private boolean startDefault;
+ private String startText;
// Constructor
public NotebookEdit() {
localRemote.setText(tr("Local Notebook"));
localRemote.setChecked(false);
grid.addWidget(localRemote, 2,1);
-
+
+ isDefault = new QCheckBox();
+ isDefault.setText(tr("Default Notebook"));
+ isDefault.setChecked(false);
+ isDefault.toggled.connect(this, "defaultNotebookChecked(Boolean)");
+ grid.addWidget(isDefault, 3,1);
+
QGridLayout buttonLayout = new QGridLayout();
ok = new QPushButton(tr("OK"));
ok.clicked.connect(this, "okButtonPressed()");
notebook.textChanged.connect(this, "textChanged()");
buttonLayout.addWidget(ok, 1, 1);
buttonLayout.addWidget(cancel, 1,2);
- grid.addLayout(buttonLayout,3,1);
+ grid.addLayout(buttonLayout,4,1);
}
// The OK button was pressed
// Set the notebook name
public void setNotebook(String name) {
+ if (name.equalsIgnoreCase("All Notebooks")) {
+ notebook.setEnabled(false);
+ localRemote.setEnabled(false);
+ isDefault.setEnabled(false);
+ }
notebook.setText(name);
+ startText = name;
}
// Is this a local notebook?
currentNotebooks = n;
}
+ // Get default notebook
+ public void setDefaultNotebook(boolean val) {
+ startDefault = val;
+ isDefault.setChecked(val);
+ if (val)
+ isDefault.setEnabled(true);
+ }
+ public boolean isDefaultNotebook() {
+ return isDefault.isChecked();
+ }
+
+ // Action when the default notebook icon is checked
+ private void defaultNotebookChecked(Boolean val) {
+ if (val != startDefault || !startText.equals(notebook.text()))
+ ok.setEnabled(true);
+ else
+ ok.setEnabled(false);
+ }
+
// Watch what text is being entered
@SuppressWarnings("unused")
private void textChanged() {
\r
package cx.fbn.nevernote.dialog;\r
\r
-import java.io.File;\r
import java.text.SimpleDateFormat;\r
+import java.util.ArrayList;\r
import java.util.List;\r
\r
import com.evernote.edam.notestore.NoteVersionId;\r
import com.evernote.edam.type.Note;\r
-import com.evernote.edam.type.Resource;\r
-import com.trolltech.qt.core.QByteArray;\r
-import com.trolltech.qt.core.QFile;\r
-import com.trolltech.qt.core.QIODevice;\r
+import com.trolltech.qt.core.QTemporaryFile;\r
import com.trolltech.qt.core.Qt.ContextMenuPolicy;\r
import com.trolltech.qt.gui.QComboBox;\r
import com.trolltech.qt.gui.QDialog;\r
import com.trolltech.qt.gui.QLabel;\r
import com.trolltech.qt.gui.QPushButton;\r
import com.trolltech.qt.gui.QVBoxLayout;\r
-import com.trolltech.qt.xml.QDomAttr;\r
-import com.trolltech.qt.xml.QDomDocument;\r
-import com.trolltech.qt.xml.QDomElement;\r
-import com.trolltech.qt.xml.QDomNodeList;\r
\r
import cx.fbn.nevernote.Global;\r
-import cx.fbn.nevernote.NeverNote;\r
import cx.fbn.nevernote.gui.BrowserWindow;\r
import cx.fbn.nevernote.sql.DatabaseConnection;\r
+import cx.fbn.nevernote.utilities.ApplicationLogger;\r
+import cx.fbn.nevernote.xml.NoteFormatter;\r
\r
public class OnlineNoteHistory extends QDialog {\r
public final QPushButton restoreAsNew;\r
public final QPushButton restore;\r
- private DatabaseConnection conn;\r
+ private final DatabaseConnection conn;\r
public final QComboBox historyCombo; \r
private final BrowserWindow browser;\r
+ private final ApplicationLogger logger;\r
+ List<QTemporaryFile> tempFiles;\r
\r
// Constructor\r
- public OnlineNoteHistory(DatabaseConnection c) {\r
+ public OnlineNoteHistory(ApplicationLogger l, DatabaseConnection c) {\r
setWindowTitle(tr("Online Note History"));\r
QVBoxLayout main = new QVBoxLayout();\r
setLayout(main);\r
\r
main.addLayout(comboLayout);\r
\r
+ conn = c;\r
browser = new BrowserWindow(conn);\r
main.addWidget(browser);\r
browser.titleLabel.setVisible(false);\r
main.addLayout(buttonLayout);\r
\r
browser.getBrowser().setContextMenuPolicy(ContextMenuPolicy.NoContextMenu);\r
-\r
+ tempFiles = new ArrayList<QTemporaryFile>();\r
+ logger = l;\r
}\r
\r
@SuppressWarnings("unused")\r
}\r
\r
public void setContent(Note currentNote) {\r
- StringBuffer b = rebuildNoteHTML(currentNote);\r
+ \r
+ \r
+ NoteFormatter formatter = new NoteFormatter(logger, conn, tempFiles);\r
+ formatter.setNote(currentNote, false);\r
+ formatter.setHighlight(null);\r
+ formatter.setNoteHistory(true);\r
+ \r
StringBuffer js = new StringBuffer();\r
-\r
+ \r
// We need to prepend the note with <HEAD></HEAD> or encoded characters are ugly \r
js.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"); \r
js.append("<style type=\"text/css\">en-crypt-temp { border-style:solid; border-color:blue; padding:1mm 1mm 1mm 1mm; }</style>");\r
js.append("</head>");\r
- js.append(b.toString());\r
+ js.append(formatter.rebuildNoteHTML());\r
js.append("</HTML>");\r
-// js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml2.dtd'>", "");\r
-// js.replace("<?xml version='1.0' encoding='UTF-8'?>", "");\r
\r
browser.setNote(currentNote);\r
browser.getBrowser().page().mainFrame().setHtml(js.toString());\r
}\r
+}\r
\r
- //*************************************************\r
- //* XML Modifying Methods\r
- //*************************************************\r
- private StringBuffer rebuildNoteHTML(Note note) {\r
- QDomDocument doc = new QDomDocument();\r
- QDomDocument.Result result = doc.setContent(note.getContent());\r
- if (!result.success) {\r
- return new StringBuffer(note.getContent());\r
- }\r
- \r
- doc = modifyTags(note, doc);\r
- QDomElement docElem = doc.documentElement();\r
- docElem.setTagName("Body");\r
- \r
- // Fix the stupid problem where inserting an <img> tag after an <a> tag (which is done\r
- // to get the <en-media> application tag to work properly) causes spaces to be inserted\r
- // between the <a> & <img>. This messes things up later. This is an ugly hack.\r
- String docString = doc.toString();\r
- StringBuffer html = new StringBuffer(docString.substring(docString.toLowerCase().indexOf("<body>")));\r
- \r
- for (int i=html.indexOf("<a en-tag=\"en-media\" ", 0); i>-1; i=html.indexOf("<a en-tag=\"en-media\" ", i)) {\r
- i=html.indexOf(">\n",i+1);\r
- int z = html.indexOf("<img",i);\r
- for (int j=z-1; j>i; j--) \r
- html.deleteCharAt(j);\r
- i=html.indexOf("/>", z+1);\r
- z = html.indexOf("</a>",i);\r
- for (int j=z-1; j>i+1; j--) \r
- html.deleteCharAt(j);\r
- } \r
- return html;\r
- } \r
\r
- \r
- \r
- private QDomDocument modifyTags(Note note, QDomDocument doc) {\r
- QDomElement docElem = doc.documentElement();\r
- \r
- // Modify en-media tags\r
- QDomNodeList anchors = docElem.elementsByTagName("en-media");\r
- int enMediaCount = anchors.length();\r
- for (int i=enMediaCount-1; i>=0; i--) {\r
- QDomElement enmedia = anchors.at(i).toElement();\r
- if (enmedia.hasAttribute("type")) {\r
- QDomAttr attr = enmedia.attributeNode("type");\r
- QDomAttr hash = enmedia.attributeNode("hash");\r
- String[] type = attr.nodeValue().split("/");\r
- String appl = type[1];\r
- \r
- if (type[0] != null) {\r
- if (type[0].equals("image")) {\r
- modifyImageTags(note, docElem, enmedia, hash);\r
- }\r
- if (!type[0].equals("image")) {\r
- modifyApplicationTags(note, doc, docElem, enmedia, hash, appl);\r
- }\r
-// if (type[0].equals("audio")) {\r
-// modifyApplicationTags(doc, docElem, enmedia, hash, appl);\r
-// }\r
- }\r
- }\r
- }\r
- \r
- // Modify todo tags\r
- anchors = docElem.elementsByTagName("en-todo");\r
- int enTodoCount = anchors.length();\r
- for (int i=enTodoCount-1; i>=0; i--) {\r
- QDomElement enmedia = anchors.at(i).toElement();\r
- modifyTodoTags(enmedia);\r
- }\r
- \r
- // Modify en-crypt tags\r
- anchors = docElem.elementsByTagName("en-crypt");\r
- int enCryptLen = anchors.length();\r
- for (int i=enCryptLen-1; i>=0; i--) {\r
- QDomElement enmedia = anchors.at(i).toElement();\r
- //enmedia.setAttribute("style","display:none");\r
- enmedia.setAttribute("contentEditable","false");\r
- enmedia.setAttribute("src", Global.getFileManager().getImageDirPath("encrypt.png"));\r
- enmedia.setAttribute("en-tag","en-crypt");\r
- enmedia.setAttribute("alt", enmedia.text());\r
- Global.cryptCounter++;\r
- enmedia.setAttribute("id", "crypt"+Global.cryptCounter.toString());\r
- String encryptedText = enmedia.text();\r
- \r
- // If the encryption string contains crlf at the end, remove them because they mess up the javascript.\r
- if (encryptedText.endsWith("\n"))\r
- encryptedText = encryptedText.substring(0,encryptedText.length()-1);\r
- if (encryptedText.endsWith("\r"))\r
- encryptedText = encryptedText.substring(0,encryptedText.length()-1);\r
- \r
- // Add the commands\r
- enmedia.setAttribute("onClick", "window.jambi.decryptText('crypt"+Global.cryptCounter.toString()+"', '"+encryptedText+"', '"+enmedia.attribute("hint")+"');");\r
- enmedia.setAttribute("onMouseOver", "style.cursor='hand'");\r
- enmedia.setTagName("img");\r
- enmedia.removeChild(enmedia.firstChild()); // Remove the actual encrypted text\r
- }\r
\r
- return doc;\r
- }\r
- \r
- \r
- \r
\r
- private void modifyApplicationTags(Note n, QDomDocument doc, QDomElement docElem, QDomElement enmedia, QDomAttr hash, String appl) {\r
- \r
- Resource r = null;\r
- for (int i=0; i<n.getResourcesSize(); i++) {\r
- String hashValue = hash.value();\r
- byte res[] = n.getResources().get(i).getData().getBodyHash();\r
- String resourceHashValue = new String(Global.byteArrayToHexString(res));\r
- if (resourceHashValue.equalsIgnoreCase(hashValue)) {\r
- r = n.getResources().get(i);\r
- i=n.getResourcesSize();\r
- }\r
- }\r
- \r
- if (r!= null) {\r
- if (r.getData()!=null) {\r
- // Did we get a generic applicaiton? Then look at the file name to \r
- // try and find a good application type for the icon\r
- if (appl.equalsIgnoreCase("octet-stream")) {\r
- if (r.getAttributes() != null && r.getAttributes().getFileName() != null) {\r
- String fn = r.getAttributes().getFileName();\r
- int pos = fn.indexOf(".");\r
- if (pos > -1) {\r
- appl = fn.substring(pos+1);\r
- }\r
- }\r
- }\r
- \r
- String fileDetails = null;\r
- if (r.getAttributes() != null && r.getAttributes().getFileName() != null && !r.getAttributes().getFileName().equals(""))\r
- fileDetails = r.getAttributes().getFileName();\r
- if (fileDetails != null && !fileDetails.equals("")) \r
- enmedia.setAttribute("href", "nnres://" +r.getGuid()+n.getUpdateSequenceNum() +Global.attachmentNameDelimeter +fileDetails);\r
- else\r
- enmedia.setAttribute("href", "nnres://" +r.getGuid()+n.getUpdateSequenceNum() +Global.attachmentNameDelimeter +appl);\r
- if (fileDetails == null || fileDetails.equals(""))\r
- fileDetails = "";\r
- enmedia.setAttribute("en-tag", "en-media");\r
- enmedia.setAttribute("guid", r.getGuid());\r
- enmedia.setTagName("a");\r
- QDomElement newText = doc.createElement("img");\r
- String icon = findIcon(appl);\r
- if (icon.equals("attachment.png"))\r
- icon = findIcon(fileDetails.substring(fileDetails.indexOf(".")+1));\r
- newText.setAttribute("src", Global.getFileManager().getImageDirPath(icon));\r
- newText.setAttribute("title", fileDetails);\r
- enmedia.removeChild(enmedia.firstChild());\r
- enmedia.appendChild(newText);\r
- }\r
- }\r
- }\r
- /**\r
- * find the appropriate icon for an attachment\r
- *\r
- * NFC TODO: duplicate of {@link NeverNote#findIcon(String)}\r
- */\r
- private String findIcon(String appl) {\r
- appl = appl.toLowerCase();\r
- String relativePath = appl + ".png";\r
- File f = Global.getFileManager().getImageDirFile(relativePath);\r
- if (f.exists()) {\r
- return relativePath;\r
- }\r
- return "attachment.png";\r
- }\r
- \r
\r
\r
\r
- \r
- \r
- \r
- private void modifyTodoTags(QDomElement todo) {\r
- todo.setAttribute("type", "checkbox");\r
- String checked = todo.attribute("checked");\r
- todo.removeAttribute("checked");\r
- if (checked.equalsIgnoreCase("true"))\r
- todo.setAttribute("checked", "");\r
- else\r
- todo.setAttribute("unchecked","");\r
- todo.setAttribute("value", checked);\r
- todo.setAttribute("onClick", "value=checked;window.jambi.contentChanged(); ");\r
- todo.setTagName("input");\r
- }\r
- \r
- \r
- private void modifyImageTags(Note note, QDomElement docElem, QDomElement enmedia, QDomAttr hash) {\r
- String type = enmedia.attribute("type");\r
- if (type.startsWith("image/"))\r
- type = "."+type.substring(6);\r
- else\r
- type="";\r
- \r
- Resource r = null;\r
- for (int i=0; i<note.getResourcesSize(); i++) {\r
- String hashValue = hash.value();\r
- byte res[] = note.getResources().get(i).getData().getBodyHash();\r
- String resourceHashValue = new String(Global.byteArrayToHexString(res));\r
- if (hashValue.equalsIgnoreCase(resourceHashValue)) {\r
- r = note.getResources().get(i);\r
- i=note.getResourcesSize();\r
- }\r
- }\r
- \r
- if (r==null)\r
- return;\r
- \r
- QFile tfile = new QFile(Global.getFileManager().getResDirPath(r.getGuid() + note.getUpdateSequenceNum() + type));\r
- if (!tfile.exists()) {\r
- if (r!= null && r.getData() != null && r.getData().getBody().length > 0) {\r
- tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));\r
- QByteArray binData = new QByteArray(r.getData().getBody());\r
- tfile.write(binData);\r
- tfile.close();\r
- enmedia.setAttribute("src", tfile.fileName());\r
- enmedia.setAttribute("en-tag", "en-media");\r
- enmedia.setNodeValue("");\r
- enmedia.setAttribute("guid", r.getGuid());\r
- enmedia.setTagName("img");\r
- }\r
- }\r
- enmedia.setAttribute("src", tfile.fileName());\r
- enmedia.setAttribute("en-tag", "en-media");\r
- enmedia.setNodeValue("");\r
- enmedia.setAttribute("guid", r.getGuid());\r
- enmedia.setTagName("img");\r
- }\r
-}\r
+\r
\r
import cx.fbn.nevernote.Global;\r
import cx.fbn.nevernote.utilities.ApplicationLogger;\r
+import cx.fbn.nevernote.utilities.Pair;\r
import cx.fbn.nevernote.xml.XMLCleanup;\r
import cx.fbn.nevernote.xml.XMLNoteRepair;\r
\r
// newContent = repair.parse(newContent, false);\r
// logger.log(logger.HIGH, "Check complete");\r
\r
+ logger.log(logger.HIGH, "Fixing encryption tags");\r
+ newContent = fixEncryptionTags(newContent);\r
+ \r
Tidy tidy = new Tidy();\r
TidyListener tidyListener = new TidyListener(logger);\r
tidy.setMessageListener(tidyListener);\r
\r
// byte html[] = newContent.getBytes();\r
// ByteArrayInputStream is = new ByteArrayInputStream(html);\r
-\r
+ logger.log(logger.HIGH, "Starting JTidy check");\r
+ logger.log(logger.EXTREME, "Start of JTidy Input");\r
+ logger.log(logger.EXTREME, newContent);\r
+ logger.log(logger.EXTREME, "End Of JTidy Input");\r
ByteArrayInputStream is = new ByteArrayInputStream(unicode.toByteArray());\r
ByteArrayOutputStream os = new ByteArrayOutputStream();\r
tidy.setInputEncoding("UTF-8");\r
-// tidy.setOutputEncoding("UTF-8");\r
tidy.parse(is, os);\r
- newContent = os.toString();\r
-// newContent = new QByteArray(codec.fromUnicode(os.toString())).toString();\r
+ String tidyContent = os.toString();\r
if (tidyListener.errorFound) {\r
logger.log(logger.LOW, "Note Contents Begin");\r
logger.log(logger.LOW, content);\r
logger.log(logger.LOW, "Note Contents End");\r
- newContent = null;\r
+ tidyContent = null;\r
} else {\r
if (newContent.trim().equals(""))\r
- newContent = null;\r
+ tidyContent = null;\r
}\r
\r
// If the repair above returned null, then the XML is foobar.\r
// We are done here.\r
- if (newContent == null) {\r
- // Houston, we've had a problem.\r
- logger.log(logger.LOW, "Parse error when converting to ENML");\r
- logger.log(logger.LOW, "Start of unmodified note HTML");\r
- logger.log(logger.LOW, content);\r
- logger.log(logger.LOW, "End of unmodified note HTML");\r
- logger.log(logger.LOW, "Start of modified note HTML");\r
- logger.log(logger.LOW, newContent);\r
- logger.log(logger.LOW, "End of modified note HTML");\r
-// logger.log(logger.LOW, result.errorMessage);\r
-// logger.log(logger.LOW, "Error Line:Column "+result.errorLine+":" +result.errorColumn);\r
- return null;\r
-\r
-\r
+ if (tidyContent != null) {\r
+ newContent = tidyContent;\r
+ } else {\r
+ // Houston, we've had a problem. Fall back to old method\r
+ logger.log(logger.HIGH, "Error converting to JTidy. Falling back to old method");\r
+ String repairedContent = repair.parse(newContent, false);\r
+ if (repairedContent == null) {\r
+ logger.log(logger.EXTREME, "Null returned from repair.parse()");\r
+ logger.log(logger.LOW, "Parse error when converting to ENML. Aborting save");\r
+ return null;\r
+ }\r
+ newContent = repairedContent;\r
+ logger.log(logger.EXTREME, "Start of repaired content");\r
+ logger.log(logger.EXTREME, repairedContent);\r
+ logger.log(logger.EXTREME, "End of repaired content");\r
}\r
\r
// Second pass through the data. The goal of this pass is to \r
"<!DOCTYPE en-note SYSTEM \"" +dtd +"\">");\r
\r
logger.log(logger.HIGH, "Validating ENML");\r
- newContent = repair.parse(newContent, true);\r
+ String repairedContent = repair.parse(newContent, true);\r
+ if (repairedContent == null)\r
+ logger.log(logger.EXTREME, "Null returned from repair.parse()");\r
+ else\r
+ newContent = repairedContent;\r
logger.log(logger.HIGH, "Validation complete");\r
saveInvalidXML = repair.saveInvalidXML;\r
\r
"<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml2.dtd'>");\r
\r
\r
- \r
+ logger.log(logger.EXTREME, "Leaving ENMLConverter.convert()");\r
return newContent;\r
}\r
+\r
\r
+ private String fixEncryptionTags(String content) {\r
+ // Fix the problem that the document body isn't properly closed\r
+ String newContent = new String(content);\r
+ logger.log(logger.MEDIUM, "Inside EnmlConverter.fixEncryptionTags");\r
+ logger.log(logger.EXTREME, content);\r
+ \r
+ // Fix the problem that the img tag isn't properly closed\r
+ int endPos, startPos, endData,slotStart, slotEnd;\r
+ logger.log(logger.MEDIUM, "Checking table encryption tags");\r
+ String eTag = "<table class=\"en-crypt-temp\"";\r
+ for (int i=newContent.indexOf(eTag); i>0; i = newContent.indexOf(eTag,i+1)) {\r
+ slotStart = newContent.indexOf("slot", i+1)+6;\r
+ slotEnd = newContent.indexOf("\"",slotStart);\r
+ String slot = newContent.substring(slotStart, slotEnd);\r
+ startPos = newContent.indexOf("<td>", i+1)+4;\r
+ endData = newContent.indexOf("</td>",startPos);\r
+ String text = newContent.substring(startPos,endData);\r
+ endPos = newContent.indexOf("</table>",i+1)+8;\r
+ // Encrypt the text\r
+ Pair<String,String> pair;\r
+ Pair pair2 = Global.passwordSafe.get(slot);\r
+ pair = pair2;\r
+ String password = pair.getFirst();\r
+ String hint = pair.getSecond();\r
+ EnCrypt crypt = new EnCrypt(); \r
+ String encrypted = crypt.encrypt(text, password, 64); \r
+\r
+ // replace the table with an en-crypt tag.\r
+ newContent = newContent.substring(0,i-1) + \r
+ "<en-crypt-temp cipher=\"RC2\" length=\"64\" hint=\""+\r
+ hint +"\" value=\""+\r
+ encrypted +\r
+ "\" />" +\r
+ newContent.substring(endPos);\r
+ }\r
+ \r
+ return newContent;\r
+ }\r
\r
// Fix XML problems that Qt can't deal with\r
public String fixStupidXMLProblems(String content) {\r
// Fix the problem that the document body isn't properly closed\r
String newContent = new String(content);\r
logger.log(logger.MEDIUM, "Inside fixStupidXMLProblems. Old content:");\r
- logger.log(logger.MEDIUM, content);\r
+ logger.log(logger.EXTREME, content);\r
\r
// Fix the problem that the img tag isn't properly closed\r
int endPos;\r
\r
// Fix XML that Evernote thinks is invalid\r
public String fixEnXMLCrap(String note) {\r
+ logger.log(logger.EXTREME, "Entering EnmlConverter.fixEnXMLCrap");\r
if (note == null)\r
return null;\r
\r
int pos;\r
StringBuffer buffer = new StringBuffer(note);\r
\r
+ logger.log(logger.EXTREME, "Converting <b/>");\r
// change all <b/> to <b></b> because Evernote hates them if they happen in <span>\r
pos = buffer.indexOf("<b/>");\r
for (; pos>-1; ) {\r
pos = buffer.indexOf("<b/>",pos);\r
}\r
// change all <br/> to <br></br> because Evernote hates them if they happen in <span>\r
+ logger.log(logger.EXTREME, "converting <br/>");\r
pos = buffer.indexOf("<br/>");\r
for (; pos>-1; ) {\r
buffer.replace(pos, pos+5, "<br></br>");\r
int spanPos;\r
pos = buffer.indexOf("<li>");\r
spanPos = buffer.indexOf("<span>");\r
-/* for (; pos>-1 && spanPos >-1;) {\r
- endPos = buffer.indexOf("</li>",pos);\r
- if (spanPos > pos && spanPos < endPos) {\r
- buffer.replace(spanPos,spanPos+6,"");\r
- spanPos = buffer.indexOf("</span>"); \r
- buffer.replace(spanPos,spanPos+7,"");\r
- }\r
- pos=buffer.indexOf("<li>",pos+1);\r
- spanPos = buffer.indexOf("<span>",spanPos);\r
- }\r
-*/ \r
// Get rid of empty spans in <li> elements\r
pos = buffer.indexOf("<li>");\r
spanPos = buffer.indexOf("<span/>");\r
spanPos = buffer.indexOf("<span/>",spanPos);\r
}\r
\r
+ logger.log(logger.EXTREME, "Leaving EnmlConverter.fixEnXMLCrap");\r
return buffer.toString();\r
}\r
\r
import com.trolltech.qt.core.QFileSystemWatcher;\r
import com.trolltech.qt.core.QIODevice;\r
import com.trolltech.qt.core.QMimeData;\r
+import com.trolltech.qt.core.QTextCodec;\r
import com.trolltech.qt.core.QUrl;\r
import com.trolltech.qt.core.Qt.Key;\r
import com.trolltech.qt.core.Qt.KeyboardModifier;\r
import cx.fbn.nevernote.sql.DatabaseConnection;\r
import cx.fbn.nevernote.utilities.ApplicationLogger;\r
import cx.fbn.nevernote.utilities.FileUtils;\r
+import cx.fbn.nevernote.utilities.Pair;\r
\r
public class BrowserWindow extends QWidget {\r
\r
spellCheckDialog = new SpellCheck(checker);\r
}\r
public void spellingError(SpellCheckEvent event) {\r
- System.out.println("**" +event.getInvalidWord());\r
errorsFound = true;\r
spellCheckDialog.setWord(event.getInvalidWord());\r
\r
// New Editor Button\r
private QPushButton newEditorButton(String name, String toolTip) {\r
QPushButton button = new QPushButton();\r
- QIcon icon = new QIcon(iconPath + name + ".gif");\r
+// QIcon icon = new QIcon(iconPath + name + ".gif");\r
+ QIcon icon = new QIcon(iconPath + name + ".png");\r
button.setIcon(icon);\r
button.setToolTip(toolTip);\r
button.clicked.connect(this, name + "Clicked()");\r
// New Editor Button\r
private QToolButton newToolButton(String name, String toolTip) {\r
QToolButton button = new QToolButton();\r
- QIcon icon = new QIcon(iconPath + name + ".gif");\r
+// QIcon icon = new QIcon(iconPath + name + ".gif");\r
+ QIcon icon = new QIcon(iconPath + name + ".png");\r
button.setIcon(icon);\r
button.setToolTip(toolTip);\r
button.clicked.connect(this, name + "Clicked()");\r
String text = browser.selectedText();\r
if (text.trim().equalsIgnoreCase(""))\r
return;\r
+ text = new String(text.replaceAll("\n", "<br/>"));\r
\r
EnCryptDialog dialog = new EnCryptDialog();\r
dialog.exec();\r
\r
EnCrypt crypt = new EnCrypt();\r
String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64);\r
+ String decrypted = crypt.decrypt(encrypted, dialog.getPassword().trim(), 64);\r
\r
if (encrypted.trim().equals("")) {\r
QMessageBox.information(this, tr("Error"), tr("Error Encrypting String"));\r
+ dialog.getHint().replace("'","\\'") + "\" length=\"64\" ");\r
buffer.append("contentEditable=\"false\" alt=\"");\r
buffer.append(encrypted);\r
- // NFC FIXME: should this be a file URL like in handleLocalAttachment and importAttachment?\r
buffer.append("\" src=\"").append(FileUtils.toForwardSlashedPath(Global.getFileManager().getImageDirPath("encrypt.png") +"\""));\r
Global.cryptCounter++;\r
buffer.append(" id=\"crypt"+Global.cryptCounter.toString() +"\"");\r
\r
// First, try to decrypt with any keys we already have\r
for (int i=0; i<Global.passwordRemember.size(); i++) {\r
- plainText = crypt.decrypt(text, Global.passwordRemember.get(i), 64);\r
+ plainText = crypt.decrypt(text, Global.passwordRemember.get(i).getFirst(), 64);\r
if (plainText != null) {\r
slot = new String(Long.toString(l));\r
+ Pair<String,String> passwordPair = new Pair<String,String>();\r
Global.passwordSafe.put(slot, Global.passwordRemember.get(i));\r
removeEncryption(id, plainText, false, slot); \r
return;\r
QMessageBox.warning(this, "Incorrect Password", "The password entered is not correct");\r
}\r
}\r
- Global.passwordSafe.put(slot, dialog.getPassword());\r
+ Pair<String,String> passwordPair = new Pair<String,String>();\r
+ passwordPair.setFirst(dialog.getPassword());\r
+ passwordPair.setSecond(dialog.getHint());\r
+ Global.passwordSafe.put(slot, passwordPair);\r
+// removeEncryption(id, plainText.replaceAll("\n", "<br/>"), dialog.permanentlyDecrypt(), slot);\r
removeEncryption(id, plainText, dialog.permanentlyDecrypt(), slot);\r
- if (dialog.rememberPassword())\r
- Global.passwordRemember.add(dialog.getPassword());\r
+ if (dialog.rememberPassword()) {\r
+ Pair<String, String> pair = new Pair<String,String>();\r
+ pair.setFirst(dialog.getPassword());\r
+ pair.setSecond(dialog.getHint());\r
+ Global.passwordRemember.add(pair);\r
+ }\r
\r
}\r
\r
String newTagArray[];\r
if (!completionText.equals("")) {\r
String before = tagEdit.text().substring(0,tagEdit.cursorPosition());\r
- before = before.substring(0,before.lastIndexOf(Global.tagDelimeter));\r
+ int lastDelimiter = before.lastIndexOf(Global.tagDelimeter);\r
+ if (lastDelimiter > 0)\r
+ before = before.substring(0,before.lastIndexOf(Global.tagDelimeter));\r
+ else \r
+ before = "";\r
String after = tagEdit.text().substring(tagEdit.cursorPosition());\r
newTagArray = (before+Global.tagDelimeter+completionText+Global.tagDelimeter+after).split(Global.tagDelimeter);\r
}\r
}\r
}\r
}\r
+ \r
+ \r
+ // Set the notebook for a note\r
+ public void setNotebook(String notebook) {\r
+ currentNote.setNotebookGuid(notebook);\r
+ loadNotebookList();\r
+ }\r
\r
// Get the contents of the editor\r
public String getContent() {\r
\r
PDFPreview pdfPreview = new PDFPreview();\r
if (pdfPreview.setupPreview(Global.getFileManager().getResDirPath(fileName), "pdf",0)) {\r
- // NFC TODO: should this be a 'file://' url like the ones above?\r
imageURL = file.fileName() + ".png";\r
}\r
}\r
// * User chose to save an attachment. Pares out the request *\r
// * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!! \r
// ************************************************************\r
- // NFC TODO: unused? remove\r
public void downloadImage(QNetworkRequest request) {\r
QFileDialog fd = new QFileDialog(this);\r
fd.setFileMode(FileMode.AnyFile);\r
// *************************************************************\r
private void removeEncryption(String id, String plainText, boolean permanent, String slot) {\r
if (!permanent) {\r
- plainText = " <en-crypt-temp slot=\""+slot +"\">" +plainText+"</en-crypt-temp> ";\r
+ plainText = " <table class=\"en-crypt-temp\" slot=\""\r
+ +slot \r
+ +"\""\r
+ +"border=1 width=100%><tbody><tr><td>"\r
+ +plainText+"</td></tr></tbody></table>";\r
}\r
\r
String html = browser.page().mainFrame().toHtml();\r
endPos = text.indexOf(">", imagePos);\r
String tag = text.substring(imagePos-1,endPos);\r
if (tag.indexOf("id=\""+id+"\"") > -1) {\r
- text = text.substring(0,imagePos) +plainText+text.substring(endPos+1);\r
- \r
- browser.setContent(new QByteArray(text));\r
- contentChanged();\r
+ text = text.substring(0,imagePos) +plainText+text.substring(endPos+1); \r
+ QTextCodec codec = QTextCodec.codecForName("UTF-8");\r
+ QByteArray unicode = codec.fromUnicode(text);\r
+ browser.setContent(unicode);\r
+ if (permanent)\r
+ contentChanged();\r
}\r
imagePos = text.indexOf("<img", imagePos+1);\r
}\r
+" var workingNode = window.getSelection().anchorNode.parentNode;"\r
+" while(workingNode != null) { " \r
// +" window.jambi.printNode(workingNode.nodeName);"\r
- +" if (workingNode.nodeName=='EN-CRYPT-TEMP') window.jambi.forceTextPaste();"\r
+ +" if (workingNode.nodeName=='TABLE') { if (workingNode.getAttribute('class').toLowerCase() == 'en-crypt-temp') window.jambi.forceTextPaste(); }"\r
+" if (workingNode.nodeName=='B') window.jambi.boldActive();"\r
+" if (workingNode.nodeName=='I') window.jambi.italicActive();"\r
+" if (workingNode.nodeName=='U') window.jambi.underlineActive();"\r
QKeyEvent ke = (QKeyEvent) event;\r
if (ke.key() == Qt.Key.Key_Tab.value()) {\r
parent.tabPressed();\r
+ ke.accept();\r
return true;\r
}\r
if (ke.key() == Qt.Key.Key_Backtab.value()) {\r
--- /dev/null
+/*\r
+ * This file is part of NeverNote \r
+ * Copyright 2009 Randy Baumgarte\r
+ * \r
+ * This file may be licensed under the terms of of the\r
+ * GNU General Public License Version 2 (the ``GPL'').\r
+ *\r
+ * Software distributed under the License is distributed\r
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either\r
+ * express or implied. See the GPL for the specific language\r
+ * governing rights and limitations.\r
+ *\r
+ * You should have received a copy of the GPL along with this\r
+ * program. If not, go to http://www.gnu.org/licenses/gpl.html\r
+ * or write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+ *\r
+*/\r
+\r
+package cx.fbn.nevernote.gui;\r
+\r
+import java.util.List;\r
+\r
+import com.trolltech.qt.gui.QCloseEvent;\r
+import com.trolltech.qt.gui.QMdiSubWindow;\r
+\r
+import cx.fbn.nevernote.Global;\r
+import cx.fbn.nevernote.sql.DatabaseConnection;\r
+\r
+public class ExternalBrowse extends QMdiSubWindow {\r
+ private final DatabaseConnection conn;\r
+ private final BrowserWindow browser;\r
+ public Signal4<String, String, Boolean, BrowserWindow> contentsChanged;\r
+ public Signal1<String> windowClosing;\r
+ boolean noteDirty;\r
+ \r
+ // Constructor\r
+ public ExternalBrowse(DatabaseConnection c) {\r
+ setWindowTitle(tr("NeverNote"));\r
+ conn = c;\r
+ contentsChanged = new Signal4<String, String, Boolean, BrowserWindow>();\r
+ windowClosing = new Signal1<String>();\r
+ browser = new BrowserWindow(conn);\r
+ setWidget(browser);\r
+ noteDirty = false;\r
+ browser.titleLabel.textChanged.connect(this, "titleChanged(String)");\r
+ browser.getBrowser().page().contentsChanged.connect(this, "contentChanged()");\r
+ }\r
+ \r
+ private void contentChanged() {\r
+ noteDirty = true;\r
+ contentsChanged.emit(getBrowserWindow().getNote().getGuid(), getBrowserWindow().getContent(), false, getBrowserWindow());\r
+ }\r
+\r
+ \r
+ @Override\r
+ public void closeEvent(QCloseEvent event) {\r
+ if (noteDirty) \r
+ contentsChanged.emit(getBrowserWindow().getNote().getGuid(), getBrowserWindow().getContent(), true, getBrowserWindow());\r
+ windowClosing.emit(getBrowserWindow().getNote().getGuid());\r
+ }\r
+ \r
+ public BrowserWindow getBrowserWindow() {\r
+ return browser;\r
+ }\r
+ \r
+ private void titleChanged(String value) {\r
+ setWindowTitle(tr("NeverNote - ") +value);\r
+ }\r
+ \r
+ private void updateTitle(String guid, String title) {\r
+ if (guid.equals(getBrowserWindow().getNote().getGuid())) {\r
+ getBrowserWindow().loadingData(true);\r
+ getBrowserWindow().setTitle(title);\r
+ getBrowserWindow().getNote().setTitle(title);\r
+ getBrowserWindow().loadingData(false);\r
+ }\r
+ }\r
+ private void updateNotebook(String guid, String notebook) {\r
+ if (guid.equals(getBrowserWindow().getNote().getGuid())) {\r
+ getBrowserWindow().loadingData(true);\r
+ getBrowserWindow().setNotebook(notebook);\r
+ getBrowserWindow().loadingData(false);\r
+ }\r
+ }\r
+ \r
+ private void updateTags(String guid, List<String> tags) {\r
+ if (guid.equals(getBrowserWindow().getNote().getGuid())) {\r
+ StringBuffer tagLine = new StringBuffer(100);\r
+ for (int i=0; i<tags.size(); i++) {\r
+ if (i>0)\r
+ tagLine.append(Global.tagDelimeter+" ");\r
+ tagLine.append(tags.get(i));\r
+ \r
+ }\r
+ getBrowserWindow().loadingData(true);\r
+ getBrowserWindow().getTagLine().setText(tagLine.toString());\r
+ getBrowserWindow().loadingData(false);\r
+ }\r
+ }\r
+\r
+}\r
public QAction editPasteWithoutFormat; // Paste selected text\r
public QAction editCopy; // Copy selected text;\r
\r
+ public QAction wideListView; // View with list on the top\r
+ public QAction narrowListView; // View with list on the side\r
public QAction thumbnailView; // view thumbnails\r
public QAction hideSavedSearches; // show/hide saved searches\r
public QAction hideNotebooks; // show/hide notebooks\r
hideNotebooks.setChecked(true);\r
setupShortcut(hideNotebooks, "View_Show_Notebooks");\r
\r
+ wideListView = new QAction(tr("Wide List View"), this);\r
+ wideListView.setToolTip("Wide List Viwe");\r
+ wideListView.setCheckable(true);\r
+ wideListView.changed.connect(parent, "wideListView()");\r
+ setupShortcut(wideListView, "View_Wide_List");\r
+ \r
+ narrowListView = new QAction(tr("Narrow List View"), this);\r
+ narrowListView.setToolTip("Narrow List View");\r
+ narrowListView.setCheckable(true);\r
+ narrowListView.changed.connect(parent, "narrowListView()");\r
+ setupShortcut(narrowListView, "View_Narrow_List");\r
+ \r
thumbnailView = new QAction(tr("Preview"), this);\r
thumbnailView.setToolTip("Preview Notes");\r
thumbnailView.triggered.connect(parent, "thumbnailView()");\r
viewMenu = addMenu(tr("&View"));\r
viewMenu.addAction(noteAttributes);\r
viewMenu.addSeparator();\r
+ viewMenu.addAction(wideListView);\r
+ viewMenu.addAction(narrowListView);\r
viewMenu.addAction(thumbnailView);\r
viewMenu.addSeparator();\r
viewMenu.addAction(hideNoteList);\r
import com.trolltech.qt.core.QDateTime;\r
import com.trolltech.qt.core.QModelIndex;\r
import com.trolltech.qt.core.Qt;\r
+import com.trolltech.qt.core.Qt.AspectRatioMode;\r
import com.trolltech.qt.gui.QAbstractTableModel;\r
import com.trolltech.qt.gui.QColor;\r
+import com.trolltech.qt.gui.QPixmap;\r
\r
import cx.fbn.nevernote.Global;\r
import cx.fbn.nevernote.filters.NoteSortFilterProxyModel;\r
case Qt.ItemDataRole.DisplayRole: {\r
return valueAt(index.row(), index.column());\r
}\r
+ case Qt.ItemDataRole.DecorationRole: {\r
+ if (index.column() == Global.noteTableThumbnailPosition)\r
+ return valueAt(index.row(), index.column());\r
+ else\r
+ return null;\r
+ }\r
case Qt.ItemDataRole.BackgroundRole: {\r
String guid = (String)valueAt(index.row(), Global.noteTableGuidPosition);\r
QColor backgroundColor = new QColor(QColor.white);\r
return listManager.getNotebookIndex().get(i).getName();\r
}\r
}\r
+ if (col == Global.noteTableGuidPosition) {\r
+ return note.getGuid();\r
+ }\r
+ if (col == Global.noteTableThumbnailPosition) {\r
+ if (listManager.getThumbnails().get(note.getGuid()) == null)\r
+ return null;\r
+ if (Global.listView)\r
+ return QPixmap.fromImage(listManager.getThumbnails().get(note.getGuid())).scaled(Global.smallThumbnailSize, AspectRatioMode.KeepAspectRatio);\r
+ else\r
+ return QPixmap.fromImage(listManager.getThumbnails().get(note.getGuid())).scaled(Global.largeThumbnailSize, AspectRatioMode.KeepAspectRatio);\r
+ \r
+ }\r
return "";\r
}\r
\r
\r
public NotebookTreeWidget() {\r
noteSignal = new NoteSignal();\r
+ setProperty("hideTree", true);\r
List<String> labels = new ArrayList<String>();\r
labels.add("Notebooks");\r
labels.add("");\r
public SavedSearchTreeWidget() {\r
// setAcceptDrops(true);\r
// setDragEnabled(true);\r
+ setProperty("hideTree", true);\r
setAcceptDrops(false);\r
setDragEnabled(false);\r
// setDragDropMode(QAbstractItemView.DragDropMode.DragDrop);\r
header.tagsAction.toggled.connect(this, "toggleTags(Boolean)");\r
header.notebookAction.toggled.connect(this, "toggleNotebook(Boolean)");\r
header.synchronizedAction.toggled.connect(this, "toggleSynchronized(Boolean)");\r
+ header.guidAction.toggled.connect(this, "toggleGuid(Boolean)");\r
+ header.thumbnailAction.toggled.connect(this, "toggleThumbnail(Boolean)");\r
\r
noteSignal = new NoteSignal();\r
setAcceptDrops(true);\r
runner.getNoteTableModel().setHeaderData(Global.noteTableSourceUrlPosition, Qt.Orientation.Horizontal, tr("Source Url"), Qt.ItemDataRole.DisplayRole);\r
runner.getNoteTableModel().setHeaderData(Global.noteTableSubjectDatePosition, Qt.Orientation.Horizontal, tr("Subject Date"), Qt.ItemDataRole.DisplayRole);\r
runner.getNoteTableModel().setHeaderData(Global.noteTableSynchronizedPosition, Qt.Orientation.Horizontal, tr("Synchronized"), Qt.ItemDataRole.DisplayRole);\r
+ runner.getNoteTableModel().setHeaderData(Global.noteTableThumbnailPosition, Qt.Orientation.Horizontal, tr("Thumbnail"), Qt.ItemDataRole.DisplayRole);\r
header.sortIndicatorChanged.connect(this, "resetViewport()");\r
\r
proxyModel = new NoteSortFilterProxyModel(this);\r
proxyModel.setSourceModel(runner.getNoteTableModel());\r
setAlternatingRowColors(false);\r
setModel(proxyModel);\r
-// setModel(runner.getNoteTableModel());\r
runner.getNoteTableModel().setSortProxyModel(proxyModel);\r
\r
setSortingEnabled(true);\r
proxyModel.clear();\r
setSortingEnabled(false);\r
QFontMetrics f = QApplication.fontMetrics();\r
- verticalHeader().setDefaultSectionSize(f.height());\r
+ if (Global.listView) {\r
+ if (!Global.isColumnVisible("thumbnail"))\r
+ verticalHeader().setDefaultSectionSize(f.height());\r
+ else\r
+ verticalHeader().setDefaultSectionSize(Global.smallThumbnailSize.height());\r
+ } else\r
+ verticalHeader().setDefaultSectionSize(Global.largeThumbnailSize.height());\r
for (int i=0; i<runner.getNoteIndex().size(); i++) {\r
if (Global.showDeleted == true && !runner.getNoteIndex().get(i).isActive())\r
proxyModel.addGuid(runner.getNoteIndex().get(i).getGuid());\r
public void insertRow(Note tempNote, boolean newNote, int row) {\r
if (newNote)\r
proxyModel.addGuid(tempNote.getGuid());\r
- \r
if (row > runner.getNoteTableModel().rowCount())\r
runner.getNoteTableModel().insertRow(0);\r
\r
row = runner.getNoteTableModel().rowCount();\r
runner.getNoteTableModel().insertRow(row);\r
}\r
- \r
if (newNote) {\r
QFontMetrics f = QApplication.fontMetrics();\r
fontHeight = f.height();\r
- for (int i=0; i<runner.getNoteTableModel().rowCount(); i++)\r
+ for (int i=0; i<runner.getNoteTableModel().rowCount(); i++) {\r
setRowHeight(i, fontHeight);\r
+ }\r
}\r
}\r
protected boolean filterAcceptsRow(int sourceRow, QModelIndex sourceParent) {\r
public int getColumnWidth(int col) {\r
return columnWidth(col);\r
}\r
-\r
-/*\r
- @Override\r
- public void scrollTo(final QModelIndex index, ScrollHint hint) {\r
- QRect area = viewport().rect();\r
- QRect rect = visualRect(index);\r
-\r
- if (rect.top() < area.top())\r
- verticalScrollBar().setValue(\r
- verticalScrollBar().value() + rect.top() - area.top());\r
- else if (rect.bottom() > area.bottom())\r
- verticalScrollBar().setValue(\r
- verticalScrollBar().value() + Math.min(\r
- rect.bottom() - area.bottom(), rect.top() - area.top()));\r
- update();\r
- }\r
- \r
- @Override\r
- protected void updateGeometries() {\r
- verticalScrollBar().setPageStep(viewport().height());\r
- verticalScrollBar().setRange(0, Math.max(0, viewport().height()));\r
- }\r
- @Override\r
- protected int verticalOffset() {\r
- return verticalScrollBar().value();\r
- }\r
-*/\r
\r
public void toggleSubjectDate(Boolean toggle) {\r
Global.saveColumnVisible("dateSubject", toggle);\r
Global.saveColumnVisible("synchronized", toggle);\r
setColumnHidden(Global.noteTableSynchronizedPosition, !toggle);\r
}\r
+ public void toggleGuid(Boolean toggle) {\r
+ Global.saveColumnVisible("guid", toggle);\r
+ setColumnHidden(Global.noteTableGuidPosition, !toggle);\r
+ } \r
+ public void toggleThumbnail(Boolean toggle) {\r
+ Global.saveColumnVisible("thumbnail", toggle);\r
+ int size;\r
+ if (!toggle) {\r
+ QFontMetrics f = QApplication.fontMetrics();\r
+ size = f.height();\r
+ verticalHeader().setDefaultSectionSize(f.height());\r
+ } else\r
+ size = Global.smallThumbnailSize.height();\r
+ for (int i=0; i<runner.getNoteTableModel().rowCount(); i++) {\r
+ setRowHeight(i, size);\r
+ }\r
+ \r
+ setColumnHidden(Global.noteTableThumbnailPosition, !toggle);\r
+ }\r
}\r
public QAction synchronizedAction;\r
public QAction authorAction;\r
public QAction urlAction;\r
+ public QAction thumbnailAction;\r
+ public QAction guidAction;\r
\r
\r
public TableViewHeader(Orientation orientation, QWidget parent) {\r
urlAction.setChecked(Global.isColumnVisible("sourceUrl"));\r
contextMenu.addAction(urlAction);\r
\r
+ thumbnailAction = new QAction(this);\r
+ thumbnailAction.setText(tr("Thumbnail"));\r
+ thumbnailAction.setCheckable(true);\r
+ thumbnailAction.setChecked(Global.isColumnVisible("thumbnail"));\r
+// contextMenu.addAction(thumbnailAction);\r
+ \r
+ guidAction = new QAction(this);\r
+ guidAction.setText(tr("Guid"));\r
+ guidAction.setCheckable(true);\r
+ guidAction.setChecked(Global.isColumnVisible("guid"));\r
+// contextMenu.addAction(guidAction);\r
+ \r
}\r
\r
@Override\r
package cx.fbn.nevernote.gui;\r
\r
-import com.trolltech.qt.core.QByteArray;\r
-import com.trolltech.qt.core.QFile;\r
+import com.trolltech.qt.core.QBuffer;\r
import com.trolltech.qt.core.QIODevice;\r
import com.trolltech.qt.core.QObject;\r
import com.trolltech.qt.core.QSize;\r
import com.trolltech.qt.gui.QPainter;\r
import com.trolltech.qt.webkit.QWebPage;\r
\r
-import cx.fbn.nevernote.Global;\r
+import cx.fbn.nevernote.sql.DatabaseConnection;\r
+import cx.fbn.nevernote.utilities.ListManager;\r
\r
public class Thumbnailer extends QObject {\r
public QWebPage page;\r
public QPainter painter;\r
public Signal1<String> finished;\r
public String guid;\r
+ private final DatabaseConnection conn;\r
+ private final QSize size;\r
+ public boolean idle = false;\r
+ private final ListManager listManager;\r
\r
- public Thumbnailer(String g, QSize s)\r
+ public Thumbnailer(DatabaseConnection conn, ListManager l)\r
{\r
- guid = g;\r
+ this.conn = conn;\r
finished = new Signal1<String>();\r
page = new QWebPage();\r
+ listManager = l;\r
painter = new QPainter();\r
-\r
+ size = new QSize(1024,768);\r
page.mainFrame().setScrollBarPolicy(Orientation.Horizontal, ScrollBarPolicy.ScrollBarAlwaysOff);\r
page.mainFrame().setScrollBarPolicy(Orientation.Vertical, ScrollBarPolicy.ScrollBarAlwaysOff);\r
page.loadFinished.connect(this, "loadFinished(Boolean)");\r
}\r
\r
- public void setContent(String content) {\r
- QFile file = new QFile(Global.getFileManager().getResDirPath("thumbnail-" + guid + ".html"));\r
- file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));\r
- file.write(new QByteArray(content));\r
- file.close(); \r
- page.mainFrame().load(new QUrl(QUrl.fromLocalFile(file.fileName()).toString()));\r
+ public void loadContent(String guid, String fileName) {\r
+ idle = false;\r
+ this.guid = guid;\r
+ page.setViewportSize(size);\r
+ page.mainFrame().load(new QUrl(QUrl.fromLocalFile(fileName)));\r
}\r
\r
\r
page.mainFrame().render(painter); //<<<< THIS CAN LOCKUP if height too big!!!!\r
painter.end();\r
\r
- image.save(Global.getFileManager().getResDirPath("thumbnail-" + guid + ".png"));\r
- finished.emit(guid);\r
+ image = image.scaled(new QSize(100,100));\r
+ \r
+ QBuffer buffer = new QBuffer();\r
+ buffer.open(QIODevice.OpenModeFlag.ReadWrite);\r
+ image.save(buffer);\r
+ conn.getNoteTable().setThumbnail(guid, buffer.data());\r
+ conn.getNoteTable().setThumbnailNeeded(guid, false);\r
+ \r
+ listManager.getThumbnails().remove(guid);\r
+ listManager.getThumbnails().put(guid, image);\r
+ finished.emit(guid); \r
+ \r
+ idle = true;\r
+ return;\r
}\r
}\r
private QAction emptyAction;\r
private QTreeWidgetItem trashItem;\r
private Integer trashCount; \r
+ private final String iconPath;\r
+ private final QIcon trashIcon;\r
+ private final QIcon trashFullIcon;\r
\r
public void setEmptyAction(QAction a) {\r
emptyAction = a;\r
\r
public TrashTreeWidget() {\r
trashCount = 0;\r
+ setProperty("hideTree", true);\r
+ iconPath = new String("classpath:cx/fbn/nevernote/icons/");\r
+ trashIcon = new QIcon(iconPath+"trash.png");\r
+ trashFullIcon = new QIcon(iconPath+"trash-full.png");\r
}\r
\r
public void updateCounts(Integer cnt) {\r
header().resizeSection(1, 0);\r
if (trashCount > 0) {\r
trashItem.setForeground(0, black); \r
- trashItem.setForeground(1, black); \r
+ trashItem.setForeground(1, black);\r
+ trashItem.setIcon(0, trashFullIcon);\r
} else {\r
+ trashItem.setIcon(0,trashIcon);\r
trashItem.setForeground(0, gray); \r
trashItem.setForeground(1, gray); \r
}\r
}\r
\r
public void load() {\r
- String iconPath = new String("classpath:cx/fbn/nevernote/icons/");\r
- QIcon trashIcon = new QIcon(iconPath+"trash.png");\r
trashItem = new QTreeWidgetItem();\r
trashItem.setIcon(0, trashIcon);\r
trashItem.setText(0, "Trash");\r
public Signal1<Integer> titleColorChanged = new Signal1<Integer>();\r
public Signal2<Note, Boolean> noteDownloaded = new Signal2<Note, Boolean>();\r
public Signal2<String, String> noteSaveRunnerError = new Signal2<String, String>();\r
+ public Signal2<String, String> thumbnailPageReady = new Signal2<String,String>();\r
}\r
\r
\r
// Update a note's title\r
public void updateNoteContent(String guid, String content) {\r
NSqlQuery query = new NSqlQuery(db.getConnection());\r
- boolean check = query.prepare("Update Note set content=:content, updated=CURRENT_TIMESTAMP(), isDirty=true, indexNeeded=true " +\r
- " where guid=:guid");\r
+ boolean check = query.prepare("Update Note set content=:content, updated=CURRENT_TIMESTAMP(), isDirty=true, indexNeeded=true, " +\r
+ " thumbnailneeded=true where guid=:guid");\r
if (!check) {\r
logger.log(logger.EXTREME, "Update note content sql prepare has failed.");\r
logger.log(logger.MEDIUM, query.lastError());\r
if (!check) \r
logger.log(logger.EXTREME, "Note SQL get thumbail failed: " +query.lastError().toString());\r
// Get a list of the notes\r
- if (query.next()) \r
- if (query.getBlob(0) != null)\r
- return new QByteArray(query.getBlob(0)); \r
+ if (query.next()) {\r
+ try {\r
+ if (query.getBlob(0) != null) {\r
+ return new QByteArray(query.getBlob(0)); \r
+ }\r
+ } catch (java.lang.IllegalArgumentException e) {\r
+ return null;\r
+ }\r
+ }\r
return null;\r
}\r
- \r
+ // Get a list of notes that need thumbnails\r
+ // Is a thumbail needed for this guid?\r
+ public List<String> findThumbnailsNeeded() {\r
+ \r
+ boolean check;\r
+ NSqlQuery query = new NSqlQuery(db.getConnection());\r
+ \r
+ check = query.prepare("select guid from note where thumbnailneeded = true limit 100");\r
+ check = query.exec();\r
+ if (!check) \r
+ logger.log(logger.EXTREME, "Note SQL findThumbnailsNeeded query failed: " +query.lastError().toString());\r
+ \r
+\r
+ // Get a list of the notes\r
+ List<String> values = new ArrayList<String>();\r
+ while (query.next()) {\r
+ values.add(query.valueString(0)); \r
+ }\r
+\r
+ return values; \r
+ }\r
\r
// Update a note content's hash. This happens if a resource is edited outside of NN\r
public void updateResourceContentHash(String guid, String oldHash, String newHash) {\r
newSegment +\r
n.getContent().substring(endPos);\r
NSqlQuery query = new NSqlQuery(db.getConnection());\r
- query.prepare("update note set isdirty=true, content=:content where guid=:guid");\r
+ query.prepare("update note set isdirty=true, thumbnailneeded=true, content=:content where guid=:guid");\r
query.bindValue(":content", content);\r
query.bindValue(":guid", n.getGuid());\r
query.exec();\r
}\r
// Reset the dirty flag. Typically done after a sync.\r
public void resetDirtyFlag(String guid) {\r
- \r
NSqlQuery query = new NSqlQuery(db.getConnection());\r
\r
query.prepare("Update notebook set isdirty='false' where guid=:guid");\r
if (!query.exec())\r
logger.log(logger.EXTREME, "Error resetting notebook dirty field.");\r
}\r
- \r
+ // Set the default notebook\r
+ public void setDefaultNotebook(String guid) {\r
+ NSqlQuery query = new NSqlQuery(db.getConnection());\r
+ \r
+ query.prepare("Update notebook set defaultNotebook=false");\r
+ if (!query.exec())\r
+ logger.log(logger.EXTREME, "Error removing default notebook.");\r
+ query.prepare("Update notebook set defaultNotebook=true where guid = :guid");\r
+ query.bindValue(":guid", guid);\r
+ if (!query.exec())\r
+ logger.log(logger.EXTREME, "Error setting default notebook.");\r
+ }\r
\r
\r
\r
private int indexType;\r
public final int CONTENT=1; \r
public final int RESOURCE=2;\r
- private boolean keepRunning;\r
+ public boolean keepRunning;\r
private final QDomDocument doc;\r
private static String regex = Global.getWordRegex();\r
private final DatabaseConnection conn;\r
public class SaveRunner extends QObject implements Runnable {\r
\r
private final ApplicationLogger logger;\r
- private volatile boolean keepRunning;\r
+ public volatile boolean keepRunning;\r
public QMutex threadLock;\r
private final DatabaseConnection conn;\r
private boolean idle;\r
\r
List<DeletedItemRecord> expunged = conn.getDeletedTable().getAllDeleted();\r
boolean error = false;\r
- for (int i=0; i<expunged.size(); i++) {\r
+ for (int i=0; i<expunged.size() && keepRunning; i++) {\r
\r
if (authRefreshNeeded)\r
refreshConnection();\r
--- /dev/null
+/*\r
+ * This file is part of NeverNote \r
+ * Copyright 2009 Randy Baumgarte\r
+ * \r
+ * This file may be licensed under the terms of of the\r
+ * GNU General Public License Version 2 (the ``GPL'').\r
+ *\r
+ * Software distributed under the License is distributed\r
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either\r
+ * express or implied. See the GPL for the specific language\r
+ * governing rights and limitations.\r
+ *\r
+ * You should have received a copy of the GPL along with this\r
+ * program. If not, go to http://www.gnu.org/licenses/gpl.html\r
+ * or write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+ *\r
+*/\r
+\r
+package cx.fbn.nevernote.threads;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.concurrent.LinkedBlockingQueue;\r
+\r
+import com.evernote.edam.type.Note;\r
+import com.trolltech.qt.core.QByteArray;\r
+import com.trolltech.qt.core.QFile;\r
+import com.trolltech.qt.core.QIODevice.OpenModeFlag;\r
+import com.trolltech.qt.core.QObject;\r
+import com.trolltech.qt.core.QTemporaryFile;\r
+\r
+import cx.fbn.nevernote.Global;\r
+import cx.fbn.nevernote.signals.NoteSignal;\r
+import cx.fbn.nevernote.sql.DatabaseConnection;\r
+import cx.fbn.nevernote.utilities.ApplicationLogger;\r
+import cx.fbn.nevernote.xml.NoteFormatter;\r
+\r
+public class ThumbnailRunner extends QObject implements Runnable {\r
+ \r
+ private final ApplicationLogger logger;\r
+ private String guid;\r
+ public NoteSignal noteSignal;\r
+ private boolean keepRunning;\r
+ private final DatabaseConnection conn;\r
+ private volatile LinkedBlockingQueue<String> workQueue;\r
+ private static int MAX_QUEUED_WAITING = 1000;\r
+\r
+\r
+\r
+ public ThumbnailRunner(String logname, String u, String uid, String pswd, String cpswd) {\r
+ logger = new ApplicationLogger(logname);\r
+ conn = new DatabaseConnection(logger, u, uid, pswd, cpswd);\r
+ noteSignal = new NoteSignal();\r
+ guid = null;\r
+ keepRunning = true;\r
+ workQueue=new LinkedBlockingQueue<String>(MAX_QUEUED_WAITING); \r
+ }\r
+ \r
+ \r
+ @Override\r
+ public void run() {\r
+ thread().setPriority(Thread.MIN_PRIORITY);\r
+ \r
+ logger.log(logger.MEDIUM, "Starting thumbnail thread ");\r
+ while (keepRunning) {\r
+ try {\r
+ String work = workQueue.take();\r
+ if (work.startsWith("GENERATE")) {\r
+ work = work.replace("GENERATE ", "");\r
+ guid = work;\r
+ generateThumbnail();\r
+ }\r
+ if (work.startsWith("SCAN")) {\r
+ scanDatabase();\r
+ }\r
+ if (work.startsWith("STOP")) {\r
+ logger.log(logger.MEDIUM, "Stopping thumbail thread");\r
+ keepRunning = false;\r
+ }\r
+ } catch (InterruptedException e) {\r
+ // TODO Auto-generated catch block\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ conn.dbShutdown();\r
+ }\r
+ \r
+ \r
+ private void scanDatabase() {\r
+ // If there is already work in the queue, that takes priority\r
+ logger.log(logger.HIGH, "Scanning database for notes needing thumbnail");\r
+ if (workQueue.size() > 0)\r
+ return;\r
+ \r
+ // Find a few records that need thumbnails\r
+ List<String> guids = conn.getNoteTable().findThumbnailsNeeded();\r
+ logger.log(logger.HIGH, guids.size() +" records returned");\r
+ for (int i=0; i<guids.size() && keepRunning; i++) {\r
+ guid = guids.get(i);\r
+ logger.log(logger.HIGH, "Working on:" +guids.get(i));\r
+ generateThumbnail();\r
+ }\r
+ logger.log(logger.HIGH, "Scan completed");\r
+ }\r
+\r
+ \r
+ public synchronized boolean addWork(String request) {\r
+ if (workQueue.size() == 0) {\r
+ workQueue.offer(request);\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+ \r
+ public synchronized int getWorkQueueSize() {\r
+ return workQueue.size();\r
+ }\r
+ \r
+ private void generateThumbnail() {\r
+ QByteArray js = new QByteArray();\r
+ logger.log(logger.HIGH, "Starting thumbnail for " +guid);\r
+ ArrayList<QTemporaryFile> tempFiles = new ArrayList<QTemporaryFile>();\r
+ Note currentNote = conn.getNoteTable().getNote(guid,true,true,false,true,false);\r
+ NoteFormatter formatter = new NoteFormatter(logger, conn, tempFiles);\r
+ currentNote = conn.getNoteTable().getNote(guid, true, true, false, true, false);\r
+ formatter.setNote(currentNote, true);\r
+ formatter.setHighlight(null);\r
+ js.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"); \r
+ js.append("<style type=\"text/css\">.en-crypt-temp { border-collapse:collapse; border-style:solid; border-color:blue; padding:0.0mm 0.0mm 0.0mm 0.0mm; }</style>");\r
+ js.append("<style type=\"text/css\">en-hilight { background-color: rgb(255,255,0) }</style>");\r
+ js.append("<style> img { max-width:100%; }</style>");\r
+ js.append("<style type=\"text/css\">en-spell { text-decoration: none; border-bottom: dotted 1px #cc0000; }</style>");\r
+ js.append("</head>");\r
+ js.append(formatter.rebuildNoteHTML());\r
+ js.append("</HTML>");\r
+ js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml.dtd'>", "");\r
+ js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml2.dtd'>", "");\r
+ js.replace("<?xml version='1.0' encoding='UTF-8'?>", "");\r
+ String fileName = Global.getFileManager().getResDirPath("thumbnail-" + guid + ".html");\r
+ QFile tFile = new QFile(fileName);\r
+ tFile.open(OpenModeFlag.WriteOnly);\r
+ tFile.write(js);\r
+ tFile.close();\r
+ logger.log(logger.HIGH, "Thumbnail file ready");\r
+ noteSignal.thumbnailPageReady.emit(guid, fileName);\r
+ }\r
+ \r
+ \r
+\r
+\r
+}\r
import com.evernote.edam.type.Tag;\r
import com.trolltech.qt.QThread;\r
import com.trolltech.qt.core.QDateTime;\r
+import com.trolltech.qt.gui.QImage;\r
import com.trolltech.qt.sql.QSqlQuery;\r
import com.trolltech.qt.xml.QDomAttr;\r
import com.trolltech.qt.xml.QDomDocument;\r
public NotebookSignal notebookSignal;\r
private int trashCount;\r
public SaveRunner saveRunner; // Thread used to save content. Used because the xml conversion is slowwwww\r
- QThread saveThread;\r
+ QThread saveThread;\r
\r
+ private final HashMap<String,QImage> thumbnailList;\r
+ \r
// Constructor\r
public ListManager(DatabaseConnection d, ApplicationLogger l) {\r
conn = d;\r
saveRunner = new SaveRunner("saveRunner.log", Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);\r
saveThread = new QThread(saveRunner, "Save Runner Thread");\r
saveThread.start();\r
-\r
+ \r
+ thumbnailList = new HashMap<String, QImage>();\r
+/* for (int i=0; i<getMasterNoteIndex().size(); i++) {\r
+ QImage img = new QImage();\r
+ QByteArray dbImage = conn.getNoteTable().getThumbnail(getMasterNoteIndex().get(i).getGuid());\r
+ if (dbImage != null) {\r
+ img.loadFromData(dbImage);\r
+ img.scaled(new QSize(400,400));\r
+ thumbnailList.put(getMasterNoteIndex().get(i).getGuid(), img);\r
+ }\r
+ }\r
+*/\r
loadNoteTitleColors();\r
\r
}\r
public List<Note> getMasterNoteIndex() {\r
return noteModel.getMasterNoteIndex();\r
}\r
- \r
+ // Thumbnails\r
+ public HashMap<String, QImage> getThumbnails() {\r
+ return thumbnailList;\r
+ }\r
//***************************************************************\r
//***************************************************************\r
//** These functions deal with setting & retrieving filters\r
return false;\r
}\r
\r
- \r
+ public void setNoteSynchronized(String guid, boolean value) {\r
+ getNoteTableModel().updateNoteSyncStatus(guid, value);\r
+ }\r
\r
public void updateNoteTitleColor(String guid, Integer color) {\r
noteModel.updateNoteTitleColor(guid, color);\r
private String notebookGuid;\r
public final boolean importTags = false;\r
public final boolean importNotebooks = false;\r
+ private final HashMap<String,String> tagMap;\r
+ private final HashMap<String,String> noteMap;\r
+ private final HashMap<String,String> notebookMap;\r
\r
public ImportData(DatabaseConnection c, boolean full) {\r
logger = new ApplicationLogger("import.log");\r
backup = full;\r
conn = c;\r
titleColors = new HashMap<String,Integer>();\r
+ notebookMap = new HashMap<String,String>();\r
+ tagMap = new HashMap<String,String>();\r
+ noteMap = new HashMap<String,String>();\r
}\r
\r
public void importData(String f) {\r
boolean atEnd = false;\r
while(!atEnd) {\r
if (reader.isStartElement()) {\r
- if (reader.name().equalsIgnoreCase("Guid")) \r
+ if (reader.name().equalsIgnoreCase("Guid")) { \r
note.setGuid(textValue());\r
- if (!backup) {\r
- Random random1 = new Random();\r
- String newGuid = "IMP" +new Integer(random1.nextInt(1000)).toString();\r
- newGuid = newGuid+"-"+new Integer(random1.nextInt(1000)).toString();\r
- newGuid = newGuid+"-"+new Integer(random1.nextInt(1000)).toString();\r
- newGuid = newGuid+"-"+new Integer(random1.nextInt(1000)).toString();\r
- note.setGuid(newGuid);\r
+ if (!backup) {\r
+ Random random1 = new Random();\r
+ String newGuid = "IMP" +new Integer(random1.nextInt(1000)).toString();\r
+ newGuid = newGuid+"-"+new Integer(random1.nextInt(1000)).toString();\r
+ newGuid = newGuid+"-"+new Integer(random1.nextInt(1000)).toString();\r
+ newGuid = newGuid+"-"+new Integer(random1.nextInt(1000)).toString();\r
+ noteMap.put(note.getGuid(), newGuid);\r
+ note.setGuid(newGuid);\r
+ } else \r
+ noteMap.put(note.getGuid(), note.getGuid());\r
}\r
if (reader.name().equalsIgnoreCase("UpdateSequenceNumber")) \r
note.setUpdateSequenceNum(intValue());\r
resource.setGuid(newGuid);\r
}\r
if (reader.name().equalsIgnoreCase("NoteGuid")) \r
- resource.setNoteGuid(textValue());\r
+ resource.setNoteGuid(noteMap.get(textValue()));\r
if (reader.name().equalsIgnoreCase("UpdateSequenceNumber")) \r
resource.setUpdateSequenceNum(intValue());\r
if (reader.name().equalsIgnoreCase("Active")) \r
--- /dev/null
+package cx.fbn.nevernote.xml;\r
+\r
+import java.io.File;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import com.evernote.edam.type.Note;\r
+import com.evernote.edam.type.Resource;\r
+import com.trolltech.qt.core.QByteArray;\r
+import com.trolltech.qt.core.QDataStream;\r
+import com.trolltech.qt.core.QFile;\r
+import com.trolltech.qt.core.QIODevice;\r
+import com.trolltech.qt.core.QTemporaryFile;\r
+import com.trolltech.qt.core.QUrl;\r
+import com.trolltech.qt.xml.QDomAttr;\r
+import com.trolltech.qt.xml.QDomDocument;\r
+import com.trolltech.qt.xml.QDomElement;\r
+import com.trolltech.qt.xml.QDomNodeList;\r
+\r
+import cx.fbn.nevernote.Global;\r
+import cx.fbn.nevernote.config.FileManager;\r
+import cx.fbn.nevernote.filters.EnSearch;\r
+import cx.fbn.nevernote.gui.PDFPreview;\r
+import cx.fbn.nevernote.sql.DatabaseConnection;\r
+import cx.fbn.nevernote.utilities.ApplicationLogger;\r
+\r
+public class NoteFormatter {\r
+\r
+ private final ApplicationLogger logger;\r
+ private final DatabaseConnection conn;\r
+ public boolean resourceError = false;\r
+ public boolean readOnly = false;\r
+ public boolean addHighlight = true;\r
+ private Note currentNote;\r
+ private String currentNoteGuid;\r
+ private boolean pdfPreview;\r
+ ArrayList<QTemporaryFile> tempFiles;\r
+ private EnSearch enSearch;\r
+ private boolean noteHistory;\r
+ \r
+ public NoteFormatter(ApplicationLogger logger, DatabaseConnection conn, List<QTemporaryFile> tempFiles2) {\r
+ this.logger = logger;\r
+ this.conn = conn;\r
+ noteHistory = false;\r
+ }\r
+ \r
+ \r
+ public void setNote(Note note, boolean pdfPreview) {\r
+ currentNote = note;\r
+ this.pdfPreview = pdfPreview;\r
+ currentNoteGuid = note.getGuid();\r
+ readOnly = false;\r
+ resourceError = false;\r
+ }\r
+ \r
+ public void setHighlight(EnSearch search) {\r
+ if (search==null || search.hilightWords == null ||search.hilightWords.size() == 0) {\r
+ enSearch = null;\r
+ addHighlight = false;\r
+ } else {\r
+ enSearch = search;\r
+ addHighlight = true;\r
+ }\r
+ }\r
+ \r
+ // Set if we are coming here through note histary. It triggers longer file names to avoid conflicts\r
+ public void setNoteHistory(boolean value) {\r
+ noteHistory = value;\r
+ }\r
+ \r
+ // Rebuild the note HTML to something usable\r
+ public String rebuildNoteHTML() {\r
+ logger.log(logger.HIGH, "Entering NeverNote.rebuildNoteHTML");\r
+ logger.log(logger.EXTREME, "Note guid: " +currentNoteGuid);\r
+ logger.log(logger.EXTREME, "Note Text:" +currentNote);\r
+ QDomDocument doc = new QDomDocument();\r
+ QDomDocument.Result result = doc.setContent(currentNote.getContent());\r
+ if (!result.success) {\r
+ logger.log(logger.MEDIUM, "Parse error when rebuilding HTML");\r
+ logger.log(logger.MEDIUM, "Note guid: " +currentNoteGuid);\r
+ logger.log(logger.EXTREME, "Start of unmodified note HTML");\r
+ logger.log(logger.EXTREME, currentNote.getContent());\r
+ logger.log(logger.EXTREME, "End of unmodified note HTML");\r
+ return currentNote.getContent();\r
+ }\r
+\r
+ if (tempFiles == null)\r
+ tempFiles = new ArrayList<QTemporaryFile>();\r
+ tempFiles.clear();\r
+ \r
+ doc = modifyTags(doc);\r
+ if (addHighlight)\r
+ doc = addHilight(doc);\r
+ QDomElement docElem = doc.documentElement();\r
+ docElem.setTagName("Body");\r
+// docElem.setAttribute("bgcolor", "green");\r
+ logger.log(logger.EXTREME, "Rebuilt HTML:");\r
+ logger.log(logger.EXTREME, doc.toString()); \r
+ logger.log(logger.HIGH, "Leaving NeverNote.rebuildNoteHTML");\r
+ // Fix the stupid problem where inserting an <img> tag after an <a> tag (which is done\r
+ // to get the <en-media> application tag to work properly) causes spaces to be inserted\r
+ // between the <a> & <img>. This messes things up later. This is an ugly hack.\r
+ StringBuffer html = new StringBuffer(doc.toString());\r
+ for (int i=html.indexOf("<a en-tag=\"en-media\" ", 0); i>-1; i=html.indexOf("<a en-tag=\"en-media\" ", i)) {\r
+ i=html.indexOf(">\n",i+1);\r
+ int z = html.indexOf("<img",i);\r
+ for (int j=z-1; j>i; j--) \r
+ html.deleteCharAt(j);\r
+ i=html.indexOf("/>", z+1);\r
+ z = html.indexOf("</a>",i);\r
+ for (int j=z-1; j>i+1; j--) \r
+ html.deleteCharAt(j);\r
+ } \r
+ return html.toString();\r
+ } \r
+\r
+ \r
+ // Modify the en-media tag into an image tag so it can be displayed.\r
+ private void modifyImageTags(QDomElement docElem, QDomElement enmedia, QDomAttr hash) {\r
+ logger.log(logger.HIGH, "Entering NeverNote.modifyImageTags");\r
+ String type = enmedia.attribute("type");\r
+ if (type.startsWith("image/"))\r
+ type = "."+type.substring(6);\r
+ else\r
+ type="";\r
+ \r
+ String resGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(currentNoteGuid, hash.value());\r
+ QFile tfile = new QFile(Global.getFileManager().getResDirPath(resGuid + type));\r
+ if (!tfile.exists()) {\r
+ Resource r = null;\r
+ if (resGuid != null)\r
+ r = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid,true);\r
+ if (r==null || r.getData() == null || r.getData().getBody().length == 0)\r
+ resourceError = true;;\r
+ if (r!= null && r.getData() != null && r.getData().getBody().length > 0) {\r
+ tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly));\r
+ QByteArray binData = new QByteArray(r.getData().getBody());\r
+ tfile.write(binData);\r
+ tfile.close();\r
+ enmedia.setAttribute("src", QUrl.fromLocalFile(tfile.fileName()).toString());\r
+ enmedia.setAttribute("en-tag", "en-media");\r
+ enmedia.setNodeValue("");\r
+ enmedia.setAttribute("guid", r.getGuid());\r
+ enmedia.setTagName("img");\r
+ }\r
+ }\r
+ enmedia.setAttribute("src", QUrl.fromLocalFile(tfile.fileName()).toString());\r
+ enmedia.setAttribute("en-tag", "en-media");\r
+ enmedia.setAttribute("onContextMenu", "window.jambi.imageContextMenu('" +tfile.fileName() +"');");\r
+ enmedia.setNodeValue("");\r
+ enmedia.setAttribute("guid", resGuid);\r
+ enmedia.setTagName("img");\r
+\r
+ logger.log(logger.HIGH, "Leaving NeverNote.modifyImageTags");\r
+ }\r
+ \r
+ \r
+ // Modify tags from Evernote specific things to XHTML tags.\r
+ private QDomDocument modifyTags(QDomDocument doc) {\r
+ logger.log(logger.HIGH, "Entering NeverNote.modifyTags");\r
+ if (tempFiles == null)\r
+ tempFiles = new ArrayList<QTemporaryFile>();\r
+ tempFiles.clear();\r
+ QDomElement docElem = doc.documentElement();\r
+ \r
+ // Modify en-media tags\r
+ QDomNodeList anchors = docElem.elementsByTagName("en-media");\r
+ int enMediaCount = anchors.length();\r
+ for (int i=enMediaCount-1; i>=0; i--) {\r
+ QDomElement enmedia = anchors.at(i).toElement();\r
+ if (enmedia.hasAttribute("type")) {\r
+ QDomAttr attr = enmedia.attributeNode("type");\r
+ QDomAttr hash = enmedia.attributeNode("hash");\r
+ String[] type = attr.nodeValue().split("/");\r
+ String appl = type[1];\r
+ \r
+ if (type[0] != null) {\r
+ if (type[0].equals("image")) {\r
+ modifyImageTags(docElem, enmedia, hash);\r
+ }\r
+ if (!type[0].equals("image")) {\r
+ modifyApplicationTags(doc, docElem, enmedia, hash, appl);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ // Modify todo tags\r
+ anchors = docElem.elementsByTagName("en-todo");\r
+ int enTodoCount = anchors.length();\r
+ for (int i=enTodoCount-1; i>=0; i--) {\r
+ QDomElement enmedia = anchors.at(i).toElement();\r
+ modifyTodoTags(enmedia);\r
+ }\r
+ \r
+ // Modify en-crypt tags\r
+ anchors = docElem.elementsByTagName("en-crypt");\r
+ int enCryptLen = anchors.length();\r
+ for (int i=enCryptLen-1; i>=0; i--) {\r
+ QDomElement enmedia = anchors.at(i).toElement();\r
+ enmedia.setAttribute("contentEditable","false");\r
+ enmedia.setAttribute("src", Global.getFileManager().getImageDirPath("encrypt.png"));\r
+ enmedia.setAttribute("en-tag","en-crypt");\r
+ enmedia.setAttribute("alt", enmedia.text());\r
+ Global.cryptCounter++;\r
+ enmedia.setAttribute("id", "crypt"+Global.cryptCounter.toString());\r
+ String encryptedText = enmedia.text();\r
+ \r
+ // If the encryption string contains crlf at the end, remove them because they mess up the javascript.\r
+ if (encryptedText.endsWith("\n"))\r
+ encryptedText = encryptedText.substring(0,encryptedText.length()-1);\r
+ if (encryptedText.endsWith("\r"))\r
+ encryptedText = encryptedText.substring(0,encryptedText.length()-1);\r
+ \r
+ // Add the commands\r
+ String hint = enmedia.attribute("hint");\r
+ hint = hint.replace("'","'");\r
+ enmedia.setAttribute("onClick", "window.jambi.decryptText('crypt"+Global.cryptCounter.toString()+"', '"+encryptedText+"', '"+hint+"');");\r
+ enmedia.setAttribute("onMouseOver", "style.cursor='hand'");\r
+ enmedia.setTagName("img");\r
+ enmedia.removeChild(enmedia.firstChild()); // Remove the actual encrypted text\r
+ }\r
+\r
+ \r
+ // Modify link tags\r
+ anchors = docElem.elementsByTagName("a");\r
+ enCryptLen = anchors.length();\r
+ for (int i=0; i<anchors.length(); i++) {\r
+ QDomElement element = anchors.at(i).toElement();\r
+ element.setAttribute("title", element.attribute("href"));\r
+ }\r
+\r
+ logger.log(logger.HIGH, "Leaving NeverNote.modifyTags");\r
+ return doc;\r
+ }\r
+ \r
+ \r
+ // Modify the en-media tag into an attachment\r
+ private void modifyApplicationTags(QDomDocument doc, QDomElement docElem, QDomElement enmedia, QDomAttr hash, String appl) {\r
+ logger.log(logger.HIGH, "Entering NeverNote.modifyApplicationTags");\r
+ if (appl.equalsIgnoreCase("vnd.evernote.ink"))\r
+ readOnly = true;\r
+ String resGuid = conn.getNoteTable().noteResourceTable.getNoteResourceGuidByHashHex(currentNote.getGuid(), hash.value());\r
+ Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(resGuid, false);\r
+ if (r == null || r.getData() == null) \r
+ resourceError = true;\r
+ if (r!= null) {\r
+ if (r.getData()!=null) {\r
+ // Did we get a generic applicaiton? Then look at the file name to \r
+ // try and find a good application type for the icon\r
+ if (appl.equalsIgnoreCase("octet-stream")) {\r
+ if (r.getAttributes() != null && r.getAttributes().getFileName() != null) {\r
+ String fn = r.getAttributes().getFileName();\r
+ int pos = fn.lastIndexOf(".");\r
+ if (pos > -1) {\r
+ appl = fn.substring(pos+1);\r
+ }\r
+ }\r
+ }\r
+ \r
+ String fileDetails = null;\r
+ if (r.getAttributes() != null && r.getAttributes().getFileName() != null && !r.getAttributes().getFileName().equals(""))\r
+ fileDetails = r.getAttributes().getFileName();\r
+ String contextFileName;\r
+ FileManager fileManager = Global.getFileManager();\r
+ if (fileDetails != null && !fileDetails.equals("")) {\r
+ if (!noteHistory) {\r
+ enmedia.setAttribute("href", "nnres://" +r.getGuid() \r
+ +Global.attachmentNameDelimeter +fileDetails);\r
+ contextFileName = fileManager.getResDirPath(r.getGuid() \r
+ +Global.attachmentNameDelimeter + fileDetails);\r
+ } else {\r
+ enmedia.setAttribute("href", "nnres://" +r.getGuid() + currentNote.getUpdateSequenceNum() \r
+ +Global.attachmentNameDelimeter +fileDetails);\r
+ contextFileName = fileManager.getResDirPath(r.getGuid() + currentNote.getUpdateSequenceNum() \r
+ +Global.attachmentNameDelimeter + fileDetails);\r
+ }\r
+ } else { \r
+ if (!noteHistory) {\r
+ enmedia.setAttribute("href", "nnres://" +r.getGuid() +currentNote.getUpdateSequenceNum()\r
+ +Global.attachmentNameDelimeter +appl);\r
+ contextFileName = fileManager.getResDirPath(r.getGuid() +currentNote.getUpdateSequenceNum() \r
+ +Global.attachmentNameDelimeter + appl);\r
+ } else {\r
+ enmedia.setAttribute("href", "nnres://" +r.getGuid() \r
+ +Global.attachmentNameDelimeter +appl);\r
+ contextFileName = fileManager.getResDirPath(r.getGuid() \r
+ +Global.attachmentNameDelimeter + appl);\r
+ }\r
+ }\r
+ contextFileName = contextFileName.replace("\\", "/");\r
+ enmedia.setAttribute("onContextMenu", "window.jambi.resourceContextMenu('" +contextFileName +"');");\r
+ if (fileDetails == null || fileDetails.equals(""))\r
+ fileDetails = "";\r
+ enmedia.setAttribute("en-tag", "en-media");\r
+ enmedia.setAttribute("guid", r.getGuid());\r
+ enmedia.setTagName("a");\r
+ QDomElement newText = doc.createElement("img");\r
+ boolean goodPreview = false;\r
+ String filePath = "";\r
+ if (appl.equalsIgnoreCase("pdf") && pdfPreview) {\r
+ String fileName;\r
+ Resource res = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), true);\r
+ if (res.getAttributes() != null && \r
+ res.getAttributes().getFileName() != null && \r
+ !res.getAttributes().getFileName().trim().equals(""))\r
+ fileName = res.getGuid()+Global.attachmentNameDelimeter+res.getAttributes().getFileName();\r
+ else\r
+ fileName = res.getGuid()+".pdf";\r
+ QFile file = new QFile(fileManager.getResDirPath(fileName));\r
+ QFile.OpenMode mode = new QFile.OpenMode();\r
+ mode.set(QFile.OpenModeFlag.WriteOnly);\r
+ file.open(mode);\r
+ QDataStream out = new QDataStream(file);\r
+ Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(res.getGuid(), true);\r
+ QByteArray binData = new QByteArray(resBinary.getData().getBody());\r
+ resBinary = null;\r
+ out.writeBytes(binData.toByteArray());\r
+ file.close();\r
+ PDFPreview pdfPreview = new PDFPreview();\r
+ goodPreview = pdfPreview.setupPreview(file.fileName(), appl,0);\r
+ if (goodPreview) {\r
+ QDomElement span = doc.createElement("span");\r
+ QDomElement table = doc.createElement("table");\r
+ span.setAttribute("pdfNavigationTable", "true");\r
+ QDomElement tr = doc.createElement("tr");\r
+ QDomElement td = doc.createElement("td");\r
+ QDomElement left = doc.createElement("img");\r
+ left.setAttribute("onMouseDown", "window.jambi.nextPage('" +file.fileName() +"')");\r
+ left.setAttribute("onMouseDown", "window.jambi.nextPage('" +file.fileName() +"')");\r
+ left.setAttribute("onMouseOver", "style.cursor='hand'");\r
+ QDomElement right = doc.createElement("img");\r
+ right.setAttribute("onMouseDown", "window.jambi.nextPage('" +file.fileName() +"')");\r
+ left.setAttribute("onMouseDown", "window.jambi.previousPage('" +file.fileName() +"')");\r
+ // NFC TODO: should these be file:// URLs?\r
+ left.setAttribute("src", Global.getFileManager().getImageDirPath("small_left.png"));\r
+ right.setAttribute("src", Global.getFileManager().getImageDirPath("small_right.png"));\r
+ right.setAttribute("onMouseOver", "style.cursor='hand'");\r
+ \r
+ table.appendChild(tr);\r
+ tr.appendChild(td);\r
+ td.appendChild(left);\r
+ td.appendChild(right);\r
+ span.appendChild(table);\r
+ enmedia.parentNode().insertBefore(span, enmedia);\r
+ } \r
+ filePath = fileName+".png";\r
+ }\r
+ String icon = findIcon(appl);\r
+ if (icon.equals("attachment.png"))\r
+ icon = findIcon(fileDetails.substring(fileDetails.indexOf(".")+1));\r
+ // NFC TODO: should this be a 'file://' URL?\r
+ newText.setAttribute("src", Global.getFileManager().getImageDirPath(icon));\r
+ if (goodPreview) {\r
+ // NFC TODO: should this be a 'file://' URL?\r
+ newText.setAttribute("src", fileManager.getResDirPath(filePath));\r
+ newText.setAttribute("style", "border-style:solid; border-color:green; padding:0.5mm 0.5mm 0.5mm 0.5mm;");\r
+ }\r
+ newText.setAttribute("title", fileDetails);\r
+ enmedia.removeChild(enmedia.firstChild());\r
+ \r
+ enmedia.appendChild(newText);\r
+ }\r
+ }\r
+ logger.log(logger.HIGH, "Leaving NeverNote.modifyApplicationTags");\r
+ }\r
+ // Modify the en-to tag into an input field\r
+ private void modifyTodoTags(QDomElement todo) {\r
+ logger.log(logger.HIGH, "Entering NeverNote.modifyTodoTags");\r
+ todo.setAttribute("type", "checkbox");\r
+ String checked = todo.attribute("checked");\r
+ todo.removeAttribute("checked");\r
+ if (checked.equalsIgnoreCase("true"))\r
+ todo.setAttribute("checked", "");\r
+ else\r
+ todo.setAttribute("unchecked","");\r
+ todo.setAttribute("value", checked);\r
+ todo.setAttribute("onClick", "value=checked;window.jambi.contentChanged(); ");\r
+ todo.setTagName("input");\r
+ logger.log(logger.HIGH, "Leaving NeverNote.modifyTodoTags");\r
+ }\r
+ \r
+ \r
+ \r
+ // Modify any cached todo tags that may have changed\r
+ public String modifyCachedTodoTags(String note) {\r
+ logger.log(logger.HIGH, "Entering NeverNote.modifyCachedTodoTags");\r
+ StringBuffer html = new StringBuffer(note);\r
+ for (int i=html.indexOf("<input", 0); i>-1; i=html.indexOf("<input", i)) {\r
+ int endPos =html.indexOf(">",i+1);\r
+ String input = html.substring(i,endPos);\r
+ if (input.indexOf("value=\"true\"") > 0) \r
+ input = input.replace(" unchecked=\"\"", " checked=\"\"");\r
+ else\r
+ input = input.replace(" checked=\"\"", " unchecked=\"\"");\r
+ html.replace(i, endPos, input);\r
+ i++;\r
+ }\r
+ logger.log(logger.HIGH, "Leaving NeverNote.modifyCachedTodoTags");\r
+ return html.toString();\r
+ }\r
+ \r
+ \r
+\r
+\r
+ // Scan and do hilighting of words\r
+ public QDomDocument addHilight(QDomDocument doc) {\r
+// EnSearch e = listManager.getEnSearch();\r
+ if (enSearch.hilightWords == null || enSearch.hilightWords.size() == 0)\r
+ return doc;\r
+ XMLInsertHilight hilight = new XMLInsertHilight(doc, enSearch.hilightWords);\r
+ return hilight.getDoc();\r
+ }\r
+ \r
+ \r
+ // find the appropriate icon for an attachment\r
+ private String findIcon(String appl) {\r
+ logger.log(logger.HIGH, "Entering NeverNote.findIcon");\r
+ appl = appl.toLowerCase();\r
+ String relativePath = appl + ".png";\r
+ File f = Global.getFileManager().getImageDirFile(relativePath);\r
+ if (f.exists()) {\r
+ return relativePath;\r
+ }\r
+ if (f.exists())\r
+ return appl+".png";\r
+ logger.log(logger.HIGH, "Leaving NeverNote.findIcon");\r
+ return "attachment.png";\r
+ }\r
+\r
+\r
+}\r
import com.trolltech.qt.xml.QDomText;\r
\r
import cx.fbn.nevernote.Global;\r
-import cx.fbn.nevernote.evernote.EnCrypt;\r
\r
public class XMLCleanup {\r
private String content;\r
\r
public void setValue(String text) {\r
content = text;\r
-/* content = content.replace("<HR>", "<hr/>");\r
- content = content.replace("<hr>", "<hr/>");\r
- content = content.replace("</HR>", "");\r
- content = content.replace("</hr>", ""); */\r
}\r
public String getValue() {\r
return content;\r
}\r
}\r
\r
+ // Scan through tags node by node\r
scanTags();\r
\r
+ // Scan again making sure we didn't miss any <a> tags. Sometimes we do\r
+ QDomNodeList anchorList = doc.elementsByTagName("a");\r
+ int anchorCount = anchorList.length();\r
+ for (int i=anchorCount-1; i>=0; i--) {\r
+ QDomNode link = anchorList.at(i);\r
+ link = fixLinkNode(link);\r
+ }\r
+ \r
// Remove invalid elements & attributes\r
// Modify en-media tags\r
QDomNodeList anchors;\r
\r
}\r
// Start looking through the tree.\r
- private void scanTags() {\r
-// System.out.println("scanTags start");\r
-// QDomElement element = doc.firstChildElement();\r
-// parseChildren(element.firstChild()); \r
+ private void scanTags() { \r
\r
if (doc.hasChildNodes())\r
parseNodes(doc.childNodes());\r
}\r
}\r
\r
-/* \r
- // Parse through individual nodes\r
- private void parseChildren(QDomNode node) {\r
- System.out.println("Starting parseChildren " +node.toElement().nodeName() +" : " +node.toElement().text());\r
- for(; !node.isNull(); node = node.nextSibling()) {\r
- if (node.hasChildNodes()) {\r
- QDomNodeList l = node.childNodes();\r
- \r
- for (int i=0; i<l.size(); i++) {\r
- System.out.println("Child node size: " +l.size() +" " +i);\r
- parseChildren(l.at(i));\r
- }\r
- }\r
- fixNode(node);\r
- }\r
- }\r
- \r
-*/ \r
- \r
+\r
// Fix the contents of the node back to ENML.\r
private void fixNode(QDomNode node) {\r
QDomElement scanChecked = node.toElement();\r
e.removeAttribute("type");\r
}\r
\r
-\r
if (node.nodeName().equalsIgnoreCase("a")) {\r
- QDomElement e = node.toElement();\r
- String enTag = e.attribute("en-tag");\r
- if (enTag.equalsIgnoreCase("en-media")) {\r
- e.setTagName("en-media");\r
- e.removeAttribute("en-type");\r
- e.removeAttribute("en-tag");\r
- e.removeAttribute("en-new");\r
- resources.add(e.attribute("guid"));\r
- e.removeAttribute("href");\r
- e.removeAttribute("guid");\r
- e.setNodeValue("");\r
- e.removeChild(e.firstChildElement());\r
- }\r
+ node = fixLinkNode(node);\r
}\r
// Restore image resources\r
if (node.nodeName().equalsIgnoreCase("img")) {\r
}\r
}\r
\r
- if (node.nodeName().equalsIgnoreCase("en-crypt-temp")) {\r
- QDomElement e = node.toElement();\r
- String slot = e.attribute("slot");\r
- e.removeAttribute("slot");\r
- String password = Global.passwordSafe.get(slot);\r
- Global.passwordSafe.remove(slot);\r
- EnCrypt crypt = new EnCrypt();\r
- String encrypted = crypt.encrypt(e.text(), password, 64); \r
- \r
- QDomText newText = doc.createTextNode(encrypted);\r
- e.appendChild(newText);\r
- e.removeChild(e.firstChild());\r
- e.setTagName("en-crypt");\r
- }\r
if (node.nodeName().equalsIgnoreCase("en-hilight")) {\r
QDomElement e = node.toElement();\r
QDomText newText = doc.createTextNode(e.text());\r
node.parentNode().removeChild(node);\r
}\r
}\r
+ \r
+ // Fix up encryption tag\r
+ if (node.nodeName().equalsIgnoreCase("en-crypt-temp")) {\r
+ QDomElement e = node.toElement();\r
+ e.setTagName("en-crypt");\r
+ String crypt = e.attribute("value");\r
+ e.removeAttribute("value");\r
+ QDomText cryptValue = doc.createTextNode(crypt);\r
+ e.appendChild(cryptValue);\r
+ }\r
}\r
\r
+ \r
+ private QDomNode fixLinkNode(QDomNode node) {\r
+ QDomElement e = node.toElement();\r
+ String enTag = e.attribute("en-tag");\r
+ if (enTag.equalsIgnoreCase("en-media")) {\r
+ e.setTagName("en-media");\r
+ e.removeAttribute("en-type");\r
+ e.removeAttribute("en-tag");\r
+ e.removeAttribute("en-new");\r
+ resources.add(e.attribute("guid"));\r
+ e.removeAttribute("href");\r
+ e.removeAttribute("guid");\r
+ e.setNodeValue("");\r
+ e.removeChild(e.firstChildElement());\r
+ }\r
+ return e;\r
+ }\r
\r
\r
// Return old resources we've found\r