From 62760c1f19bba822efcc699b8061f3993decb94a Mon Sep 17 00:00:00 2001 From: Randy Baumgarte Date: Tue, 13 Jul 2010 15:08:08 -0400 Subject: [PATCH 1/1] NeverNote 0.88. --- .classpath | 13 + .gitignore | 1 + .project | 22 + .settings/org.eclipse.jdt.ui.prefs | 54 + .settings/org.eclipse.ltk.core.refactoring.prefs | 3 + src/.classpath | 20 + src/.project | 22 + src/com/swabunga/spell/engine/Configuration.java | 153 + src/com/swabunga/spell/engine/DoubleMeta.java | 713 +++ src/com/swabunga/spell/engine/EditDistance.java | 253 + .../spell/engine/GenericSpellDictionary.java | 195 + .../spell/engine/GenericTransformator.java | 447 ++ .../spell/engine/PropertyConfiguration.java | 108 + src/com/swabunga/spell/engine/SpellDictionary.java | 92 + .../spell/engine/SpellDictionaryASpell.java | 360 ++ .../engine/SpellDictionaryCachedDichoDisk.java | 1 + .../spell/engine/SpellDictionaryDichoDisk.java | 231 + .../swabunga/spell/engine/SpellDictionaryDisk.java | 546 +++ .../spell/engine/SpellDictionaryHashMap.java | 328 ++ src/com/swabunga/spell/engine/Transformator.java | 54 + src/com/swabunga/spell/engine/Word.java | 115 + .../swabunga/spell/engine/configuration.properties | 18 + .../swabunga/spell/event/AbstractWordFinder.java | 392 ++ .../spell/event/AbstractWordTokenizer.java | 164 + .../swabunga/spell/event/BasicSpellCheckEvent.java | 151 + .../swabunga/spell/event/DefaultWordFinder.java | 116 + .../spell/event/DocumentWordTokenizer.java | 267 ++ .../swabunga/spell/event/FileWordTokenizer.java | 94 + src/com/swabunga/spell/event/JavaWordFinder.java | 142 + src/com/swabunga/spell/event/SpellCheckEvent.java | 103 + .../swabunga/spell/event/SpellCheckListener.java | 36 + src/com/swabunga/spell/event/SpellChecker.java | 577 +++ .../swabunga/spell/event/StringWordTokenizer.java | 91 + src/com/swabunga/spell/event/TeXWordFinder.java | 193 + src/com/swabunga/spell/event/Word.java | 141 + src/com/swabunga/spell/event/WordFinder.java | 102 + .../spell/event/WordNotFoundException.java | 45 + src/com/swabunga/spell/event/WordTokenizer.java | 105 + src/com/swabunga/spell/event/XMLWordFinder.java | 97 + .../swing/autospell/AutoSpellCheckHandler.java | 318 ++ .../spell/swing/autospell/AutoSpellConstants.java | 32 + .../spell/swing/autospell/AutoSpellEditorKit.java | 202 + .../spell/swing/autospell/AutoSpellView.java | 438 ++ .../swing/autospell/AutoSpellViewFactory.java | 54 + src/com/swabunga/util/StringUtility.java | 37 + src/com/swabunga/util/VectorUtility.java | 40 + src/cx/fbn/nevernote/Global.class | Bin 0 -> 21814 bytes src/cx/fbn/nevernote/Global.java | 1137 +++++ src/cx/fbn/nevernote/NeverNote.class | Bin 0 -> 100161 bytes src/cx/fbn/nevernote/NeverNote.java | 4856 ++++++++++++++++++++ src/cx/fbn/nevernote/dialog/AccountDialog.class | Bin 0 -> 4104 bytes src/cx/fbn/nevernote/dialog/AccountDialog.java | 121 + src/cx/fbn/nevernote/dialog/AssignTag.class | Bin 0 -> 3555 bytes .../nevernote/dialog/ConfigAppearancePage.class | Bin 0 -> 6002 bytes .../fbn/nevernote/dialog/ConfigAppearancePage.java | 336 ++ .../nevernote/dialog/ConfigConnectionPage.class | Bin 0 -> 4646 bytes .../fbn/nevernote/dialog/ConfigConnectionPage.java | 182 + src/cx/fbn/nevernote/dialog/ConfigDebugPage.class | Bin 0 -> 4736 bytes src/cx/fbn/nevernote/dialog/ConfigDebugPage.java | 150 + src/cx/fbn/nevernote/dialog/ConfigDialog.class | Bin 0 -> 14154 bytes src/cx/fbn/nevernote/dialog/ConfigDialog.java | 352 ++ .../fbn/nevernote/dialog/ConfigFormatsPage.class | Bin 0 -> 3049 bytes .../fbn/nevernote/dialog/ConfigGeneralPage.class | Bin 0 -> 8566 bytes src/cx/fbn/nevernote/dialog/ConfigIndexPage.class | Bin 0 -> 2878 bytes src/cx/fbn/nevernote/dialog/ConfigIndexPage.java | 151 + .../nevernote/dialog/ConfigShowColumnsPage.class | Bin 0 -> 4917 bytes .../nevernote/dialog/ConfigShowColumnsPage.java | 231 + .../dialog/ConfigShowEditorButtonsPage.class | Bin 0 -> 10863 bytes .../dialog/ConfigShowEditorButtonsPage.java | 521 +++ .../fbn/nevernote/dialog/DatabaseLoginDialog.java | 98 + src/cx/fbn/nevernote/dialog/DatabaseStatus.class | Bin 0 -> 3277 bytes src/cx/fbn/nevernote/dialog/DatabaseStatus.java | 116 + src/cx/fbn/nevernote/dialog/EnCryptDialog.class | Bin 0 -> 3337 bytes src/cx/fbn/nevernote/dialog/EnCryptDialog.java | 134 + src/cx/fbn/nevernote/dialog/EnDecryptDialog.class | Bin 0 -> 3339 bytes src/cx/fbn/nevernote/dialog/EnDecryptDialog.java | 149 + src/cx/fbn/nevernote/dialog/FindDialog.class | Bin 0 -> 3587 bytes src/cx/fbn/nevernote/dialog/FindDialog.java | 132 + src/cx/fbn/nevernote/dialog/InsertLinkDialog.class | Bin 0 -> 2351 bytes src/cx/fbn/nevernote/dialog/InsertLinkDialog.java | 103 + src/cx/fbn/nevernote/dialog/LoginDialog.class | Bin 0 -> 2933 bytes src/cx/fbn/nevernote/dialog/LoginDialog.java | 113 + src/cx/fbn/nevernote/dialog/NotebookArchive.class | Bin 0 -> 3577 bytes src/cx/fbn/nevernote/dialog/NotebookArchive.java | 207 + src/cx/fbn/nevernote/dialog/NotebookEdit.class | Bin 0 -> 3690 bytes src/cx/fbn/nevernote/dialog/NotebookEdit.java | 144 + src/cx/fbn/nevernote/dialog/OnlineNoteHistory.java | 369 ++ src/cx/fbn/nevernote/dialog/PreviewDialog.java | 82 + src/cx/fbn/nevernote/dialog/PreviewImage.java | 32 + src/cx/fbn/nevernote/dialog/SavedSearchEdit.class | Bin 0 -> 3595 bytes src/cx/fbn/nevernote/dialog/SavedSearchEdit.java | 138 + src/cx/fbn/nevernote/dialog/TableDialog.java | 160 + src/cx/fbn/nevernote/dialog/TagAssign.java | 160 + src/cx/fbn/nevernote/dialog/TagEdit.class | Bin 0 -> 3198 bytes src/cx/fbn/nevernote/dialog/TagEdit.java | 121 + src/cx/fbn/nevernote/dialog/ThumbnailViewer.java | 175 + src/cx/fbn/nevernote/dialog/WatchFolder.java | 260 ++ src/cx/fbn/nevernote/dialog/WatchFolderAdd.java | 149 + src/cx/fbn/nevernote/evernote/EnCrypt.class | Bin 0 -> 4923 bytes src/cx/fbn/nevernote/evernote/EnCrypt.java | 167 + src/cx/fbn/nevernote/evernote/EnmlConverter.class | Bin 0 -> 5221 bytes src/cx/fbn/nevernote/evernote/EnmlConverter.java | 281 ++ src/cx/fbn/nevernote/filters/AttributeFilter.class | Bin 0 -> 710 bytes src/cx/fbn/nevernote/filters/AttributeFilter.java | 39 + src/cx/fbn/nevernote/filters/EnSearch.class | Bin 0 -> 2133 bytes src/cx/fbn/nevernote/filters/EnSearch.java | 73 + .../filters/NoteSortFilterProxyModel.class | Bin 0 -> 3351 bytes .../filters/NoteSortFilterProxyModel.java | 89 + src/cx/fbn/nevernote/filters/NotebookCounter.class | Bin 0 -> 1026 bytes src/cx/fbn/nevernote/filters/NotebookCounter.java | 49 + src/cx/fbn/nevernote/filters/TagCounter.class | Bin 0 -> 833 bytes src/cx/fbn/nevernote/filters/TagCounter.java | 45 + src/cx/fbn/nevernote/filters/WordFilter.class | Bin 0 -> 3134 bytes src/cx/fbn/nevernote/filters/WordFilter.java | 86 + src/cx/fbn/nevernote/gui/AttributeTreeWidget.class | Bin 0 -> 2899 bytes src/cx/fbn/nevernote/gui/AttributeTreeWidget.java | 171 + src/cx/fbn/nevernote/gui/BrowserWindow.class | Bin 0 -> 49317 bytes src/cx/fbn/nevernote/gui/BrowserWindow.java | 2349 ++++++++++ src/cx/fbn/nevernote/gui/ColorMenu.java | 72 + .../gui/ContainsAttributeFilterTable.java | 140 + src/cx/fbn/nevernote/gui/ContentView.java | 342 ++ .../nevernote/gui/DateAttributeFilterTable.class | Bin 0 -> 5589 bytes .../nevernote/gui/DateAttributeFilterTable.java | 231 + src/cx/fbn/nevernote/gui/FbnMenuBar.class | Bin 0 -> 15492 bytes src/cx/fbn/nevernote/gui/FbnWebView.class | Bin 0 -> 6725 bytes src/cx/fbn/nevernote/gui/MainMenuBar.java | 677 +++ src/cx/fbn/nevernote/gui/NotebookTreeWidget.class | Bin 0 -> 9471 bytes src/cx/fbn/nevernote/gui/NotebookTreeWidget.java | 289 ++ src/cx/fbn/nevernote/gui/PDFPreview.java | 99 + .../fbn/nevernote/gui/SavedSearchTreeWidget.class | Bin 0 -> 3749 bytes .../fbn/nevernote/gui/SavedSearchTreeWidget.java | 120 + src/cx/fbn/nevernote/gui/ShortcutKeys.class | Bin 0 -> 8084 bytes src/cx/fbn/nevernote/gui/ShortcutKeys.java | 362 ++ src/cx/fbn/nevernote/gui/TableView.class | Bin 0 -> 13663 bytes src/cx/fbn/nevernote/gui/TableView.java | 503 ++ src/cx/fbn/nevernote/gui/TagLineCompleter.class | Bin 0 -> 3239 bytes src/cx/fbn/nevernote/gui/TagLineCompleter.java | 102 + src/cx/fbn/nevernote/gui/TagLineEdit.class | Bin 0 -> 4222 bytes src/cx/fbn/nevernote/gui/TagLineEdit.java | 106 + src/cx/fbn/nevernote/gui/TagTreeWidget.class | Bin 0 -> 11407 bytes src/cx/fbn/nevernote/gui/TagTreeWidget.java | 343 ++ src/cx/fbn/nevernote/gui/Thumbnailer.java | 69 + src/cx/fbn/nevernote/gui/TrashTreeWidget.class | Bin 0 -> 2986 bytes src/cx/fbn/nevernote/gui/TrashTreeWidget.java | 105 + src/cx/fbn/nevernote/icons/appearance.jpg | Bin 0 -> 3696 bytes src/cx/fbn/nevernote/icons/attribute.png | Bin 0 -> 41307 bytes src/cx/fbn/nevernote/icons/back.png | Bin 0 -> 25627 bytes src/cx/fbn/nevernote/icons/bold.gif | Bin 0 -> 104 bytes src/cx/fbn/nevernote/icons/bulletList.gif | Bin 0 -> 101 bytes src/cx/fbn/nevernote/icons/copy.gif | Bin 0 -> 149 bytes src/cx/fbn/nevernote/icons/cut.gif | Bin 0 -> 120 bytes src/cx/fbn/nevernote/icons/debug.jpg | Bin 0 -> 1384 bytes src/cx/fbn/nevernote/icons/delete.png | Bin 0 -> 42797 bytes src/cx/fbn/nevernote/icons/down.png | Bin 0 -> 25128 bytes src/cx/fbn/nevernote/icons/email.png | Bin 0 -> 24515 bytes src/cx/fbn/nevernote/icons/encrypt.png | Bin 0 -> 2071 bytes src/cx/fbn/nevernote/icons/fontColor.gif | Bin 0 -> 149 bytes src/cx/fbn/nevernote/icons/fontHilight.gif | Bin 0 -> 147 bytes src/cx/fbn/nevernote/icons/forward.png | Bin 0 -> 25924 bytes src/cx/fbn/nevernote/icons/hline.gif | Bin 0 -> 89 bytes src/cx/fbn/nevernote/icons/indent.gif | Bin 0 -> 113 bytes src/cx/fbn/nevernote/icons/italic.gif | Bin 0 -> 98 bytes src/cx/fbn/nevernote/icons/justify.gif | Bin 0 -> 93 bytes src/cx/fbn/nevernote/icons/justifyCenter.gif | Bin 0 -> 179 bytes src/cx/fbn/nevernote/icons/justifyFull.gif | Bin 0 -> 93 bytes src/cx/fbn/nevernote/icons/justifyLeft.gif | Bin 0 -> 93 bytes src/cx/fbn/nevernote/icons/justifyRight.gif | Bin 0 -> 92 bytes src/cx/fbn/nevernote/icons/left.gif | Bin 0 -> 93 bytes src/cx/fbn/nevernote/icons/nevernote.png | Bin 0 -> 21257 bytes src/cx/fbn/nevernote/icons/new.png | Bin 0 -> 28246 bytes src/cx/fbn/nevernote/icons/notebook-blue.png | Bin 0 -> 6184 bytes src/cx/fbn/nevernote/icons/notebook-green.png | Bin 0 -> 6178 bytes src/cx/fbn/nevernote/icons/notebook-red.png | Bin 0 -> 6207 bytes src/cx/fbn/nevernote/icons/notebook-yellow.png | Bin 0 -> 7263 bytes src/cx/fbn/nevernote/icons/numberList.gif | Bin 0 -> 104 bytes src/cx/fbn/nevernote/icons/outdent.gif | Bin 0 -> 111 bytes src/cx/fbn/nevernote/icons/paste.gif | Bin 0 -> 181 bytes src/cx/fbn/nevernote/icons/print.png | Bin 0 -> 11581 bytes src/cx/fbn/nevernote/icons/redo.gif | Bin 0 -> 105 bytes src/cx/fbn/nevernote/icons/right.gif | Bin 0 -> 92 bytes src/cx/fbn/nevernote/icons/scissors.jpg | Bin 0 -> 2876 bytes src/cx/fbn/nevernote/icons/search.png | Bin 0 -> 38265 bytes src/cx/fbn/nevernote/icons/search_config.jpg | Bin 0 -> 69061 bytes src/cx/fbn/nevernote/icons/searchclear.png | Bin 0 -> 52520 bytes src/cx/fbn/nevernote/icons/show-columns.png | Bin 0 -> 16651 bytes src/cx/fbn/nevernote/icons/splash_logo-new.png | Bin 0 -> 9749 bytes src/cx/fbn/nevernote/icons/splash_logo.png | Bin 0 -> 194775 bytes src/cx/fbn/nevernote/icons/strikethrough.gif | Bin 0 -> 71 bytes src/cx/fbn/nevernote/icons/synchronize-0.png | Bin 0 -> 24796 bytes src/cx/fbn/nevernote/icons/synchronize-1.png | Bin 0 -> 29074 bytes src/cx/fbn/nevernote/icons/synchronize-2.png | Bin 0 -> 28300 bytes src/cx/fbn/nevernote/icons/synchronize-3.png | Bin 0 -> 29042 bytes src/cx/fbn/nevernote/icons/synchronize.png | Bin 0 -> 102451 bytes src/cx/fbn/nevernote/icons/synchronize2.png | Bin 0 -> 36151 bytes src/cx/fbn/nevernote/icons/tag-tan.png | Bin 0 -> 7347 bytes src/cx/fbn/nevernote/icons/tag.png | Bin 0 -> 32699 bytes src/cx/fbn/nevernote/icons/trash.png | Bin 0 -> 24582 bytes src/cx/fbn/nevernote/icons/underline.gif | Bin 0 -> 109 bytes src/cx/fbn/nevernote/icons/undo.gif | Bin 0 -> 105 bytes src/cx/fbn/nevernote/icons/up.png | Bin 0 -> 20997 bytes src/cx/fbn/nevernote/icons/world.jpg | Bin 0 -> 3400 bytes src/cx/fbn/nevernote/signals/DBRunnerSignal.class | Bin 0 -> 598 bytes src/cx/fbn/nevernote/signals/DBRunnerSignal.java | 27 + src/cx/fbn/nevernote/signals/NoteIndexSignal.class | Bin 0 -> 880 bytes src/cx/fbn/nevernote/signals/NoteIndexSignal.java | 29 + .../fbn/nevernote/signals/NoteResourceSignal.class | Bin 0 -> 922 bytes .../fbn/nevernote/signals/NoteResourceSignal.java | 30 + src/cx/fbn/nevernote/signals/NoteSignal.class | Bin 0 -> 1943 bytes src/cx/fbn/nevernote/signals/NoteSignal.java | 47 + src/cx/fbn/nevernote/signals/NotebookSignal.class | Bin 0 -> 1190 bytes src/cx/fbn/nevernote/signals/NotebookSignal.java | 34 + .../fbn/nevernote/signals/SavedSearchSignal.class | Bin 0 -> 629 bytes .../fbn/nevernote/signals/SavedSearchSignal.java | 28 + src/cx/fbn/nevernote/signals/StatusSignal.class | Bin 0 -> 637 bytes src/cx/fbn/nevernote/signals/StatusSignal.java | 25 + src/cx/fbn/nevernote/signals/SyncSignal.class | Bin 0 -> 2221 bytes src/cx/fbn/nevernote/signals/SyncSignal.java | 46 + src/cx/fbn/nevernote/signals/TagSignal.class | Bin 0 -> 1147 bytes src/cx/fbn/nevernote/signals/TagSignal.java | 35 + src/cx/fbn/nevernote/signals/ThreadSignal.class | Bin 0 -> 1621 bytes src/cx/fbn/nevernote/signals/ThreadSignal.java | 30 + src/cx/fbn/nevernote/signals/TrashSignal.java | 26 + src/cx/fbn/nevernote/sql/DBLock.class | Bin 0 -> 1160 bytes src/cx/fbn/nevernote/sql/DatabaseConnection.class | Bin 0 -> 3620 bytes src/cx/fbn/nevernote/sql/DatabaseConnection.java | 178 + src/cx/fbn/nevernote/sql/DeletedItemRecord.class | Bin 0 -> 369 bytes src/cx/fbn/nevernote/sql/DeletedTable.class | Bin 0 -> 2141 bytes src/cx/fbn/nevernote/sql/DeletedTable.java | 85 + src/cx/fbn/nevernote/sql/IndexConnection.class | Bin 0 -> 3962 bytes src/cx/fbn/nevernote/sql/InvalidXMLTable.java | 103 + src/cx/fbn/nevernote/sql/NoteResourceTable.class | Bin 0 -> 5757 bytes src/cx/fbn/nevernote/sql/NoteResourceTable.java | 225 + src/cx/fbn/nevernote/sql/NoteTable.class | Bin 0 -> 10662 bytes src/cx/fbn/nevernote/sql/NoteTable.java | 497 ++ src/cx/fbn/nevernote/sql/NoteTagsRecord.class | Bin 0 -> 367 bytes src/cx/fbn/nevernote/sql/NoteTagsTable.class | Bin 0 -> 2878 bytes src/cx/fbn/nevernote/sql/NoteTagsTable.java | 111 + src/cx/fbn/nevernote/sql/NotebookTable.class | Bin 0 -> 4814 bytes src/cx/fbn/nevernote/sql/NotebookTable.java | 197 + src/cx/fbn/nevernote/sql/ResourceConnection.class | Bin 0 -> 5424 bytes src/cx/fbn/nevernote/sql/SavedSearchTable.class | Bin 0 -> 4429 bytes src/cx/fbn/nevernote/sql/SavedSearchTable.java | 164 + src/cx/fbn/nevernote/sql/SyncTable.java | 93 + src/cx/fbn/nevernote/sql/TagTable.class | Bin 0 -> 5245 bytes src/cx/fbn/nevernote/sql/TagTable.java | 184 + src/cx/fbn/nevernote/sql/WatchFolderTable.java | 96 + src/cx/fbn/nevernote/sql/WordsTable.class | Bin 0 -> 2610 bytes src/cx/fbn/nevernote/sql/WordsTable.java | 94 + src/cx/fbn/nevernote/sql/driver/NSqlQuery.java | 351 ++ .../nevernote/sql/requests/DBRunnerRequest.class | Bin 0 -> 862 bytes .../nevernote/sql/requests/DBRunnerRequest.java | 44 + .../nevernote/sql/requests/DatabaseRequest.class | Bin 0 -> 1123 bytes .../nevernote/sql/requests/DatabaseRequest.java | 58 + .../sql/requests/DeletedItemRequest.class | Bin 0 -> 1777 bytes .../nevernote/sql/requests/DeletedItemRequest.java | 70 + .../nevernote/sql/requests/EnSearchRequest.class | Bin 0 -> 1622 bytes .../nevernote/sql/requests/EnSearchRequest.java | 75 + .../nevernote/sql/requests/InvalidXMLRequest.java | 80 + .../fbn/nevernote/sql/requests/NoteRequest.class | Bin 0 -> 4062 bytes src/cx/fbn/nevernote/sql/requests/NoteRequest.java | 178 + .../nevernote/sql/requests/NoteTagsRequest.class | Bin 0 -> 2091 bytes .../nevernote/sql/requests/NoteTagsRequest.java | 93 + .../nevernote/sql/requests/NotebookRequest.class | Bin 0 -> 2401 bytes .../nevernote/sql/requests/NotebookRequest.java | 105 + .../nevernote/sql/requests/ResourceRequest.class | Bin 0 -> 2762 bytes .../nevernote/sql/requests/ResourceRequest.java | 103 + .../sql/requests/SavedSearchRequest.class | Bin 0 -> 2456 bytes .../nevernote/sql/requests/SavedSearchRequest.java | 95 + src/cx/fbn/nevernote/sql/requests/SyncRequest.java | 60 + src/cx/fbn/nevernote/sql/requests/TagRequest.class | Bin 0 -> 2502 bytes src/cx/fbn/nevernote/sql/requests/TagRequest.java | 99 + .../nevernote/sql/requests/WatchFolderRequest.java | 84 + src/cx/fbn/nevernote/sql/requests/WordRequest.java | 65 + .../nevernote/sql/runners/DeletedItemRecord.class | Bin 0 -> 385 bytes .../nevernote/sql/runners/DeletedItemRecord.java | 25 + .../fbn/nevernote/sql/runners/NoteTagsRecord.class | Bin 0 -> 383 bytes .../fbn/nevernote/sql/runners/NoteTagsRecord.java | 25 + .../sql/runners/RDatabaseConnection.class | Bin 0 -> 5987 bytes .../nevernote/sql/runners/RDatabaseConnection.java | 207 + .../fbn/nevernote/sql/runners/RDeletedTable.class | Bin 0 -> 3714 bytes .../fbn/nevernote/sql/runners/RDeletedTable.java | 95 + src/cx/fbn/nevernote/sql/runners/REnSearch.class | Bin 0 -> 15415 bytes src/cx/fbn/nevernote/sql/runners/REnSearch.java | 853 ++++ .../nevernote/sql/runners/RInvalidXMLTable.java | 221 + .../nevernote/sql/runners/RNoteResourceTable.class | Bin 0 -> 19966 bytes .../nevernote/sql/runners/RNoteResourceTable.java | 569 +++ src/cx/fbn/nevernote/sql/runners/RNoteTable.class | Bin 0 -> 32467 bytes src/cx/fbn/nevernote/sql/runners/RNoteTable.java | 1110 +++++ .../fbn/nevernote/sql/runners/RNoteTagsTable.class | Bin 0 -> 5234 bytes .../fbn/nevernote/sql/runners/RNoteTagsTable.java | 179 + .../fbn/nevernote/sql/runners/RNotebookTable.class | Bin 0 -> 13018 bytes .../fbn/nevernote/sql/runners/RNotebookTable.java | 432 ++ .../nevernote/sql/runners/RSavedSearchTable.class | Bin 0 -> 9640 bytes .../nevernote/sql/runners/RSavedSearchTable.java | 284 ++ src/cx/fbn/nevernote/sql/runners/RSyncTable.java | 94 + src/cx/fbn/nevernote/sql/runners/RTagTable.class | Bin 0 -> 10170 bytes src/cx/fbn/nevernote/sql/runners/RTagTable.java | 338 ++ .../nevernote/sql/runners/RWatchFolderTable.java | 117 + src/cx/fbn/nevernote/sql/runners/RWordsTable.java | 137 + .../nevernote/sql/runners/WatchFolderRecord.java | 27 + src/cx/fbn/nevernote/threads/CounterRunner.class | Bin 0 -> 5839 bytes src/cx/fbn/nevernote/threads/CounterRunner.java | 331 ++ src/cx/fbn/nevernote/threads/DBRunner.class | Bin 0 -> 25503 bytes src/cx/fbn/nevernote/threads/DBRunner.java | 935 ++++ src/cx/fbn/nevernote/threads/IndexRunner.class | Bin 0 -> 6965 bytes src/cx/fbn/nevernote/threads/IndexRunner.java | 237 + src/cx/fbn/nevernote/threads/SaveRunner.java | 176 + src/cx/fbn/nevernote/threads/SyncRunner.class | Bin 0 -> 35023 bytes src/cx/fbn/nevernote/threads/SyncRunner.java | 1407 ++++++ src/cx/fbn/nevernote/utilities/AESEncrypter.class | Bin 0 -> 3880 bytes src/cx/fbn/nevernote/utilities/AESEncrypter.java | 134 + .../nevernote/utilities/ApplicationLogger.class | Bin 0 -> 3747 bytes .../fbn/nevernote/utilities/ApplicationLogger.java | 114 + src/cx/fbn/nevernote/utilities/Base64$1.class | Bin 0 -> 1315 bytes .../nevernote/utilities/Base64$InputStream.class | Bin 0 -> 2370 bytes .../nevernote/utilities/Base64$OutputStream.class | Bin 0 -> 2620 bytes src/cx/fbn/nevernote/utilities/Base64.class | Bin 0 -> 20537 bytes src/cx/fbn/nevernote/utilities/Base64.java | 2053 +++++++++ src/cx/fbn/nevernote/utilities/Base64Coder.class | Bin 0 -> 3005 bytes src/cx/fbn/nevernote/utilities/FileImporter.java | 421 ++ src/cx/fbn/nevernote/utilities/ListManager.class | Bin 0 -> 29525 bytes src/cx/fbn/nevernote/utilities/ListManager.java | 1127 +++++ src/cx/fbn/nevernote/utilities/OutStream.class | Bin 0 -> 2161 bytes src/cx/fbn/nevernote/utilities/OutStream.java | 71 + src/cx/fbn/nevernote/utilities/Pair.java | 54 + src/cx/fbn/nevernote/utilities/StringUtils.java | 108 + src/cx/fbn/nevernote/utilities/SyncTimes.class | Bin 0 -> 1729 bytes src/cx/fbn/nevernote/utilities/SyncTimes.java | 71 + src/cx/fbn/nevernote/xml/EnmlException.java | 39 + src/cx/fbn/nevernote/xml/ExportData.java | 448 ++ src/cx/fbn/nevernote/xml/ImportData.java | 527 +++ src/cx/fbn/nevernote/xml/ResourceXMLParse.class | Bin 0 -> 4459 bytes src/cx/fbn/nevernote/xml/XMLCleanup.java | 296 ++ src/cx/fbn/nevernote/xml/XMLInsertHilight.java | 160 + src/cx/fbn/nevernote/xml/XMLNoteRepair.java | 122 + src/cx/fbn/nevernote/xml/XMLNoteRepairHandler.java | 164 + src/cx/fbn/nevernote/xml/XMLValidator.class | Bin 0 -> 9822 bytes src/cx/fbn/nevernote/xml/XmlNoteRepair.class | Bin 0 -> 2530 bytes .../fbn/nevernote/xml/XmlNoteRepairHandler.class | Bin 0 -> 3205 bytes 339 files changed, 43126 insertions(+) create mode 100644 .classpath create mode 100644 .gitignore create mode 100644 .project create mode 100644 .settings/org.eclipse.jdt.ui.prefs create mode 100644 .settings/org.eclipse.ltk.core.refactoring.prefs create mode 100644 src/.classpath create mode 100644 src/.project create mode 100644 src/com/swabunga/spell/engine/Configuration.java create mode 100644 src/com/swabunga/spell/engine/DoubleMeta.java create mode 100644 src/com/swabunga/spell/engine/EditDistance.java create mode 100644 src/com/swabunga/spell/engine/GenericSpellDictionary.java create mode 100644 src/com/swabunga/spell/engine/GenericTransformator.java create mode 100644 src/com/swabunga/spell/engine/PropertyConfiguration.java create mode 100644 src/com/swabunga/spell/engine/SpellDictionary.java create mode 100644 src/com/swabunga/spell/engine/SpellDictionaryASpell.java create mode 100644 src/com/swabunga/spell/engine/SpellDictionaryCachedDichoDisk.java create mode 100644 src/com/swabunga/spell/engine/SpellDictionaryDichoDisk.java create mode 100644 src/com/swabunga/spell/engine/SpellDictionaryDisk.java create mode 100644 src/com/swabunga/spell/engine/SpellDictionaryHashMap.java create mode 100644 src/com/swabunga/spell/engine/Transformator.java create mode 100644 src/com/swabunga/spell/engine/Word.java create mode 100644 src/com/swabunga/spell/engine/configuration.properties create mode 100644 src/com/swabunga/spell/event/AbstractWordFinder.java create mode 100644 src/com/swabunga/spell/event/AbstractWordTokenizer.java create mode 100644 src/com/swabunga/spell/event/BasicSpellCheckEvent.java create mode 100644 src/com/swabunga/spell/event/DefaultWordFinder.java create mode 100644 src/com/swabunga/spell/event/DocumentWordTokenizer.java create mode 100644 src/com/swabunga/spell/event/FileWordTokenizer.java create mode 100644 src/com/swabunga/spell/event/JavaWordFinder.java create mode 100644 src/com/swabunga/spell/event/SpellCheckEvent.java create mode 100644 src/com/swabunga/spell/event/SpellCheckListener.java create mode 100644 src/com/swabunga/spell/event/SpellChecker.java create mode 100644 src/com/swabunga/spell/event/StringWordTokenizer.java create mode 100644 src/com/swabunga/spell/event/TeXWordFinder.java create mode 100644 src/com/swabunga/spell/event/Word.java create mode 100644 src/com/swabunga/spell/event/WordFinder.java create mode 100644 src/com/swabunga/spell/event/WordNotFoundException.java create mode 100644 src/com/swabunga/spell/event/WordTokenizer.java create mode 100644 src/com/swabunga/spell/event/XMLWordFinder.java create mode 100644 src/com/swabunga/spell/swing/autospell/AutoSpellCheckHandler.java create mode 100644 src/com/swabunga/spell/swing/autospell/AutoSpellConstants.java create mode 100644 src/com/swabunga/spell/swing/autospell/AutoSpellEditorKit.java create mode 100644 src/com/swabunga/spell/swing/autospell/AutoSpellView.java create mode 100644 src/com/swabunga/spell/swing/autospell/AutoSpellViewFactory.java create mode 100644 src/com/swabunga/util/StringUtility.java create mode 100644 src/com/swabunga/util/VectorUtility.java create mode 100644 src/cx/fbn/nevernote/Global.class create mode 100644 src/cx/fbn/nevernote/Global.java create mode 100644 src/cx/fbn/nevernote/NeverNote.class create mode 100644 src/cx/fbn/nevernote/NeverNote.java create mode 100644 src/cx/fbn/nevernote/dialog/AccountDialog.class create mode 100644 src/cx/fbn/nevernote/dialog/AccountDialog.java create mode 100644 src/cx/fbn/nevernote/dialog/AssignTag.class create mode 100644 src/cx/fbn/nevernote/dialog/ConfigAppearancePage.class create mode 100644 src/cx/fbn/nevernote/dialog/ConfigAppearancePage.java create mode 100644 src/cx/fbn/nevernote/dialog/ConfigConnectionPage.class create mode 100644 src/cx/fbn/nevernote/dialog/ConfigConnectionPage.java create mode 100644 src/cx/fbn/nevernote/dialog/ConfigDebugPage.class create mode 100644 src/cx/fbn/nevernote/dialog/ConfigDebugPage.java create mode 100644 src/cx/fbn/nevernote/dialog/ConfigDialog.class create mode 100644 src/cx/fbn/nevernote/dialog/ConfigDialog.java create mode 100644 src/cx/fbn/nevernote/dialog/ConfigFormatsPage.class create mode 100644 src/cx/fbn/nevernote/dialog/ConfigGeneralPage.class create mode 100644 src/cx/fbn/nevernote/dialog/ConfigIndexPage.class create mode 100644 src/cx/fbn/nevernote/dialog/ConfigIndexPage.java create mode 100644 src/cx/fbn/nevernote/dialog/ConfigShowColumnsPage.class create mode 100644 src/cx/fbn/nevernote/dialog/ConfigShowColumnsPage.java create mode 100644 src/cx/fbn/nevernote/dialog/ConfigShowEditorButtonsPage.class create mode 100644 src/cx/fbn/nevernote/dialog/ConfigShowEditorButtonsPage.java create mode 100644 src/cx/fbn/nevernote/dialog/DatabaseLoginDialog.java create mode 100644 src/cx/fbn/nevernote/dialog/DatabaseStatus.class create mode 100644 src/cx/fbn/nevernote/dialog/DatabaseStatus.java create mode 100644 src/cx/fbn/nevernote/dialog/EnCryptDialog.class create mode 100644 src/cx/fbn/nevernote/dialog/EnCryptDialog.java create mode 100644 src/cx/fbn/nevernote/dialog/EnDecryptDialog.class create mode 100644 src/cx/fbn/nevernote/dialog/EnDecryptDialog.java create mode 100644 src/cx/fbn/nevernote/dialog/FindDialog.class create mode 100644 src/cx/fbn/nevernote/dialog/FindDialog.java create mode 100644 src/cx/fbn/nevernote/dialog/InsertLinkDialog.class create mode 100644 src/cx/fbn/nevernote/dialog/InsertLinkDialog.java create mode 100644 src/cx/fbn/nevernote/dialog/LoginDialog.class create mode 100644 src/cx/fbn/nevernote/dialog/LoginDialog.java create mode 100644 src/cx/fbn/nevernote/dialog/NotebookArchive.class create mode 100644 src/cx/fbn/nevernote/dialog/NotebookArchive.java create mode 100644 src/cx/fbn/nevernote/dialog/NotebookEdit.class create mode 100644 src/cx/fbn/nevernote/dialog/NotebookEdit.java create mode 100644 src/cx/fbn/nevernote/dialog/OnlineNoteHistory.java create mode 100644 src/cx/fbn/nevernote/dialog/PreviewDialog.java create mode 100644 src/cx/fbn/nevernote/dialog/PreviewImage.java create mode 100644 src/cx/fbn/nevernote/dialog/SavedSearchEdit.class create mode 100644 src/cx/fbn/nevernote/dialog/SavedSearchEdit.java create mode 100644 src/cx/fbn/nevernote/dialog/TableDialog.java create mode 100644 src/cx/fbn/nevernote/dialog/TagAssign.java create mode 100644 src/cx/fbn/nevernote/dialog/TagEdit.class create mode 100644 src/cx/fbn/nevernote/dialog/TagEdit.java create mode 100644 src/cx/fbn/nevernote/dialog/ThumbnailViewer.java create mode 100644 src/cx/fbn/nevernote/dialog/WatchFolder.java create mode 100644 src/cx/fbn/nevernote/dialog/WatchFolderAdd.java create mode 100644 src/cx/fbn/nevernote/evernote/EnCrypt.class create mode 100644 src/cx/fbn/nevernote/evernote/EnCrypt.java create mode 100644 src/cx/fbn/nevernote/evernote/EnmlConverter.class create mode 100644 src/cx/fbn/nevernote/evernote/EnmlConverter.java create mode 100644 src/cx/fbn/nevernote/filters/AttributeFilter.class create mode 100644 src/cx/fbn/nevernote/filters/AttributeFilter.java create mode 100644 src/cx/fbn/nevernote/filters/EnSearch.class create mode 100644 src/cx/fbn/nevernote/filters/EnSearch.java create mode 100644 src/cx/fbn/nevernote/filters/NoteSortFilterProxyModel.class create mode 100644 src/cx/fbn/nevernote/filters/NoteSortFilterProxyModel.java create mode 100644 src/cx/fbn/nevernote/filters/NotebookCounter.class create mode 100644 src/cx/fbn/nevernote/filters/NotebookCounter.java create mode 100644 src/cx/fbn/nevernote/filters/TagCounter.class create mode 100644 src/cx/fbn/nevernote/filters/TagCounter.java create mode 100644 src/cx/fbn/nevernote/filters/WordFilter.class create mode 100644 src/cx/fbn/nevernote/filters/WordFilter.java create mode 100644 src/cx/fbn/nevernote/gui/AttributeTreeWidget.class create mode 100644 src/cx/fbn/nevernote/gui/AttributeTreeWidget.java create mode 100644 src/cx/fbn/nevernote/gui/BrowserWindow.class create mode 100644 src/cx/fbn/nevernote/gui/BrowserWindow.java create mode 100644 src/cx/fbn/nevernote/gui/ColorMenu.java create mode 100644 src/cx/fbn/nevernote/gui/ContainsAttributeFilterTable.java create mode 100644 src/cx/fbn/nevernote/gui/ContentView.java create mode 100644 src/cx/fbn/nevernote/gui/DateAttributeFilterTable.class create mode 100644 src/cx/fbn/nevernote/gui/DateAttributeFilterTable.java create mode 100644 src/cx/fbn/nevernote/gui/FbnMenuBar.class create mode 100644 src/cx/fbn/nevernote/gui/FbnWebView.class create mode 100644 src/cx/fbn/nevernote/gui/MainMenuBar.java create mode 100644 src/cx/fbn/nevernote/gui/NotebookTreeWidget.class create mode 100644 src/cx/fbn/nevernote/gui/NotebookTreeWidget.java create mode 100644 src/cx/fbn/nevernote/gui/PDFPreview.java create mode 100644 src/cx/fbn/nevernote/gui/SavedSearchTreeWidget.class create mode 100644 src/cx/fbn/nevernote/gui/SavedSearchTreeWidget.java create mode 100644 src/cx/fbn/nevernote/gui/ShortcutKeys.class create mode 100644 src/cx/fbn/nevernote/gui/ShortcutKeys.java create mode 100644 src/cx/fbn/nevernote/gui/TableView.class create mode 100644 src/cx/fbn/nevernote/gui/TableView.java create mode 100644 src/cx/fbn/nevernote/gui/TagLineCompleter.class create mode 100644 src/cx/fbn/nevernote/gui/TagLineCompleter.java create mode 100644 src/cx/fbn/nevernote/gui/TagLineEdit.class create mode 100644 src/cx/fbn/nevernote/gui/TagLineEdit.java create mode 100644 src/cx/fbn/nevernote/gui/TagTreeWidget.class create mode 100644 src/cx/fbn/nevernote/gui/TagTreeWidget.java create mode 100644 src/cx/fbn/nevernote/gui/Thumbnailer.java create mode 100644 src/cx/fbn/nevernote/gui/TrashTreeWidget.class create mode 100644 src/cx/fbn/nevernote/gui/TrashTreeWidget.java create mode 100644 src/cx/fbn/nevernote/icons/appearance.jpg create mode 100644 src/cx/fbn/nevernote/icons/attribute.png create mode 100644 src/cx/fbn/nevernote/icons/back.png create mode 100644 src/cx/fbn/nevernote/icons/bold.gif create mode 100644 src/cx/fbn/nevernote/icons/bulletList.gif create mode 100644 src/cx/fbn/nevernote/icons/copy.gif create mode 100644 src/cx/fbn/nevernote/icons/cut.gif create mode 100644 src/cx/fbn/nevernote/icons/debug.jpg create mode 100644 src/cx/fbn/nevernote/icons/delete.png create mode 100644 src/cx/fbn/nevernote/icons/down.png create mode 100644 src/cx/fbn/nevernote/icons/email.png create mode 100644 src/cx/fbn/nevernote/icons/encrypt.png create mode 100644 src/cx/fbn/nevernote/icons/fontColor.gif create mode 100644 src/cx/fbn/nevernote/icons/fontHilight.gif create mode 100644 src/cx/fbn/nevernote/icons/forward.png create mode 100644 src/cx/fbn/nevernote/icons/hline.gif create mode 100644 src/cx/fbn/nevernote/icons/indent.gif create mode 100644 src/cx/fbn/nevernote/icons/italic.gif create mode 100644 src/cx/fbn/nevernote/icons/justify.gif create mode 100644 src/cx/fbn/nevernote/icons/justifyCenter.gif create mode 100644 src/cx/fbn/nevernote/icons/justifyFull.gif create mode 100644 src/cx/fbn/nevernote/icons/justifyLeft.gif create mode 100644 src/cx/fbn/nevernote/icons/justifyRight.gif create mode 100644 src/cx/fbn/nevernote/icons/left.gif create mode 100644 src/cx/fbn/nevernote/icons/nevernote.png create mode 100644 src/cx/fbn/nevernote/icons/new.png create mode 100644 src/cx/fbn/nevernote/icons/notebook-blue.png create mode 100644 src/cx/fbn/nevernote/icons/notebook-green.png create mode 100644 src/cx/fbn/nevernote/icons/notebook-red.png create mode 100644 src/cx/fbn/nevernote/icons/notebook-yellow.png create mode 100644 src/cx/fbn/nevernote/icons/numberList.gif create mode 100644 src/cx/fbn/nevernote/icons/outdent.gif create mode 100644 src/cx/fbn/nevernote/icons/paste.gif create mode 100644 src/cx/fbn/nevernote/icons/print.png create mode 100644 src/cx/fbn/nevernote/icons/redo.gif create mode 100644 src/cx/fbn/nevernote/icons/right.gif create mode 100644 src/cx/fbn/nevernote/icons/scissors.jpg create mode 100644 src/cx/fbn/nevernote/icons/search.png create mode 100644 src/cx/fbn/nevernote/icons/search_config.jpg create mode 100644 src/cx/fbn/nevernote/icons/searchclear.png create mode 100644 src/cx/fbn/nevernote/icons/show-columns.png create mode 100644 src/cx/fbn/nevernote/icons/splash_logo-new.png create mode 100644 src/cx/fbn/nevernote/icons/splash_logo.png create mode 100644 src/cx/fbn/nevernote/icons/strikethrough.gif create mode 100644 src/cx/fbn/nevernote/icons/synchronize-0.png create mode 100644 src/cx/fbn/nevernote/icons/synchronize-1.png create mode 100644 src/cx/fbn/nevernote/icons/synchronize-2.png create mode 100644 src/cx/fbn/nevernote/icons/synchronize-3.png create mode 100644 src/cx/fbn/nevernote/icons/synchronize.png create mode 100644 src/cx/fbn/nevernote/icons/synchronize2.png create mode 100644 src/cx/fbn/nevernote/icons/tag-tan.png create mode 100644 src/cx/fbn/nevernote/icons/tag.png create mode 100644 src/cx/fbn/nevernote/icons/trash.png create mode 100644 src/cx/fbn/nevernote/icons/underline.gif create mode 100644 src/cx/fbn/nevernote/icons/undo.gif create mode 100644 src/cx/fbn/nevernote/icons/up.png create mode 100644 src/cx/fbn/nevernote/icons/world.jpg create mode 100644 src/cx/fbn/nevernote/signals/DBRunnerSignal.class create mode 100644 src/cx/fbn/nevernote/signals/DBRunnerSignal.java create mode 100644 src/cx/fbn/nevernote/signals/NoteIndexSignal.class create mode 100644 src/cx/fbn/nevernote/signals/NoteIndexSignal.java create mode 100644 src/cx/fbn/nevernote/signals/NoteResourceSignal.class create mode 100644 src/cx/fbn/nevernote/signals/NoteResourceSignal.java create mode 100644 src/cx/fbn/nevernote/signals/NoteSignal.class create mode 100644 src/cx/fbn/nevernote/signals/NoteSignal.java create mode 100644 src/cx/fbn/nevernote/signals/NotebookSignal.class create mode 100644 src/cx/fbn/nevernote/signals/NotebookSignal.java create mode 100644 src/cx/fbn/nevernote/signals/SavedSearchSignal.class create mode 100644 src/cx/fbn/nevernote/signals/SavedSearchSignal.java create mode 100644 src/cx/fbn/nevernote/signals/StatusSignal.class create mode 100644 src/cx/fbn/nevernote/signals/StatusSignal.java create mode 100644 src/cx/fbn/nevernote/signals/SyncSignal.class create mode 100644 src/cx/fbn/nevernote/signals/SyncSignal.java create mode 100644 src/cx/fbn/nevernote/signals/TagSignal.class create mode 100644 src/cx/fbn/nevernote/signals/TagSignal.java create mode 100644 src/cx/fbn/nevernote/signals/ThreadSignal.class create mode 100644 src/cx/fbn/nevernote/signals/ThreadSignal.java create mode 100644 src/cx/fbn/nevernote/signals/TrashSignal.java create mode 100644 src/cx/fbn/nevernote/sql/DBLock.class create mode 100644 src/cx/fbn/nevernote/sql/DatabaseConnection.class create mode 100644 src/cx/fbn/nevernote/sql/DatabaseConnection.java create mode 100644 src/cx/fbn/nevernote/sql/DeletedItemRecord.class create mode 100644 src/cx/fbn/nevernote/sql/DeletedTable.class create mode 100644 src/cx/fbn/nevernote/sql/DeletedTable.java create mode 100644 src/cx/fbn/nevernote/sql/IndexConnection.class create mode 100644 src/cx/fbn/nevernote/sql/InvalidXMLTable.java create mode 100644 src/cx/fbn/nevernote/sql/NoteResourceTable.class create mode 100644 src/cx/fbn/nevernote/sql/NoteResourceTable.java create mode 100644 src/cx/fbn/nevernote/sql/NoteTable.class create mode 100644 src/cx/fbn/nevernote/sql/NoteTable.java create mode 100644 src/cx/fbn/nevernote/sql/NoteTagsRecord.class create mode 100644 src/cx/fbn/nevernote/sql/NoteTagsTable.class create mode 100644 src/cx/fbn/nevernote/sql/NoteTagsTable.java create mode 100644 src/cx/fbn/nevernote/sql/NotebookTable.class create mode 100644 src/cx/fbn/nevernote/sql/NotebookTable.java create mode 100644 src/cx/fbn/nevernote/sql/ResourceConnection.class create mode 100644 src/cx/fbn/nevernote/sql/SavedSearchTable.class create mode 100644 src/cx/fbn/nevernote/sql/SavedSearchTable.java create mode 100644 src/cx/fbn/nevernote/sql/SyncTable.java create mode 100644 src/cx/fbn/nevernote/sql/TagTable.class create mode 100644 src/cx/fbn/nevernote/sql/TagTable.java create mode 100644 src/cx/fbn/nevernote/sql/WatchFolderTable.java create mode 100644 src/cx/fbn/nevernote/sql/WordsTable.class create mode 100644 src/cx/fbn/nevernote/sql/WordsTable.java create mode 100644 src/cx/fbn/nevernote/sql/driver/NSqlQuery.java create mode 100644 src/cx/fbn/nevernote/sql/requests/DBRunnerRequest.class create mode 100644 src/cx/fbn/nevernote/sql/requests/DBRunnerRequest.java create mode 100644 src/cx/fbn/nevernote/sql/requests/DatabaseRequest.class create mode 100644 src/cx/fbn/nevernote/sql/requests/DatabaseRequest.java create mode 100644 src/cx/fbn/nevernote/sql/requests/DeletedItemRequest.class create mode 100644 src/cx/fbn/nevernote/sql/requests/DeletedItemRequest.java create mode 100644 src/cx/fbn/nevernote/sql/requests/EnSearchRequest.class create mode 100644 src/cx/fbn/nevernote/sql/requests/EnSearchRequest.java create mode 100644 src/cx/fbn/nevernote/sql/requests/InvalidXMLRequest.java create mode 100644 src/cx/fbn/nevernote/sql/requests/NoteRequest.class create mode 100644 src/cx/fbn/nevernote/sql/requests/NoteRequest.java create mode 100644 src/cx/fbn/nevernote/sql/requests/NoteTagsRequest.class create mode 100644 src/cx/fbn/nevernote/sql/requests/NoteTagsRequest.java create mode 100644 src/cx/fbn/nevernote/sql/requests/NotebookRequest.class create mode 100644 src/cx/fbn/nevernote/sql/requests/NotebookRequest.java create mode 100644 src/cx/fbn/nevernote/sql/requests/ResourceRequest.class create mode 100644 src/cx/fbn/nevernote/sql/requests/ResourceRequest.java create mode 100644 src/cx/fbn/nevernote/sql/requests/SavedSearchRequest.class create mode 100644 src/cx/fbn/nevernote/sql/requests/SavedSearchRequest.java create mode 100644 src/cx/fbn/nevernote/sql/requests/SyncRequest.java create mode 100644 src/cx/fbn/nevernote/sql/requests/TagRequest.class create mode 100644 src/cx/fbn/nevernote/sql/requests/TagRequest.java create mode 100644 src/cx/fbn/nevernote/sql/requests/WatchFolderRequest.java create mode 100644 src/cx/fbn/nevernote/sql/requests/WordRequest.java create mode 100644 src/cx/fbn/nevernote/sql/runners/DeletedItemRecord.class create mode 100644 src/cx/fbn/nevernote/sql/runners/DeletedItemRecord.java create mode 100644 src/cx/fbn/nevernote/sql/runners/NoteTagsRecord.class create mode 100644 src/cx/fbn/nevernote/sql/runners/NoteTagsRecord.java create mode 100644 src/cx/fbn/nevernote/sql/runners/RDatabaseConnection.class create mode 100644 src/cx/fbn/nevernote/sql/runners/RDatabaseConnection.java create mode 100644 src/cx/fbn/nevernote/sql/runners/RDeletedTable.class create mode 100644 src/cx/fbn/nevernote/sql/runners/RDeletedTable.java create mode 100644 src/cx/fbn/nevernote/sql/runners/REnSearch.class create mode 100644 src/cx/fbn/nevernote/sql/runners/REnSearch.java create mode 100644 src/cx/fbn/nevernote/sql/runners/RInvalidXMLTable.java create mode 100644 src/cx/fbn/nevernote/sql/runners/RNoteResourceTable.class create mode 100644 src/cx/fbn/nevernote/sql/runners/RNoteResourceTable.java create mode 100644 src/cx/fbn/nevernote/sql/runners/RNoteTable.class create mode 100644 src/cx/fbn/nevernote/sql/runners/RNoteTable.java create mode 100644 src/cx/fbn/nevernote/sql/runners/RNoteTagsTable.class create mode 100644 src/cx/fbn/nevernote/sql/runners/RNoteTagsTable.java create mode 100644 src/cx/fbn/nevernote/sql/runners/RNotebookTable.class create mode 100644 src/cx/fbn/nevernote/sql/runners/RNotebookTable.java create mode 100644 src/cx/fbn/nevernote/sql/runners/RSavedSearchTable.class create mode 100644 src/cx/fbn/nevernote/sql/runners/RSavedSearchTable.java create mode 100644 src/cx/fbn/nevernote/sql/runners/RSyncTable.java create mode 100644 src/cx/fbn/nevernote/sql/runners/RTagTable.class create mode 100644 src/cx/fbn/nevernote/sql/runners/RTagTable.java create mode 100644 src/cx/fbn/nevernote/sql/runners/RWatchFolderTable.java create mode 100644 src/cx/fbn/nevernote/sql/runners/RWordsTable.java create mode 100644 src/cx/fbn/nevernote/sql/runners/WatchFolderRecord.java create mode 100644 src/cx/fbn/nevernote/threads/CounterRunner.class create mode 100644 src/cx/fbn/nevernote/threads/CounterRunner.java create mode 100644 src/cx/fbn/nevernote/threads/DBRunner.class create mode 100644 src/cx/fbn/nevernote/threads/DBRunner.java create mode 100644 src/cx/fbn/nevernote/threads/IndexRunner.class create mode 100644 src/cx/fbn/nevernote/threads/IndexRunner.java create mode 100644 src/cx/fbn/nevernote/threads/SaveRunner.java create mode 100644 src/cx/fbn/nevernote/threads/SyncRunner.class create mode 100644 src/cx/fbn/nevernote/threads/SyncRunner.java create mode 100644 src/cx/fbn/nevernote/utilities/AESEncrypter.class create mode 100644 src/cx/fbn/nevernote/utilities/AESEncrypter.java create mode 100644 src/cx/fbn/nevernote/utilities/ApplicationLogger.class create mode 100644 src/cx/fbn/nevernote/utilities/ApplicationLogger.java create mode 100644 src/cx/fbn/nevernote/utilities/Base64$1.class create mode 100644 src/cx/fbn/nevernote/utilities/Base64$InputStream.class create mode 100644 src/cx/fbn/nevernote/utilities/Base64$OutputStream.class create mode 100644 src/cx/fbn/nevernote/utilities/Base64.class create mode 100644 src/cx/fbn/nevernote/utilities/Base64.java create mode 100644 src/cx/fbn/nevernote/utilities/Base64Coder.class create mode 100644 src/cx/fbn/nevernote/utilities/FileImporter.java create mode 100644 src/cx/fbn/nevernote/utilities/ListManager.class create mode 100644 src/cx/fbn/nevernote/utilities/ListManager.java create mode 100644 src/cx/fbn/nevernote/utilities/OutStream.class create mode 100644 src/cx/fbn/nevernote/utilities/OutStream.java create mode 100644 src/cx/fbn/nevernote/utilities/Pair.java create mode 100644 src/cx/fbn/nevernote/utilities/StringUtils.java create mode 100644 src/cx/fbn/nevernote/utilities/SyncTimes.class create mode 100644 src/cx/fbn/nevernote/utilities/SyncTimes.java create mode 100644 src/cx/fbn/nevernote/xml/EnmlException.java create mode 100644 src/cx/fbn/nevernote/xml/ExportData.java create mode 100644 src/cx/fbn/nevernote/xml/ImportData.java create mode 100644 src/cx/fbn/nevernote/xml/ResourceXMLParse.class create mode 100644 src/cx/fbn/nevernote/xml/XMLCleanup.java create mode 100644 src/cx/fbn/nevernote/xml/XMLInsertHilight.java create mode 100644 src/cx/fbn/nevernote/xml/XMLNoteRepair.java create mode 100644 src/cx/fbn/nevernote/xml/XMLNoteRepairHandler.java create mode 100644 src/cx/fbn/nevernote/xml/XMLValidator.class create mode 100644 src/cx/fbn/nevernote/xml/XmlNoteRepair.class create mode 100644 src/cx/fbn/nevernote/xml/XmlNoteRepairHandler.class diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..5e183da --- /dev/null +++ b/.classpath @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c5e82d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bin \ No newline at end of file diff --git a/.project b/.project new file mode 100644 index 0000000..084f199 --- /dev/null +++ b/.project @@ -0,0 +1,22 @@ + + + NeverNote + + + + + + com.trolltech.qtjambi.juicBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000..cee40d6 --- /dev/null +++ b/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,54 @@ +#Mon Feb 01 13:37:03 EST 2010 +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_to_enhanced_for_loop=true +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=false +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_trailing_whitespaces=false +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=false +sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/.settings/org.eclipse.ltk.core.refactoring.prefs b/.settings/org.eclipse.ltk.core.refactoring.prefs new file mode 100644 index 0000000..e9f6479 --- /dev/null +++ b/.settings/org.eclipse.ltk.core.refactoring.prefs @@ -0,0 +1,3 @@ +#Thu Aug 06 07:27:30 EDT 2009 +eclipse.preferences.version=1 +org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/src/.classpath b/src/.classpath new file mode 100644 index 0000000..ad27fe8 --- /dev/null +++ b/src/.classpath @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/.project b/src/.project new file mode 100644 index 0000000..0f09a69 --- /dev/null +++ b/src/.project @@ -0,0 +1,22 @@ + + + NeverNote 0.80 + + + + + + com.trolltech.qtjambi.juicBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/src/com/swabunga/spell/engine/Configuration.java b/src/com/swabunga/spell/engine/Configuration.java new file mode 100644 index 0000000..389fac5 --- /dev/null +++ b/src/com/swabunga/spell/engine/Configuration.java @@ -0,0 +1,153 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.engine; + +import java.security.AccessControlException; + + +/** + * The various settings used to control how a spell checker works are read from here. + * Includes the COST_* constants that decide how to figure the cost of converting one word to + * another in the EditDistance class. + *

+ * Also includes SPELL_* constants that control how misspellings are detected, for example, how to handle + * mixed-case words, etc. + * + * @author aim4min + * @see EditDistance + */ +public abstract class Configuration { + + /** used by EditDistance: the cost of having to remove a character
(integer greater than 0) */ + public static final String COST_REMOVE_CHAR = "EDIT_DEL1"; + + /** used by EditDistance: the cost of having to insert a character
(integer greater than 0)*/ + public static final String COST_INSERT_CHAR = "EDIT_DEL2"; + + /** + * used by EditDistance: the cost of having to swap two adjoining characters + * for the swap value to ever be used, it should be smaller than the COST_REMOVE_CHAR or COST_INSERT_CHAR values + *
(integer greater than 0) + */ + public static final String COST_SWAP_CHARS = "EDIT_SWAP"; + + /** + * used by EditDistance: the cost of having to change case, for example, from i to I. + *
(integer greater than 0) + */ + public static final String COST_CHANGE_CASE = "EDIT_CASE"; + + /** + * used by EditDistance: the cost of having to substitute one character for another + * for the sub value to ever be used, it should be smaller than the COST_REMOVE_CHAR or COST_INSERT_CHAR values + *
(integer greater than 0) + */ + public static final String COST_SUBST_CHARS = "EDIT_SUB"; + +// public static final String EDIT_SIMILAR = "EDIT_SIMILAR"; //DMV: these does not seem to be used at all +// public static final String EDIT_MIN = "EDIT_MIN"; +// public static final String EDIT_MAX = "EDIT_MAX"; + + /** the maximum cost of suggested spelling. Any suggestions that cost more are thrown away + *
integer greater than 1) + */ + public static final String SPELL_THRESHOLD = "SPELL_THRESHOLD"; + + /** words that are all upper case are not spell checked, example: "CIA"
(boolean) */ + public static final String SPELL_IGNOREUPPERCASE = "SPELL_IGNOREUPPERCASE"; + /** words that have mixed case are not spell checked, example: "SpellChecker"
(boolean) */ + public static final String SPELL_IGNOREMIXEDCASE = "SPELL_IGNOREMIXEDCASE"; + /** words that look like an Internet address are not spell checked, example: "http://www.google.com"
(boolean)*/ + public static final String SPELL_IGNOREINTERNETADDRESSES = "SPELL_IGNOREINTERNETADDRESS"; + /** words that have digits in them are not spell checked, example: "mach5"
(boolean) */ + public static final String SPELL_IGNOREDIGITWORDS = "SPELL_IGNOREDIGITWORDS"; + /** I don't know what this does. It doesn't seem to be used
(boolean) */ + public static final String SPELL_IGNOREMULTIPLEWORDS = "SPELL_IGNOREMULTIPLEWORDS"; + /** the first word of a sentence is expected to start with an upper case letter
(boolean) */ + public static final String SPELL_IGNORESENTENCECAPITALIZATION = "SPELL_IGNORESENTENCECAPTILIZATION"; + + /** + * Gets one of the integer constants + * @param key one of the integer constants defined in this class + * @return int value of the setting + */ + public abstract int getInteger(String key); + + /** + * Gets one of the boolean constants + * @param key one of the boolean constants defined in this class + * @return boolean value of the setting + */ + public abstract boolean getBoolean(String key); + + /** + * Sets one of the integer constants + * @param key one of the integer constants defined in this class + * @param value new integer value of the constant + */ + public abstract void setInteger(String key, int value); + + /** + * Sets one of the boolean constants + * @param key one of the boolean constants defined in this class + * @param value new boolean value of this setting + */ + public abstract void setBoolean(String key, boolean value); + + /** + * gets a new default Configuration + * @return Configuration + */ + public static final Configuration getConfiguration() { + try { + String config = System.getProperty("jazzy.config"); // added by bd + if (config != null && config.length() > 0) + return getConfiguration(config); + } catch (AccessControlException e) { + e.printStackTrace(); + } + return getConfiguration(null); + } + + /** + * Returns a new instance of a Configuration class + * @param className - the class to return, must be based on Configuration + * @return Configuration + */ + public static final Configuration getConfiguration(String className) { + + Configuration result; + + if (className != null && className.length() > 0) { + try { + result = (Configuration) Class.forName(className).newInstance(); + } catch (InstantiationException e) { + result = new PropertyConfiguration(); + } catch (IllegalAccessException e) { + result = new PropertyConfiguration(); + } catch (ClassNotFoundException e) { + result = new PropertyConfiguration(); + } + } else { + result = new PropertyConfiguration(); + } + return result; + } +} diff --git a/src/com/swabunga/spell/engine/DoubleMeta.java b/src/com/swabunga/spell/engine/DoubleMeta.java new file mode 100644 index 0000000..343c169 --- /dev/null +++ b/src/com/swabunga/spell/engine/DoubleMeta.java @@ -0,0 +1,713 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.engine; + + +/** + * A phonetic encoding algorithm that takes an English word and computes a phonetic version of it. This + * allows for phonetic matches in a spell checker. This class is a port of the C++ DoubleMetaphone() class, + * which was intended to return two possible phonetic translations for certain words, although the Java version + * only seems to be concerned with one, making the "double" part erroneous. + *
+ * source code for the original C++ can be found + * here: http://aspell.sourceforge.net/metaphone/ + * DoubleMetaphone does some processing, such as uppercasing, on the input string first to normalize it. Then, to + * create the key, the function traverses the input string in a while loop, sending successive characters into a giant + * switch statement. Before determining the appropriate pronunciation, the algorithm considers the context + * surrounding each character within the input string. + *

+ * Things that were changed: + *
The alternate flag could be set to true but was never checked so why bother with it. REMOVED + *
Why was this class serializable? + *
The primary, in, length and last variables could be initialized and local to the + * process method and references passed around the appropriate methods. As such there are + * no class variables and this class becomes firstly threadsafe and secondly could be static final. + *
The function call SlavoGermaic was called repeatedly in the process function, it is now only called once. + * + */ +public class DoubleMeta implements Transformator { + + /** + * The replace list is used in the getSuggestions method. + * All of the letters in the misspelled word are replaced with the characters from + * this list to try and generate more suggestions, which implies l*n tries, + * if l is the size of the string, and n is the size of this list. + * + * In addition to that, each of these letters is added to the misspelled word. + */ + private static char[] replaceList = {'A', 'B', 'X', 'S', 'K', 'J', 'T', 'F', 'H', 'L', 'M', 'N', 'P', 'R', '0'}; + + + private static final String[] myList = {"GN", "KN", "PN", "WR", "PS", ""}; + private static final String[] list1 = {"ACH", ""}; + private static final String[] list2 = {"BACHER", "MACHER", ""}; + private static final String[] list3 = {"CAESAR", ""}; + private static final String[] list4 = {"CHIA", ""}; + private static final String[] list5 = {"CH", ""}; + private static final String[] list6 = {"CHAE", ""}; + private static final String[] list7 = {"HARAC", "HARIS", ""}; + private static final String[] list8 = {"HOR", "HYM", "HIA", "HEM", ""}; + private static final String[] list9 = {"CHORE", ""}; + private static final String[] list10 = {"VAN ", "VON ", ""}; + private static final String[] list11 = {"SCH", ""}; + private static final String[] list12 = {"ORCHES", "ARCHIT", "ORCHID", ""}; + private static final String[] list13 = {"T", "S", ""}; + private static final String[] list14 = {"A", "O", "U", "E", ""}; + private static final String[] list15 = {"L", "R", "N", "M", "B", "H", "F", "V", "W", " ", ""}; + private static final String[] list16 = {"MC", ""}; + private static final String[] list17 = {"CZ", ""}; + private static final String[] list18 = {"WICZ", ""}; + private static final String[] list19 = {"CIA", ""}; + private static final String[] list20 = {"CC", ""}; + private static final String[] list21 = {"I", "E", "H", ""}; + private static final String[] list22 = {"HU", ""}; + private static final String[] list23 = {"UCCEE", "UCCES", ""}; + private static final String[] list24 = {"CK", "CG", "CQ", ""}; + private static final String[] list25 = {"CI", "CE", "CY", ""}; +// DMV: used by the orininal code which returned two phonetic code, but not the current code +// private static final String[] list26 = { +// "CIO", "CIE", "CIA", "" +// }; + private static final String[] list27 = {" C", " Q", " G", ""}; + private static final String[] list28 = {"C", "K", "Q", ""}; + private static final String[] list29 = {"CE", "CI", ""}; + private static final String[] list30 = {"DG", ""}; + private static final String[] list31 = {"I", "E", "Y", ""}; + private static final String[] list32 = {"DT", "DD", ""}; + private static final String[] list33 = {"B", "H", "D", ""}; + private static final String[] list34 = {"B", "H", "D", ""}; + private static final String[] list35 = {"B", "H", ""}; + private static final String[] list36 = {"C", "G", "L", "R", "T", ""}; + private static final String[] list37 = {"EY", ""}; + private static final String[] list38 = {"LI", ""}; + private static final String[] list39 = {"ES", "EP", "EB", "EL", "EY", "IB", "IL", "IN", "IE", "EI", "ER", ""}; + private static final String[] list40 = {"ER", ""}; + private static final String[] list41 = {"DANGER", "RANGER", "MANGER", ""}; + private static final String[] list42 = {"E", "I", ""}; + private static final String[] list43 = {"RGY", "OGY", ""}; + private static final String[] list44 = {"E", "I", "Y", ""}; + private static final String[] list45 = {"AGGI", "OGGI", ""}; + private static final String[] list46 = {"VAN ", "VON ", ""}; + private static final String[] list47 = {"SCH", ""}; + private static final String[] list48 = {"ET", ""}; + +// DMV: used by the orininal code which returned two phonetic code, but not the current code +// private static final String[] list49 = { +// "IER ", "" +// }; + private static final String[] list50 = {"JOSE", ""}; + private static final String[] list51 = {"SAN ", ""}; + private static final String[] list52 = {"SAN ", ""}; + private static final String[] list53 = {"JOSE", ""}; + private static final String[] list54 = {"L", "T", "K", "S", "N", "M", "B", "Z", ""}; + private static final String[] list55 = {"S", "K", "L", ""}; + private static final String[] list56 = {"ILLO", "ILLA", "ALLE", ""}; + private static final String[] list57 = {"AS", "OS", ""}; + private static final String[] list58 = {"A", "O", ""}; + private static final String[] list59 = {"ALLE", ""}; + private static final String[] list60 = {"UMB", ""}; + private static final String[] list61 = {"ER", ""}; + private static final String[] list62 = {"P", "B", ""}; + private static final String[] list63 = {"IE", ""}; + private static final String[] list64 = {"ME", "MA", ""}; + private static final String[] list65 = {"ISL", "YSL", ""}; + private static final String[] list66 = {"SUGAR", ""}; + private static final String[] list67 = {"SH", ""}; + private static final String[] list68 = {"HEIM", "HOEK", "HOLM", "HOLZ", ""}; + private static final String[] list69 = {"SIO", "SIA", ""}; + private static final String[] list70 = {"SIAN", ""}; + private static final String[] list71 = {"M", "N", "L", "W", ""}; + private static final String[] list72 = {"Z", ""}; + private static final String[] list73 = {"Z", ""}; + private static final String[] list74 = {"SC", ""}; + private static final String[] list75 = {"OO", "ER", "EN", "UY", "ED", "EM", ""}; + private static final String[] list76 = {"ER", "EN", ""}; + private static final String[] list77 = {"I", "E", "Y", ""}; + private static final String[] list78 = {"AI", "OI", ""}; + private static final String[] list79 = {"S", "Z", ""}; + private static final String[] list80 = {"TION", ""}; + private static final String[] list81 = {"TIA", "TCH", ""}; + private static final String[] list82 = {"TH", ""}; + private static final String[] list83 = {"TTH", ""}; + private static final String[] list84 = {"OM", "AM", ""}; + private static final String[] list85 = {"VAN ", "VON ", ""}; + private static final String[] list86 = {"SCH", ""}; + private static final String[] list87 = {"T", "D", ""}; + private static final String[] list88 = {"WR", ""}; + private static final String[] list89 = {"WH", ""}; + private static final String[] list90 = {"EWSKI", "EWSKY", "OWSKI", "OWSKY", ""}; + private static final String[] list91 = {"SCH", ""}; + private static final String[] list92 = {"WICZ", "WITZ", ""}; + private static final String[] list93 = {"IAU", "EAU", ""}; + private static final String[] list94 = {"AU", "OU", ""}; + private static final String[] list95 = {"C", "X", ""}; + +// DMV: used by the orininal code which returned two phonetic code, but not the current code +// private static final String[] list96 = { +// "ZO", "ZI", "ZA", "" +// }; + + /** + * put your documentation comment here + * @return + */ + private final static boolean SlavoGermanic(String in) { + if ((in.indexOf("W") > -1) || (in.indexOf("K") > -1) || (in.indexOf("CZ") > -1) || (in.indexOf("WITZ") > -1)) + return true; + return false; + } + + /** + * put your documentation comment here + * @param main + */ + private final static void MetaphAdd(StringBuffer primary, String main) { + if (main != null) { + primary.append(main); + } + } + + private final static void MetaphAdd(StringBuffer primary, char main) { + primary.append(main); + } + + /** + * put your documentation comment here + * @param at + * @return + */ + private final static boolean isVowel(String in, int at, int length) { + if ((at < 0) || (at >= length)) + return false; + char it = in.charAt(at); + if ((it == 'A') || (it == 'E') || (it == 'I') || (it == 'O') || (it == 'U') || (it == 'Y')) + return true; + return false; + } + + /** + * put your documentation comment here + * @param string + * @param start + * @param length + * @param list + * @return + */ + private final static boolean stringAt(String string, int start, int length, String[] list) { + if ((start < 0) || (start >= string.length()) || list.length == 0) + return false; + String substr = string.substring(start, start + length); + for (int i = 0; i < list.length; i++) { + if (list[i].equals(substr)) + return true; + } + return false; + } + + /** + * Take the given word, and return the best phonetic hash for it. + * Vowels are minimized as much as possible, and consenants + * that have similiar sounds are converted to the same consenant + * for example, 'v' and 'f' are both converted to 'f' + * @param word the texte to transform + * @return the result of the phonetic transformation + */ + public final String transform(String word) { + StringBuffer primary = new StringBuffer(word.length() + 5); + String in = word.toUpperCase() + " "; + int current = 0; + int length = in.length(); + if (length < 1) + return ""; + int last = length - 1; + boolean isSlavoGermaic = SlavoGermanic(in); + if (stringAt(in, 0, 2, myList)) + current += 1; + if (in.charAt(0) == 'X') { + MetaphAdd(primary, 'S'); + current += 1; + } + while (current < length) { + switch (in.charAt(current)) { + case 'A': + case 'E': + case 'I': + case 'O': + case 'U': + case 'Y': + if (current == 0) + MetaphAdd(primary, 'A'); + current += 1; + break; + case 'B': + MetaphAdd(primary, 'P'); + if (in.charAt(current + 1) == 'B') + current += 2; + else + current += 1; + break; + case '\u00C7': + MetaphAdd(primary, 'S'); + current += 1; + break; + case 'C': + if ((current > 1) && !isVowel(in, current - 2, length) && stringAt(in, (current - 1), 3, list1) && (in.charAt(current + 2) != 'I') && (in.charAt(current + 2) != 'E') || stringAt(in, (current - 2), 6, list2)) { + MetaphAdd(primary, 'K'); + current += 2; + break; + } + if ((current == 0) && stringAt(in, current, 6, list3)) { + MetaphAdd(primary, 'S'); + current += 2; + break; + } + if (stringAt(in, current, 4, list4)) { + MetaphAdd(primary, 'K'); + current += 2; + break; + } + if (stringAt(in, current, 2, list5)) { + if ((current > 0) && stringAt(in, current, 4, list6)) { + MetaphAdd(primary, 'K'); + current += 2; + break; + } + if ((current == 0) && stringAt(in, (current + 1), 5, list7) || stringAt(in, current + 1, 3, list8) && !stringAt(in, 0, 5, list9)) { + MetaphAdd(primary, 'K'); + current += 2; + break; + } + if (stringAt(in, 0, 4, list10) || stringAt(in, 0, 3, list11) || stringAt(in, current - 2, 6, list12) || stringAt(in, current + 2, 1, list13) || (stringAt(in, current - 1, 1, list14) || (current == 0)) && stringAt(in, current + 2, 1, list15)) { + MetaphAdd(primary, 'K'); + } else { + if (current > 0) { + if (stringAt(in, 0, 2, list16)) + MetaphAdd(primary, 'K'); + else + MetaphAdd(primary, 'X'); + } else { + MetaphAdd(primary, 'X'); + } + } + current += 2; + break; + } + if (stringAt(in, current, 2, list17) && !stringAt(in, current, 4, list18)) { + MetaphAdd(primary, 'S'); + current += 2; + break; + } + if (stringAt(in, current, 2, list19)) { + MetaphAdd(primary, 'X'); + current += 2; + break; + } + if (stringAt(in, current, 2, list20) && !((current == 1) && in.charAt(0) == 'M')) { + if (stringAt(in, current + 2, 1, list21) && !stringAt(in, current + 2, 2, list22)) { + if (((current == 1) && (in.charAt(current - 1) == 'A')) || stringAt(in, (current - 1), 5, list23)) + MetaphAdd(primary, "KS"); + else + MetaphAdd(primary, 'X'); + current += 3; + break; + } else { + MetaphAdd(primary, 'K'); + current += 2; + break; + } + } + if (stringAt(in, current, 2, list24)) { + MetaphAdd(primary, 'K'); + current += 2; + break; + } else if (stringAt(in, current, 2, list25)) { + MetaphAdd(primary, 'S'); + current += 2; + break; + } + + MetaphAdd(primary, 'K'); + if (stringAt(in, current + 1, 2, list27)) + current += 3; + else if (stringAt(in, current + 1, 1, list28) && !stringAt(in, current + 1, 2, list29)) + current += 2; + else + current += 1; + break; + case 'D': + if (stringAt(in, current, 2, list30)) { + if (stringAt(in, current + 2, 1, list31)) { + MetaphAdd(primary, 'J'); + current += 3; + break; + } else { + MetaphAdd(primary, "TK"); + current += 2; + break; + } + } + MetaphAdd(primary, 'T'); + if (stringAt(in, current, 2, list32)) { + current += 2; + } else { + current += 1; + } + break; + case 'F': + if (in.charAt(current + 1) == 'F') + current += 2; + else + current += 1; + MetaphAdd(primary, 'F'); + break; + case 'G': + if (in.charAt(current + 1) == 'H') { + if ((current > 0) && !isVowel(in, current - 1, length)) { + MetaphAdd(primary, 'K'); + current += 2; + break; + } + if (current < 3) { + if (current == 0) { + if (in.charAt(current + 2) == 'I') + MetaphAdd(primary, 'J'); + else + MetaphAdd(primary, 'K'); + current += 2; + break; + } + } + if ((current > 1) && stringAt(in, current - 2, 1, list33) || ((current > 2) && stringAt(in, current - 3, 1, list34)) || ((current > 3) && stringAt(in, current - 4, 1, list35))) { + current += 2; + break; + } else { + if ((current > 2) && (in.charAt(current - 1) == 'U') && stringAt(in, current - 3, 1, list36)) { + MetaphAdd(primary, 'F'); + } else { + if ((current > 0) && (in.charAt(current - 1) != 'I')) + MetaphAdd(primary, 'K'); + } + current += 2; + break; + } + } + if (in.charAt(current + 1) == 'N') { + if ((current == 1) && isVowel(in, 0, length) && !isSlavoGermaic) { + MetaphAdd(primary, "KN"); + } else { + if (!stringAt(in, current + 2, 2, list37) && (in.charAt(current + 1) != 'Y') && !isSlavoGermaic) { + MetaphAdd(primary, "N"); + } else { + MetaphAdd(primary, "KN"); + } + } + current += 2; + break; + } + if (stringAt(in, current + 1, 2, list38) && !isSlavoGermaic) { + MetaphAdd(primary, "KL"); + current += 2; + break; + } + if ((current == 0) && ((in.charAt(current + 1) == 'Y') || stringAt(in, current + 1, 2, list39))) { + MetaphAdd(primary, 'K'); + current += 2; + break; + } + if ((stringAt(in, current + 1, 2, list40) || (in.charAt(current + 1) == 'Y')) && !stringAt(in, 0, 6, list41) && !stringAt(in, current - 1, 1, list42) && !stringAt(in, current - 1, 3, list43)) { + MetaphAdd(primary, 'K'); + current += 2; + break; + } + if (stringAt(in, current + 1, 1, list44) || stringAt(in, current - 1, 4, list45)) { + if (stringAt(in, 0, 4, list46) || stringAt(in, 0, 3, list47) || stringAt(in, current + 1, 2, list48)) { + MetaphAdd(primary, 'K'); + } else { + MetaphAdd(primary, 'J'); + } + current += 2; + break; + } + if (in.charAt(current + 1) == 'G') + current += 2; + else + current += 1; + MetaphAdd(primary, 'K'); + break; + case 'H': + if (((current == 0) || isVowel(in, current - 1, length)) && isVowel(in, current + 1, length)) { + MetaphAdd(primary, 'H'); + current += 2; + } else { + current += 1; + } + break; + case 'J': + if (stringAt(in, current, 4, list50) || stringAt(in, 0, 4, list51)) { + if ((current == 0) && (in.charAt(current + 4) == ' ') || stringAt(in, 0, 4, list52)) { + MetaphAdd(primary, 'H'); + } else { + MetaphAdd(primary, 'J'); + } + current += 1; + break; + } + if ((current == 0) && !stringAt(in, current, 4, list53)) { + MetaphAdd(primary, 'J'); + } else { + if (isVowel(in, current - 1, length) && !isSlavoGermaic && ((in.charAt(current + 1) == 'A') || in.charAt(current + 1) == 'O')) { + MetaphAdd(primary, 'J'); + } else { + if (current == last) { + MetaphAdd(primary, 'J'); + } else { + if (!stringAt(in, current + 1, 1, list54) && !stringAt(in, current - 1, 1, list55)) { + MetaphAdd(primary, 'J'); + } + } + } + } + if (in.charAt(current + 1) == 'J') + current += 2; + else + current += 1; + break; + case 'K': + if (in.charAt(current + 1) == 'K') + current += 2; + else + current += 1; + MetaphAdd(primary, 'K'); + break; + case 'L': + if (in.charAt(current + 1) == 'L') { + if (((current == (length - 3)) && stringAt(in, current - 1, 4, list56)) || ((stringAt(in, last - 1, 2, list57) || stringAt(in, last, 1, list58)) && stringAt(in, current - 1, 4, list59))) { + MetaphAdd(primary, 'L'); + current += 2; + break; + } + current += 2; + } else + current += 1; + MetaphAdd(primary, 'L'); + break; + case 'M': + if ((stringAt(in, current - 1, 3, list60) && (((current + 1) == last) || stringAt(in, current + 2, 2, list61))) || (in.charAt(current + 1) == 'M')) + current += 2; + else + current += 1; + MetaphAdd(primary, 'M'); + break; + case 'N': + if (in.charAt(current + 1) == 'N') + current += 2; + else + current += 1; + MetaphAdd(primary, 'N'); + break; + case '\u00D1': + current += 1; + MetaphAdd(primary, 'N'); + break; + case 'P': + if (in.charAt(current + 1) == 'N') { + MetaphAdd(primary, 'F'); + current += 2; + break; + } + if (stringAt(in, current + 1, 1, list62)) + current += 2; + else + current += 1; + MetaphAdd(primary, 'P'); + break; + case 'Q': + if (in.charAt(current + 1) == 'Q') + current += 2; + else + current += 1; + MetaphAdd(primary, 'K'); + break; + case 'R': + if ((current == last) && !isSlavoGermaic && stringAt(in, current - 2, 2, list63) && !stringAt(in, current - 4, 2, list64)) { +// MetaphAdd(primary, ""); + } else + MetaphAdd(primary, 'R'); + if (in.charAt(current + 1) == 'R') + current += 2; + else + current += 1; + break; + case 'S': + if (stringAt(in, current - 1, 3, list65)) { + current += 1; + break; + } + if ((current == 0) && stringAt(in, current, 5, list66)) { + MetaphAdd(primary, 'X'); + current += 1; + break; + } + if (stringAt(in, current, 2, list67)) { + if (stringAt(in, current + 1, 4, list68)) + MetaphAdd(primary, 'S'); + else + MetaphAdd(primary, 'X'); + current += 2; + break; + } + if (stringAt(in, current, 3, list69) || stringAt(in, current, 4, list70)) { + MetaphAdd(primary, 'S'); + current += 3; + break; + } + if (((current == 0) && stringAt(in, current + 1, 1, list71)) || stringAt(in, current + 1, 1, list72)) { + MetaphAdd(primary, 'S'); + if (stringAt(in, current + 1, 1, list73)) + current += 2; + else + current += 1; + break; + } + if (stringAt(in, current, 2, list74)) { + if (in.charAt(current + 2) == 'H') + if (stringAt(in, current + 3, 2, list75)) { + if (stringAt(in, current + 3, 2, list76)) { + MetaphAdd(primary, "X"); + } else { + MetaphAdd(primary, "SK"); + } + current += 3; + break; + } else { + MetaphAdd(primary, 'X'); + current += 3; + break; + } + if (stringAt(in, current + 2, 1, list77)) { + MetaphAdd(primary, 'S'); + current += 3; + break; + } + MetaphAdd(primary, "SK"); + current += 3; + break; + } + if ((current == last) && stringAt(in, current - 2, 2, list78)) { + //MetaphAdd(primary, ""); + } else + MetaphAdd(primary, 'S'); + if (stringAt(in, current + 1, 1, list79)) + current += 2; + else + current += 1; + break; + case 'T': + if (stringAt(in, current, 4, list80)) { + MetaphAdd(primary, 'X'); + current += 3; + break; + } + if (stringAt(in, current, 3, list81)) { + MetaphAdd(primary, 'X'); + current += 3; + break; + } + if (stringAt(in, current, 2, list82) || stringAt(in, current, 3, list83)) { + if (stringAt(in, (current + 2), 2, list84) || stringAt(in, 0, 4, list85) || stringAt(in, 0, 3, list86)) { + MetaphAdd(primary, 'T'); + } else { + MetaphAdd(primary, '0'); + } + current += 2; + break; + } + if (stringAt(in, current + 1, 1, list87)) { + current += 2; + } else + current += 1; + MetaphAdd(primary, 'T'); + break; + case 'V': + if (in.charAt(current + 1) == 'V') + current += 2; + else + current += 1; + MetaphAdd(primary, 'F'); + break; + case 'W': + if (stringAt(in, current, 2, list88)) { + MetaphAdd(primary, 'R'); + current += 2; + break; + } + if ((current == 0) && (isVowel(in, current + 1, length) || stringAt(in, current, 2, list89))) { + MetaphAdd(primary, 'A'); + } + if (((current == last) && isVowel(in, current - 1, length)) || stringAt(in, current - 1, 5, list90) || stringAt(in, 0, 3, list91)) { + MetaphAdd(primary, 'F'); + current += 1; + break; + } + if (stringAt(in, current, 4, list92)) { + MetaphAdd(primary, "TS"); + current += 4; + break; + } + current += 1; + break; + case 'X': + if (!((current == last) && (stringAt(in, current - 3, 3, list93) || stringAt(in, current - 2, 2, list94)))) + MetaphAdd(primary, "KS"); + if (stringAt(in, current + 1, 1, list95)) + current += 2; + else + current += 1; + break; + case 'Z': + if (in.charAt(current + 1) == 'H') { + MetaphAdd(primary, 'J'); + current += 2; + break; + } else { + MetaphAdd(primary, 'S'); + } + if (in.charAt(current + 1) == 'Z') + current += 2; + else + current += 1; + break; + default: + current += 1; + } + } + return primary.toString(); + } + + /** + * @see com.swabunga.spell.engine.Transformator#getReplaceList() + */ + public char[] getReplaceList() { + return replaceList; + } +} + + + diff --git a/src/com/swabunga/spell/engine/EditDistance.java b/src/com/swabunga/spell/engine/EditDistance.java new file mode 100644 index 0000000..34c64cf --- /dev/null +++ b/src/com/swabunga/spell/engine/EditDistance.java @@ -0,0 +1,253 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.engine; + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +/** + * This class is based on Levenshtein Distance algorithms, and it calculates how similar two words are. + * If the words are identical, then the distance is 0. The more that the words have in common, the lower the distance value. + * The distance value is based on how many operations it takes to get from one word to the other. Possible operations are + * swapping characters, adding a character, deleting a character, and substituting a character. + * The resulting distance is the sum of these operations weighted by their cost, which can be set in the Configuration object. + * When there are multiple ways to convert one word into the other, the lowest cost distance is returned. + *
+ * Another way to think about this: what are the cheapest operations that would have to be done on the "original" word to end up + * with the "similar" word? Each operation has a cost, and these are added up to get the distance. + *
+ * + * @see com.swabunga.spell.engine.Configuration#COST_REMOVE_CHAR + * @see com.swabunga.spell.engine.Configuration#COST_INSERT_CHAR + * @see com.swabunga.spell.engine.Configuration#COST_SUBST_CHARS + * @see com.swabunga.spell.engine.Configuration#COST_SWAP_CHARS + * + */ + +public class EditDistance { + + /** + * Fetches the spell engine configuration properties. + */ + public static Configuration config = Configuration.getConfiguration(); + + /** + * get the weights for each possible operation + */ + static final int costOfDeletingSourceCharacter = config.getInteger(Configuration.COST_REMOVE_CHAR); + static final int costOfInsertingSourceCharacter = config.getInteger(Configuration.COST_INSERT_CHAR); + static final int costOfSubstitutingLetters = config.getInteger(Configuration.COST_SUBST_CHARS); + static final int costOfSwappingLetters = config.getInteger(Configuration.COST_SWAP_CHARS); + static final int costOfChangingCase = config.getInteger(Configuration.COST_CHANGE_CASE); + + /** + * Evaluates the distance between two words. + * + * @param word One word to evaluates + * @param similar The other word to evaluates + * @return a number representing how easy or complex it is to transform on + * word into a similar one. + */ + public static final int getDistance(String word, String similar) { + return getDistance(word,similar,null); + } + + /** + * Evaluates the distance between two words. + * + * @param word One word to evaluates + * @param similar The other word to evaluates + * @return a number representing how easy or complex it is to transform on + * word into a similar one. + */ + public static final int getDistance(String word, String similar, int[][] matrix) { + /* JMH Again, there is no need to have a global class matrix variable + * in this class. I have removed it and made the getDistance static final + * DMV: I refactored this method to make it more efficient, more readable, and simpler. + * I also fixed a bug with how the distance was being calculated. You could get wrong + * distances if you compared ("abc" to "ab") depending on what you had setup your + * COST_REMOVE_CHAR and EDIT_INSERTION_COST values to - that is now fixed. + * WRS: I added a distance for case comparison, so a misspelling of "i" would be closer to "I" than + * to "a". + */ + + //Allocate memory outside of the loops. + int i; + int j; + int costOfSubst; + int costOfSwap; + int costOfDelete; + int costOfInsertion; + int costOfCaseChange; + + boolean isSwap; + char sourceChar = 0; + char otherChar = 0; + + int a_size = word.length() + 1; + int b_size = similar.length() + 1; + + + //Only allocate new memory if we need a bigger matrix. + if (matrix == null || matrix.length < a_size || matrix[0].length < b_size) + matrix = new int[a_size][b_size]; + + matrix[0][0] = 0; + + for (i = 1; i != a_size; ++i) + matrix[i][0] = matrix[i - 1][0] + costOfInsertingSourceCharacter; //initialize the first column + + for (j = 1; j != b_size; ++j) + matrix[0][j] = matrix[0][j - 1] + costOfDeletingSourceCharacter; //initalize the first row + + for (i = 1; i != a_size; ++i) { + sourceChar = word.charAt(i-1); + for (j = 1; j != b_size; ++j) { + + otherChar = similar.charAt(j-1); + if (sourceChar == otherChar) { + matrix[i][j] = matrix[i - 1][j - 1]; //no change required, so just carry the current cost up + continue; + } + + costOfSubst = costOfSubstitutingLetters + matrix[i - 1][j - 1]; + //if needed, add up the cost of doing a swap + costOfSwap = Integer.MAX_VALUE; + + isSwap = (i != 1) && (j != 1) && sourceChar == similar.charAt(j - 2) && word.charAt(i - 2) == otherChar; + if (isSwap) + costOfSwap = costOfSwappingLetters + matrix[i - 2][j - 2]; + + costOfDelete = costOfDeletingSourceCharacter + matrix[i][j - 1]; + costOfInsertion = costOfInsertingSourceCharacter + matrix[i - 1][j]; + + costOfCaseChange = Integer.MAX_VALUE; + + if (equalIgnoreCase(sourceChar, otherChar)) + costOfCaseChange = costOfChangingCase + matrix[i - 1][j - 1]; + + matrix[i][j] = minimum(costOfSubst, costOfSwap, costOfDelete, costOfInsertion, costOfCaseChange); + } + } + + return matrix[a_size - 1][b_size - 1]; + } + + /** + * checks to see if the two charactors are equal ignoring case. + * @param ch1 + * @param ch2 + * @return boolean + */ + private static boolean equalIgnoreCase(char ch1, char ch2) { + if (ch1 == ch2) + { + return true; + } + else + { + return (Character.toLowerCase(ch1) == Character.toLowerCase(ch2)); + } + } + + /** + * For debugging, this creates a string that represents the matrix. To read the matrix, look at any square. That is the cost to get from + * the partial letters along the top to the partial letters along the side. + * @param src - the source string that the matrix columns are based on + * @param dest - the dest string that the matrix rows are based on + * @param matrix - a two dimensional array of costs (distances) + * @return String + */ + @SuppressWarnings("unused") +static private String dumpMatrix(String src, String dest, int matrix[][]) { + StringBuffer s = new StringBuffer(""); + + int cols = matrix.length -1; + int rows = matrix[0].length -1; + + for (int i = 0; i < cols + 1; i++) { + for (int j = 0; j < rows + 1; j++) { + if (i == 0 && j == 0) { + s.append("\n "); + continue; + + } + if (i == 0) { + s.append("| "); + s.append(dest.charAt(j - 1)); + continue; + } + if (j == 0) { + s.append(src.charAt(i - 1)); + continue; + } + String num = Integer.toString(matrix[i - 1][j - 1]); + int padding = 4 - num.length(); + s.append("|"); + for (int k = 0; k < padding; k++) + s.append(' '); + s.append(num); + } + s.append('\n'); + } + return s.toString(); + + } + + + static private int minimum(int a, int b, int c, int d, int e) { + int mi = a; + if (b < mi) + mi = b; + if (c < mi) + mi = c; + if (d < mi) + mi = d; + if (e < mi) + mi = e; + + return mi; + } + + /** + * For testing edit distances + * @param args an array of two strings we want to evaluate their distances. + * @throws java.lang.Exception when problems occurs during reading args. + */ + public static void main(String[] args) throws Exception { + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + int[][] matrix = new int[0][0]; + while (true) { + + String input1 = stdin.readLine(); + if (input1 == null || input1.length() == 0) + break; + + String input2 = stdin.readLine(); + if (input2 == null || input2.length() == 0) + break; + + System.out.println(EditDistance.getDistance(input1, input2,matrix)); + } + System.out.println("done"); + } +} + + diff --git a/src/com/swabunga/spell/engine/GenericSpellDictionary.java b/src/com/swabunga/spell/engine/GenericSpellDictionary.java new file mode 100644 index 0000000..2238bde --- /dev/null +++ b/src/com/swabunga/spell/engine/GenericSpellDictionary.java @@ -0,0 +1,195 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.engine; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Vector; + +/** + * The SpellDictionary class holds the instance of the dictionary. + *

+ * This class is thread safe. Derived classes should ensure that this preserved. + *

+ *

+ * There are many open source dictionary files. For just a few see: + * http://wordlist.sourceforge.net/ + *

+ *

+ * This dictionary class reads words one per line. Make sure that your word list + * is formatted in this way (most are). + *

+ */ +public class GenericSpellDictionary extends SpellDictionaryASpell { + +//tech_monkey: the alphabet / replace list stuff has been moved into the Transformator classes, +//since they are so closely tied to how the phonetic transformations are done. +// /** +// * This replace list is used if no phonetic file is supplied or it doesn't +// * contain the alphabet. +// */ +// protected static final char[] englishAlphabet = + + + /** A field indicating the initial hash map capacity (16KB) for the main + * dictionary hash map. Interested to see what the performance of a + * smaller initial capacity is like. + */ + private final static int INITIAL_CAPACITY = 16 * 1024; + + /** + * The hashmap that contains the word dictionary. The map is hashed on the doublemeta + * code. The map entry contains a LinkedList of words that have the same double meta code. + */ + @SuppressWarnings("unchecked") +protected HashMap mainDictionary = new HashMap(INITIAL_CAPACITY); + + /** Holds the dictionary file for appending*/ + private File dictFile = null; + + + /** + * Dictionary constructor that uses the DoubleMeta class with the + * English alphabet. + * @param wordList The file containing dictionary as a words list. + * @throws java.io.FileNotFoundException when the words list file could not + * be located on the system. + * @throws java.io.IOException when problems occurs while reading the words + * list file + */ + public GenericSpellDictionary(File wordList) throws FileNotFoundException, IOException { + this(wordList, (File) null); + } + + /** + * Dictionary constructor that uses an aspell phonetic file to + * build the transformation table. + * If phonetic is null, then DoubleMeta is used with the English alphabet + * @param wordList The file containing dictionary as a words list. + * @param phonetic The file containing the phonetic transformation + * information. + * @throws java.io.FileNotFoundException when the words list or phonetic + * file could not be located on the system + * @throws java.io.IOException when problems occurs while reading the + * words list or phonetic file + */ + public GenericSpellDictionary(File wordList, File phonetic) throws FileNotFoundException, IOException { + + super(phonetic); + dictFile = wordList; + createDictionary(new BufferedReader(new FileReader(wordList))); + } + + + /** + * Add a word permanently to the dictionary (and the dictionary file). + *

This needs to be made thread safe (synchronized)

+ * @param word The word to add to the dictionary + */ + public void addWord(String word) { + putWord(word); + if (dictFile == null) + return; + try { + FileWriter w = new FileWriter(dictFile.toString(), true); + // Open with append. + w.write(word); + w.write("\n"); + w.close(); + } catch (IOException ex) { + System.out.println("Error writing to dictionary file"); + } + } + + /** + * Constructs the dictionary from a word list file. + *

+ * Each word in the reader should be on a separate line. + *

+ * This is a very slow function. On my machine it takes quite a while to + * load the data in. I suspect that we could speed this up quite allot. + */ + protected void createDictionary(BufferedReader in) throws IOException { + String line = ""; + while (line != null) { + line = in.readLine(); + if (line != null) { + line = new String(line.toCharArray()); + putWord(line); + } + } + } + + /** + * Allocates a word in the dictionary + */ + @SuppressWarnings("unchecked") +protected void putWord(String word) { + String code = getCode(word); + LinkedList list = (LinkedList) mainDictionary.get(code); + if (list != null) { + list.add(word); + } else { + list = new LinkedList(); + list.add(word); + mainDictionary.put(code, list); + } + } + + /** + * Returns a list of strings (words) for the code. + * @param code The phonetic code we want to find words for + * @return the list of words having the same phonetic code + */ + @SuppressWarnings("unchecked") +@Override +public List getWords(String code) { + //Check the main dictionary. + List mainDictResult = (List) mainDictionary.get(code); + if (mainDictResult == null) + return new Vector(); + return mainDictResult; + } + + /** + * Returns true if the word is correctly spelled against the current word list. + * @param word The word to checked in the dictionary + * @return indication if the word is in the dictionary + */ + @SuppressWarnings("unchecked") +@Override +public boolean isCorrect(String word) { + List possible = getWords(getCode(word)); + if (possible.contains(word)) + return true; + //JMH should we always try the lowercase version. If I dont then capitalised + //words are always returned as incorrect. + else if (possible.contains(word.toLowerCase())) + return true; + return false; + } +} diff --git a/src/com/swabunga/spell/engine/GenericTransformator.java b/src/com/swabunga/spell/engine/GenericTransformator.java new file mode 100644 index 0000000..5458ba1 --- /dev/null +++ b/src/com/swabunga/spell/engine/GenericTransformator.java @@ -0,0 +1,447 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.engine; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.HashMap; +import java.util.Vector; + +import com.swabunga.util.StringUtility; + +/** + * A Generic implementation of a transformator takes an + * + * aspell phonetics file and constructs some sort of transformation + * table using the inner class TransformationRule. + *

+ * Basically, each transformation rule represent a line in the phonetic file. + * One line contains two groups of characters separated by white space(s). + * The first group is the match expression. + * The match expression describe letters to associate with a syllable. + * The second group is the replacement expression giving the phonetic + * equivalent of the match expression. + * + * @see SpellDictionaryASpell SpellDictionaryASpell for information on getting + * phonetic files for aspell. + * + * @author Robert Gustavsson (robert@lindesign.se) + */ +public class GenericTransformator implements Transformator { + + + /** + * This replace list is used if no phonetic file is supplied or it doesn't + * contain the alphabet. + */ + private static final char[] defaultEnglishAlphabet = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; + + /** + * The alphabet start marker. + * @see GenericTransformator#KEYWORD_ALPHBET KEYWORD_ALPHBET + */ + public static final char ALPHABET_START = '['; + /** + * The alphabet end marker. + * @see GenericTransformator#KEYWORD_ALPHBET KEYWORD_ALPHBET + */ + public static final char ALPHABET_END = ']'; + /** + * Phonetic file keyword indicating that a different alphabet is used + * for this language. The keyword must be followed an + * {@link GenericTransformator#ALPHABET_START ALPHABET_START} marker, + * a list of characters defining the alphabet and a + * {@link GenericTransformator#ALPHABET_END ALPHABET_END} marker. + */ + public static final String KEYWORD_ALPHBET = "alphabet"; + /** + * Phonetic file lines starting with the keywords are skipped. + * The key words are: version, followup, collapse_result. + * Comments, starting with '#', are also skipped to the end of line. + */ + public static final String[] IGNORED_KEYWORDS = {"version", "followup", "collapse_result"}; + + /** + * Start a group of characters which can be appended to the match expression + * of the phonetic file. + */ + public static final char STARTMULTI = '('; + /** + * End a group of characters which can be appended to the match expression + * of the phonetic file. + */ + public static final char ENDMULTI = ')'; + /** + * During phonetic transformation of a word each numeric character is + * replaced by this DIGITCODE. + */ + public static final String DIGITCODE = "0"; + /** + * Phonetic file character code indicating that the replace expression + * is empty. + */ + public static final String REPLACEVOID = "_"; + + private Object[] ruleArray = null; + private char[] alphabetString = defaultEnglishAlphabet; + + /** + * Construct a transformation table from the phonetic file + * @param phonetic the phonetic file as specified in aspell + * @throws java.io.IOException indicates a problem while reading + * the phonetic file + */ + public GenericTransformator(File phonetic) throws IOException { + buildRules(new BufferedReader(new FileReader(phonetic))); + alphabetString = washAlphabetIntoReplaceList(getReplaceList()); + + } + + /** + * Construct a transformation table from the phonetic file + * @param phonetic the phonetic file as specified in aspell + * @param encoding the character set required + * @throws java.io.IOException indicates a problem while reading + * the phonetic file + */ + public GenericTransformator(File phonetic, String encoding) throws IOException { + buildRules(new BufferedReader(new InputStreamReader(new FileInputStream(phonetic), encoding))); + alphabetString = washAlphabetIntoReplaceList(getReplaceList()); + } + + /** + * Construct a transformation table from the phonetic file + * @param phonetic the phonetic file as specified in aspell. The file is + * supplied as a reader. + * @throws java.io.IOException indicates a problem while reading + * the phonetic information + */ + public GenericTransformator(Reader phonetic) throws IOException { + buildRules(new BufferedReader(phonetic)); + alphabetString = washAlphabetIntoReplaceList(getReplaceList()); + } + + /** + * Goes through an alphabet and makes sure that only one of those letters + * that are coded equally will be in the replace list. + * In other words, it removes any letters in the alphabet + * that are redundant phonetically. + * + * This is done to improve speed in the getSuggestion method. + * + * @param alphabet The complete alphabet to wash. + * @return The washed alphabet to be used as replace list. + */ + @SuppressWarnings("unchecked") +private char[] washAlphabetIntoReplaceList(char[] alphabet) { + + HashMap letters = new HashMap(alphabet.length); + + for (char element : alphabet) { + String tmp = String.valueOf(element); + String code = transform(tmp); + if (!letters.containsKey(code)) { + letters.put(code, new Character(element)); + } + } + + Object[] tmpCharacters = letters.values().toArray(); + char[] washedArray = new char[tmpCharacters.length]; + + for (int i = 0; i < tmpCharacters.length; i++) { + washedArray[i] = ((Character) tmpCharacters[i]).charValue(); + } + + return washedArray; + } + + + /** + * Takes out all single character replacements and put them in a char array. + * This array can later be used for adding or changing letters in getSuggestion(). + * @return char[] An array of chars with replacements characters + */ + @SuppressWarnings("unchecked") +public char[] getCodeReplaceList() { + char[] replacements; + TransformationRule rule; + Vector tmp = new Vector(); + + if (ruleArray == null) + return null; + for (Object element : ruleArray) { + rule = (TransformationRule) element; + if (rule.getReplaceExp().length() == 1) + tmp.addElement(rule.getReplaceExp()); + } + replacements = new char[tmp.size()]; + for (int i = 0; i < tmp.size(); i++) { + replacements[i] = ((String) tmp.elementAt(i)).charAt(0); + } + return replacements; + } + + /** + * Builds up an char array with the chars in the alphabet of the language as it was read from the + * alphabet tag in the phonetic file. + * @return char[] An array of chars representing the alphabet or null if no alphabet was available. + */ + public char[] getReplaceList() { + return alphabetString; + } + + /** + * Builds the phonetic code of the word. + * @param word the word to transform + * @return the phonetic transformation of the word + */ + public String transform(String word) { + + if (ruleArray == null) + return null; + + TransformationRule rule; + StringBuffer str = new StringBuffer(word.toUpperCase()); + int strLength = str.length(); + int startPos = 0, add = 1; + + while (startPos < strLength) { + + add = 1; + if (Character.isDigit(str.charAt(startPos))) { + StringUtility.replace(str, startPos, startPos + DIGITCODE.length(), DIGITCODE); + startPos += add; + continue; + } + + for (Object element : ruleArray) { + //System.out.println("Testing rule#:"+i); + rule = (TransformationRule) element; + if (rule.startsWithExp() && startPos > 0) + continue; + if (startPos + rule.lengthOfMatch() > strLength) { + continue; + } + if (rule.isMatching(str, startPos)) { + String replaceExp = rule.getReplaceExp(); + + add = replaceExp.length(); + StringUtility.replace(str, startPos, startPos + rule.getTakeOut(), replaceExp); + strLength -= rule.getTakeOut(); + strLength += add; + //System.out.println("Replacing with rule#:"+i+" add="+add); + break; + } + } + startPos += add; + } + //System.out.println(word); + //System.out.println(str.toString()); + return str.toString(); + } + + // Used to build up the transformastion table. + @SuppressWarnings("unchecked") +private void buildRules(BufferedReader in) throws IOException { + String read = null; + Vector ruleList = new Vector(); + while ((read = in.readLine()) != null) { + buildRule(realTrimmer(read), ruleList); + } + ruleArray = new TransformationRule[ruleList.size()]; + ruleList.copyInto(ruleArray); + } + + // Here is where the real work of reading the phonetics file is done. + @SuppressWarnings("unchecked") +private void buildRule(String str, Vector ruleList) { + if (str.length() < 1) + return; + for (String element : IGNORED_KEYWORDS) { + if (str.startsWith(element)) + return; + } + + // A different alphabet is used for this language, will be read into + // the alphabetString variable. + if (str.startsWith(KEYWORD_ALPHBET)) { + int start = str.indexOf(ALPHABET_START); + int end = str.lastIndexOf(ALPHABET_END); + if (end != -1 && start != -1) { + alphabetString = str.substring(++start, end).toCharArray(); + } + return; + } + + // str contains two groups of characters separated by white space(s). + // The fisrt group is the "match expression". The second group is the + // "replacement expression" giving the phonetic equivalent of the + // "match expression". + TransformationRule rule = null; + StringBuffer matchExp = new StringBuffer(); + StringBuffer replaceExp = new StringBuffer(); + boolean start = false, + end = false; + int takeOutPart = 0, + matchLength = 0; + boolean match = true, + inMulti = false; + for (int i = 0; i < str.length(); i++) { + if (Character.isWhitespace(str.charAt(i))) { + match = false; + } else { + if (match) { + if (!isReservedChar(str.charAt(i))) { + matchExp.append(str.charAt(i)); + if (!inMulti) { + takeOutPart++; + matchLength++; + } + if (str.charAt(i) == STARTMULTI || str.charAt(i) == ENDMULTI) + inMulti = !inMulti; + } + if (str.charAt(i) == '-') + takeOutPart--; + if (str.charAt(i) == '^') + start = true; + if (str.charAt(i) == '$') + end = true; + } else { + replaceExp.append(str.charAt(i)); + } + } + } + if (replaceExp.toString().equals(REPLACEVOID)) { + replaceExp = new StringBuffer(""); + //System.out.println("Changing _ to \"\" for "+matchExp.toString()); + } + rule = new TransformationRule(matchExp.toString(), replaceExp.toString(), takeOutPart, matchLength, start, end); + //System.out.println(rule.toString()); + ruleList.addElement(rule); + } + + // Chars with special meaning to aspell. Not everyone is implemented here. + private boolean isReservedChar(char ch) { + if (ch == '<' || ch == '>' || ch == '^' || ch == '$' || ch == '-' || Character.isDigit(ch)) + return true; + return false; + } + + // Trims off everything we don't care about. + private String realTrimmer(String row) { + int pos = row.indexOf('#'); + if (pos != -1) { + row = row.substring(0, pos); + } + return row.trim(); + } + + // Inner Classes + /* + * Holds the match string and the replace string and all the rule attributes. + * Is responsible for indicating matches. + */ + private class TransformationRule { + + private final String replace; + private final char[] match; + // takeOut=number of chars to replace; + // matchLength=length of matching string counting multies as one. + private final int takeOut, matchLength; + private final boolean start, end; + + // Construktor + public TransformationRule(String match, String replace, int takeout, int matchLength, boolean start, boolean end) { + this.match = match.toCharArray(); + this.replace = replace; + this.takeOut = takeout; + this.matchLength = matchLength; + this.start = start; + this.end = end; + } + + /* + * Returns true if word from pos and forward matches the match string. + * Precondition: wordPos+matchLengthconfiguration.properties file. + * + * @author aim4min + */ +public class PropertyConfiguration extends Configuration { + + /** + * The persistent set of properties supported by the spell engine + */ + public Properties prop; + /** + * The name of the file containing spell engine properties + */ + public URL filename; + + /** + * Constructs and loads spell engine properties configuration. + */ + public PropertyConfiguration() { + prop = new Properties(); + try { + filename = getClass().getClassLoader().getResource("com/swabunga/spell/engine/configuration.properties"); + InputStream in = filename.openStream(); + prop.load(in); + } catch (Exception e) { + System.out.println("Could not load Properties file :\n" + e); + } + } + + /** + * @see com.swabunga.spell.engine.Configuration#getBoolean(String) + */ + public boolean getBoolean(String key) { + return new Boolean(prop.getProperty(key)).booleanValue(); + } + + /** + * @see com.swabunga.spell.engine.Configuration#getInteger(String) + */ + public int getInteger(String key) { + return new Integer(prop.getProperty(key)).intValue(); + } + + /** + * @see com.swabunga.spell.engine.Configuration#setBoolean(String, boolean) + */ + public void setBoolean(String key, boolean value) { + String string = null; + if (value) + string = "true"; + else + string = "false"; + + prop.setProperty(key, string); + save(); + } + + /** + * @see com.swabunga.spell.engine.Configuration#setInteger(String, int) + */ + public void setInteger(String key, int value) { + prop.setProperty(key, Integer.toString(value)); + save(); + } + + /** + * Writes the property list (key and element pairs) in the + * PropertyConfiguration file. + */ + public void save() { + try { + File file = new File(filename.getFile()); + FileOutputStream fout = new FileOutputStream(file); + prop.store(fout, "HEADER"); + } catch (FileNotFoundException e) { + } catch (IOException e) { + } + } + +} diff --git a/src/com/swabunga/spell/engine/SpellDictionary.java b/src/com/swabunga/spell/engine/SpellDictionary.java new file mode 100644 index 0000000..58577f4 --- /dev/null +++ b/src/com/swabunga/spell/engine/SpellDictionary.java @@ -0,0 +1,92 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.engine; + +import java.util.List; + +/** + * An interface for all dictionary implementations. It defines the most basic + * operations on a dictionary: adding words, checking if a word is correct, and getting a list + * of suggestions for misspelled words. + */ +public interface SpellDictionary { + + /** + * Add a word permanently to the dictionary. + * @param word The word to add to the dictionary + */ + public void addWord(String word); + + /** + * Evaluates if the word is correctly spelled against the dictionary. + * @param word The word to verify if it's spelling is OK. + * @return Indicates if the word is present in the dictionary. + */ + public boolean isCorrect(String word); + + /** + * Returns a list of Word objects that are the suggestions to any word. + * If the word is correctly spelled, then this method + * could return just that one word, or it could still return a list + * of words with similar spellings. + *
+ * Each suggested word has a score, which is an integer + * that represents how different the suggested word is from the sourceWord. + * If the words are the exactly the same, then the score is 0. + * You can get the dictionary to only return the most similar words by setting + * an appropriately low threshold value. + * If you set the threshold value too low, you may get no suggestions for a given word. + *

+ * This method is only needed to provide backward compatibility. + * @see #getSuggestions(String, int, int[][]) + * + * @param sourceWord the string that we want to get a list of spelling suggestions for + * @param scoreThreshold Any words that have score less than this number are returned. + * @return List a List of suggested words + * @see com.swabunga.spell.engine.Word + * + */ + @SuppressWarnings("unchecked") +public List getSuggestions(String sourceWord, int scoreThreshold); + + /** + * Returns a list of Word objects that are the suggestions to any word. + * If the word is correctly spelled, then this method + * could return just that one word, or it could still return a list + * of words with similar spellings. + *
+ * Each suggested word has a score, which is an integer + * that represents how different the suggested word is from the sourceWord. + * If the words are the exactly the same, then the score is 0. + * You can get the dictionary to only return the most similar words by setting + * an appropriately low threshold value. + * If you set the threshold value too low, you may get no suggestions for a given word. + *

+ * @param sourceWord the string that we want to get a list of spelling suggestions for + * @param scoreThreshold Any words that have score less than this number are returned. + * @param Two dimensional int array used to calculate edit distance. Allocating + * this memory outside of the function will greatly improve efficiency. + * @return List a List of suggested words + * @see com.swabunga.spell.engine.Word + */ + @SuppressWarnings("unchecked") +public List getSuggestions(String sourceWord, int scoreThreshold , int[][] matrix); + +} diff --git a/src/com/swabunga/spell/engine/SpellDictionaryASpell.java b/src/com/swabunga/spell/engine/SpellDictionaryASpell.java new file mode 100644 index 0000000..bac83f0 --- /dev/null +++ b/src/com/swabunga/spell/engine/SpellDictionaryASpell.java @@ -0,0 +1,360 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +/* Created by bgalbs on Jan 30, 2003 at 11:45:25 PM */ +package com.swabunga.spell.engine; + +import java.io.File; +import java.io.IOException; +import java.io.Reader; +import java.security.InvalidParameterException; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Vector; + +/** + * Container for various methods that any SpellDictionary will use. + * This class is based on the original Jazzy aspell port. + *

+ * Derived classes will need words list files as spell checking reference. + * Words list file is a dictionary with one word per line. There are many + * open source dictionary files, see: + * + * http://wordlist.sourceforge.net/ + *

+ * You can choose words lists form aspell + * many differents languages dictionaries. To grab some, install + * aspell and the dictionaries you require. Then run aspell + * specifying the name of the dictionary and the words list file to dump it + * into, for example: + *

+ * aspell --master=fr-40 dump master > fr-40.txt
+ * 
+ * Note: the number following the language is the size indicator. A bigger + * number gives a more extensive language coverage. Size 40 is more than + * adequate for many usages. + *

+ * For some languages, Aspell can also supply you with the phonetic file. + * On Windows, go into aspell data directory and copy the + * phonetic file corresponding to your language, for example the + * fr_phonet.dat for the fr language. The phonetic + * file should be in directory /usr/share/aspell on Unix. + * + * @see GenericTransformator GenericTransformator for information on + * phonetic files. + */ +public abstract class SpellDictionaryASpell implements SpellDictionary { + + + /** The reference to a Transformator, used to transform a word into it's phonetic code. */ + protected Transformator tf; + + /** + * Constructs a new SpellDictionaryASpell + * @param phonetic The file to use for phonetic transformation of the + * words list. If phonetic is null, the the transformation + * uses {@link DoubleMeta} transformation. + * @throws java.io.IOException indicates problems reading the phonetic + * information + */ + public SpellDictionaryASpell(File phonetic) throws IOException { + if (phonetic == null) + tf = new DoubleMeta(); + else + tf = new GenericTransformator(phonetic); + } + + /** + * Constructs a new SpellDictionaryASpell + * @param phonetic The file to use for phonetic transformation of the + * words list. If phonetic is null, the the transformation + * uses {@link DoubleMeta} transformation. + * @param encoding Uses the character set encoding specified + * @throws java.io.IOException indicates problems reading the phonetic + * information + */ + public SpellDictionaryASpell(File phonetic, String encoding) throws IOException { + if (phonetic == null) + tf = new DoubleMeta(); + else + tf = new GenericTransformator(phonetic, encoding); + } + + /** + * Constructs a new SpellDictionaryASpell + * @param phonetic The Reader to use for phonetic transformation of the + * words list. If phonetic is null, the the transformation + * uses {@link DoubleMeta} transformation. + * @throws java.io.IOException indicates problems reading the phonetic + * information + */ + public SpellDictionaryASpell(Reader phonetic) throws IOException { + if (phonetic == null) + tf = new DoubleMeta(); + else + tf = new GenericTransformator(phonetic); + } + + /** + * Returns a list of Word objects that are the suggestions to an + * incorrect word. + *

+ * This method is only needed to provide backward compatibility. + * @see #getSuggestions(String, int, int[][]) + * @param word Suggestions for given misspelt word + * @param threshold The lower boundary of similarity to misspelt word + * @return Vector a List of suggestions + */ + @SuppressWarnings("unchecked") +public List getSuggestions(String word, int threshold) { + + return getSuggestions(word,threshold,null); + + } + + /** + * Returns a list of Word objects that are the suggestions to an + * incorrect word. + *

+ * @param word Suggestions for given misspelt word + * @param threshold The lower boundary of similarity to misspelt word + * @param matrix Two dimensional int array used to calculate + * edit distance. Allocating this memory outside of the function will greatly improve efficiency. + * @return Vector a List of suggestions + */ + @SuppressWarnings("unchecked") +public List getSuggestions(String word, int threshold, int[][] matrix) { + + int i; + int j; + + if(matrix == null) + matrix = new int[0][0]; + + Hashtable nearmisscodes = new Hashtable(); + String code = getCode(word); + + // add all words that have the same phonetics + nearmisscodes.put(code, code); + Vector phoneticList = getWordsFromCode(word, nearmisscodes); + + // do some tranformations to pick up more results + //interchange + nearmisscodes = new Hashtable(); + char[] charArray = word.toCharArray(); + char a; + char b ; + + for (i = 0; i < word.length() - 1; i++) { + a = charArray[i]; + b = charArray[i + 1]; + charArray[i] = b; + charArray[i + 1] = a; + String s = getCode(new String(charArray)); + nearmisscodes.put(s, s); + charArray[i] = a; + charArray[i + 1] = b; + } + + char[] replacelist = tf.getReplaceList(); + + //change + charArray = word.toCharArray(); + char original; + for (i = 0; i < word.length(); i++) { + original = charArray[i]; + for (j = 0; j < replacelist.length; j++) { + charArray[i] = replacelist[j]; + String s = getCode(new String(charArray)); + nearmisscodes.put(s, s); + } + charArray[i] = original; + } + + //add + charArray = (word += " ").toCharArray(); + int iy = charArray.length - 1; + while (true) { + for (j = 0; j < replacelist.length; j++) { + charArray[iy] = replacelist[j]; + String s = getCode(new String(charArray)); + nearmisscodes.put(s, s); + } + if (iy == 0) + break; + charArray[iy] = charArray[iy - 1]; + --iy; + } + + //delete + word = word.trim(); + charArray = word.toCharArray(); + char[] charArray2 = new char[charArray.length - 1]; + for (int ix = 0; ix < charArray2.length; ix++) { + charArray2[ix] = charArray[ix]; + } + + a = charArray[charArray.length - 1]; + int ii = charArray2.length; + while (true) { + String s = getCode(new String(charArray)); + nearmisscodes.put(s, s); + if (ii == 0) + break; + b = a; + a = charArray2[ii - 1]; + charArray2[ii - 1] = b; + --ii; + } + + nearmisscodes.remove(code); //already accounted for in phoneticList + + Vector wordlist = getWordsFromCode(word, nearmisscodes); + + if (wordlist.size() == 0 && phoneticList.size() == 0) + addBestGuess(word, phoneticList, matrix); + + + // We sort a Vector at the end instead of maintaining a + // continously sorted TreeSet because everytime you add a collection + // to a treeset it has to be resorted. It's better to do this operation + // once at the end. + + Collections.sort(phoneticList, new Word()); //always sort phonetic matches along the top + Collections.sort(wordlist, new Word()); //the non-phonetic matches can be listed below + + phoneticList.addAll(wordlist); + return phoneticList; + } + + /** + * When we don't come up with any suggestions (probably because the threshold was too strict), + * then pick the best guesses from the those words that have the same phonetic code. + *

+ * This method is only needed to provide backward compatibility. + * @see addBestGuess(String word, Vector wordList, int[][] matrix) + * @param word - the word we are trying spell correct + * @param wordList - the linked list that will get the best guess + */ + @SuppressWarnings({ "unused", "unchecked" }) +private void addBestGuess(String word, Vector wordList) { + addBestGuess(word,wordList,null); + } + + /** + * When we don't come up with any suggestions (probably because the threshold was too strict), + * then pick the best guesses from the those words that have the same phonetic code. + * @param word - the word we are trying spell correct + * @param Two dimensional array of int used to calculate + * edit distance. Allocating this memory outside of the function will greatly improve efficiency. + * @param wordList - the linked list that will get the best guess + */ + @SuppressWarnings("unchecked") +private void addBestGuess(String word, Vector wordList, int[][] matrix) { + if(matrix == null) + matrix = new int[0][0]; + + if (wordList.size() != 0) + throw new InvalidParameterException("the wordList vector must be empty"); + + int bestScore = Integer.MAX_VALUE; + + String code = getCode(word); + List simwordlist = getWords(code); + + LinkedList candidates = new LinkedList(); + + for (Iterator j = simwordlist.iterator(); j.hasNext();) { + String similar = (String) j.next(); + int distance = EditDistance.getDistance(word, similar, matrix); + if (distance <= bestScore) { + bestScore = distance; + Word goodGuess = new Word(similar, distance); + candidates.add(goodGuess); + } + } + + //now, only pull out the guesses that had the best score + for (Iterator iter = candidates.iterator(); iter.hasNext();) { + Word candidate = (Word) iter.next(); + if (candidate.getCost() == bestScore) + wordList.add(candidate); + } + + } + + @SuppressWarnings("unchecked") +private Vector getWordsFromCode(String word, Hashtable codes) { + Configuration config = Configuration.getConfiguration(); + Vector result = new Vector(); + int[][] matrix = new int[0][0]; + final int configDistance = config.getInteger(Configuration.SPELL_THRESHOLD); + + for (Enumeration i = codes.keys(); i.hasMoreElements();) { + String code = (String) i.nextElement(); + + List simwordlist = getWords(code); + for (Iterator iter = simwordlist.iterator(); iter.hasNext();) { + String similar = (String) iter.next(); + int distance = EditDistance.getDistance(word, similar, matrix); + if (distance < configDistance) { + Word w = new Word(similar, distance); + result.addElement(w); + } + } + } + return result; + } + + /** + * Returns the phonetic code representing the word. + * @param word The word we want the phonetic code. + * @return The value of the phonetic code for the word. + */ + public String getCode(String word) { + return tf.transform(word); + } + + /** + * Returns a list of words that have the same phonetic code. + * @param phoneticCode The phonetic code common to the list of words + * @return A list of words having the same phonetic code + */ + @SuppressWarnings("unchecked") +protected abstract List getWords(String phoneticCode); + + /** + * Returns true if the word is correctly spelled against the current word list. + */ + @SuppressWarnings("unchecked") +public boolean isCorrect(String word) { + List possible = getWords(getCode(word)); + if (possible.contains(word)) + return true; + //JMH should we always try the lowercase version. If I dont then capitalised + //words are always returned as incorrect. + else if (possible.contains(word.toLowerCase())) + return true; + return false; + } +} diff --git a/src/com/swabunga/spell/engine/SpellDictionaryCachedDichoDisk.java b/src/com/swabunga/spell/engine/SpellDictionaryCachedDichoDisk.java new file mode 100644 index 0000000..0bd1430 --- /dev/null +++ b/src/com/swabunga/spell/engine/SpellDictionaryCachedDichoDisk.java @@ -0,0 +1 @@ +/* Jazzy - a Java library for Spell Checking Copyright (C) 2001 Mindaugas Idzelis Full text of license can be found in LICENSE.txt This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package com.swabunga.spell.engine; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.HashMap; import java.util.Iterator; import java.util.List; /** * Yet another SpellDictionary this one is based on Damien Guillaume's * Diskbased dictionary but adds a cache to try to improve abit on performance. * * @author Robert Gustavsson * @version 0.01 */ public class SpellDictionaryCachedDichoDisk extends SpellDictionaryDichoDisk { // Only used for testing to measure the effectiveness of the cache. static public int hits=0; static public int codes=0; public static final String JAZZY_DIR=".jazzy"; public static final String PRE_CACHE_FILE_EXT=".pre"; private static int MAX_CACHED=10000; @SuppressWarnings("unchecked") private final HashMap suggestionCache=new HashMap(MAX_CACHED); private String preCacheFileName; private String preCacheDir; /** * Dictionary Convienence Constructor. */ public SpellDictionaryCachedDichoDisk(File wordList) throws FileNotFoundException, IOException { super(wordList); loadPreCache(wordList); } /** * Dictionary Convienence Constructor. */ public SpellDictionaryCachedDichoDisk(File wordList, String encoding) throws FileNotFoundException, IOException { super(wordList, encoding); loadPreCache(wordList); } /** * Dictionary constructor that uses an aspell phonetic file to * build the transformation table. */ public SpellDictionaryCachedDichoDisk(File wordList, File phonetic) throws FileNotFoundException, IOException { super(wordList, phonetic); loadPreCache(wordList); } /** * Dictionary constructor that uses an aspell phonetic file to * build the transformation table. */ public SpellDictionaryCachedDichoDisk(File wordList, File phonetic, String encoding) throws FileNotFoundException, IOException { super(wordList, phonetic, encoding); loadPreCache(wordList); } /** * Add a word permanantly to the dictionary (and the dictionary file). * not implemented ! */ @Override public void addWord(String word) { System.err.println("error: addWord is not implemented for SpellDictionaryCachedDichoDisk"); } /** * Clears the cache. */ public void clearCache(){ suggestionCache.clear(); } /** * Returns a list of strings (words) for the code. */ @Override @SuppressWarnings("unchecked") public List getWords(String code) { List list; codes++; if(suggestionCache.containsKey(code)){ hits++; list=getCachedList(code); return list; } list=super.getWords(code); addToCache(code,list); return list; } /** * This method returns the cached suggestionlist and also moves the code to * the top of the codeRefQueue to indicate this code has resentlly been * referenced. */ @SuppressWarnings("unchecked") private List getCachedList(String code){ CacheObject obj=(CacheObject)suggestionCache.get(code); obj.setRefTime(); return obj.getSuggestionList(); } /** * Adds a code and it's suggestion list to the cache. */ @SuppressWarnings("unchecked") private void addToCache(String code, List l){ String c=null; String lowestCode=null; long lowestTime=Long.MAX_VALUE; Iterator it; CacheObject obj; if(suggestionCache.size()>=MAX_CACHED){ it=suggestionCache.keySet().iterator(); while(it.hasNext()){ c=(String)it.next(); obj=(CacheObject)suggestionCache.get(c); if(obj.getRefTime()==0){ lowestCode=c; break; } if(lowestTime>obj.getRefTime()){ lowestCode=c; lowestTime=obj.getRefTime(); } } suggestionCache.remove(lowestCode); } suggestionCache.put(code,new CacheObject(l)); } /** * Load the cache from file. The cach file has the same name as the * dico file with the .pre extension added. */ @SuppressWarnings("unchecked") private void loadPreCache(File dicoFile)throws IOException{ String code; List suggestions; long size, time; File preFile; ObjectInputStream in; preCacheDir=System.getProperty("user.home")+"/"+JAZZY_DIR; preCacheFileName=preCacheDir+"/"+dicoFile.getName()+PRE_CACHE_FILE_EXT; //System.out.println(preCacheFileName); preFile=new File(preCacheFileName); if(!preFile.exists()){ System.err.println("No precache file"); return; } //System.out.println("Precaching..."); in=new ObjectInputStream(new FileInputStream(preFile)); try{ size=in.readLong(); for(int i=0;iSpellDictionary that doesn't cache any words in memory. Avoids the huge + * footprint of SpellDictionaryHashMap at the cost of relatively minor latency. A future version + * of this class that implements some caching strategies might be a good idea in the future, if there's any + * demand for it. + * + * This implementation requires a special dictionary file, with "code*word" lines sorted by code. + * It's using a dichotomy algorithm to search for words in the dictionary + * + * @author Damien Guillaume + * @version 0.1 + */ +public class SpellDictionaryDichoDisk extends SpellDictionaryASpell { + + /** Holds the dictionary file for reading*/ + private RandomAccessFile dictFile = null; + + /** dictionary and phonetic file encoding */ + private String encoding = null; + + /** + * Dictionary convenience Constructor. + * @param wordList The file containing the words list for the dictionary + * @throws java.io.FileNotFoundException indicates problems locating the + * words list file on the system + * @throws java.io.IOException indicates problems reading the words list + * file + */ + public SpellDictionaryDichoDisk(File wordList) + throws FileNotFoundException, IOException { + super((File) null); + dictFile = new RandomAccessFile(wordList, "r"); + } + + /** + * Dictionary convenience Constructor. + * @param wordList The file containing the words list for the dictionary + * @param encoding Uses the character set encoding specified + * @throws java.io.FileNotFoundException indicates problems locating the + * words list file on the system + * @throws java.io.IOException indicates problems reading the words list + * file + */ + public SpellDictionaryDichoDisk(File wordList, String encoding) + throws FileNotFoundException, IOException { + super((File) null); + this.encoding = encoding; + dictFile = new RandomAccessFile(wordList, "r"); + } + + /** + * Dictionary constructor that uses an aspell phonetic file to + * build the transformation table. + * @param wordList The file containing the words list for the dictionary + * @param phonetic The file to use for phonetic transformation of the + * wordlist. + * @throws java.io.FileNotFoundException indicates problems locating the + * file on the system + * @throws java.io.IOException indicates problems reading the words list + * file + */ + public SpellDictionaryDichoDisk(File wordList, File phonetic) + throws FileNotFoundException, IOException { + super(phonetic); + dictFile = new RandomAccessFile(wordList, "r"); + } + + /** + * Dictionary constructor that uses an aspell phonetic file to + * build the transformation table. + * @param wordList The file containing the words list for the dictionary + * @param phonetic The file to use for phonetic transformation of the + * wordlist. + * @param encoding Uses the character set encoding specified + * @throws java.io.FileNotFoundException indicates problems locating the + * file on the system + * @throws java.io.IOException indicates problems reading the words list + * file + */ + public SpellDictionaryDichoDisk(File wordList, File phonetic, String encoding) + throws FileNotFoundException, IOException { + super(phonetic, encoding); + this.encoding = encoding; + dictFile = new RandomAccessFile(wordList, "r"); + } + + /** + * Add a word permanently to the dictionary (and the dictionary file). + * not implemented ! + * @param word The word to add. + */ + public void addWord(String word) { + System.err.println("error: addWord is not implemented for SpellDictionaryDichoDisk"); + } + + /** + * Search the dictionary file for the words corresponding to the code + * within positions p1 - p2 + */ + @SuppressWarnings("unchecked") +private LinkedList dichoFind(String code, long p1, long p2) throws IOException { + //System.out.println("dichoFind("+code+","+p1+","+p2+")"); + long pm = (p1 + p2) / 2; + dictFile.seek(pm); + String l; + if (encoding == null) + l = dictFile.readLine(); + else + l = dictReadLine(); + pm = dictFile.getFilePointer(); + if (encoding == null) + l = dictFile.readLine(); + else + l = dictReadLine(); + long pm2 = dictFile.getFilePointer(); + if (pm2 >= p2) + return(seqFind(code, p1, p2)); + int istar = l.indexOf('*'); + if (istar == -1) + throw new IOException("bad format: no * !"); + String testcode = l.substring(0, istar); + int comp = code.compareTo(testcode); + if (comp < 0) + return(dichoFind(code, p1, pm-1)); + else if (comp > 0) + return(dichoFind(code, pm2, p2)); + else { + LinkedList l1 = dichoFind(code, p1, pm-1); + LinkedList l2 = dichoFind(code, pm2, p2); + String word = l.substring(istar+1); + l1.add(word); + l1.addAll(l2); + return(l1); + } + } + + @SuppressWarnings("unchecked") +private LinkedList seqFind(String code, long p1, long p2) throws IOException { + //System.out.println("seqFind("+code+","+p1+","+p2+")"); + LinkedList list = new LinkedList(); + dictFile.seek(p1); + while (dictFile.getFilePointer() < p2) { + String l; + if (encoding == null) + l = dictFile.readLine(); + else + l = dictReadLine(); + int istar = l.indexOf('*'); + if (istar == -1) + throw new IOException("bad format: no * !"); + String testcode = l.substring(0, istar); + if (testcode.equals(code)) { + String word = l.substring(istar+1); + list.add(word); + } + } + return(list); + } + + /** + * Read a line of dictFile with a specific encoding + */ + private String dictReadLine() throws IOException { + int max = 255; + byte b=0; + byte[] buf = new byte[max]; + int i=0; + try { + for (; b != '\n' && b != '\r' && iSpellDictionary that doesn't cache any words in memory. Avoids the huge + * footprint of SpellDictionaryHashMap at the cost of relatively minor latency. A future version + * of this class that implements some caching strategies might be a good idea in the future, if there's any + * demand for it. + *

+ * This class makes use of the "classic" Java IO library (java.io). However, it could probably benefit from + * the new IO APIs (java.nio) and it is anticipated that a future version of this class, probably called + * SpellDictionaryDiskNIO will appear at some point. + * + * @author Ben Galbraith (ben@galbraiths.org) + * @version 0.1 + * @since 0.5 + */ +public class SpellDictionaryDisk extends SpellDictionaryASpell { + private final static String DIRECTORY_WORDS = "words"; + private final static String DIRECTORY_DB = "db"; + private final static String FILE_CONTENTS = "contents"; + private final static String FILE_DB = "words.db"; + private final static String FILE_INDEX = "words.idx"; + + /* maximum number of words an index entry can represent */ + private final static int INDEX_SIZE_MAX = 200; + + private final File base; + private final File words; + private final File db; + @SuppressWarnings("unchecked") +private Map index; + /** + * The flag indicating if the initial preparation or loading of the on + * disk dictionary is complete. + */ + protected boolean ready; + + /* used at time of creation of index to speed up determining the number of words per index entry */ + @SuppressWarnings("unchecked") +private List indexCodeCache = null; + + /** + * Construct a spell dictionary on disk. + * The spell dictionary is created from words list(s) contained in file(s). + * A words list file is a file with one word per line. Words list files are + * located in a base/words dictionary where base + * is the path to words dictionary. The on disk spell + * dictionary is created in base/db dictionary and contains + * files: + *

+ * The contents file has a list of + * filename, size indicating the name and length of each files + * in the base/words dictionary. If one of theses files was + * changed, added or deleted before the call to the constructor, the process + * of producing new or updated words.db and + * words.idx files is started again. + *

+ * The spellchecking process is then worked upon the words.db + * and words.idx files. + *

+ * + * NOTE: Do *not* create two instances of this class pointing to the same base unless + * you are sure that a new dictionary does not have to be created. In the future, some sort of + * external locking mechanism may be created that handles this scenario gracefully. + * + * @param base the base directory in which SpellDictionaryDisk can expect to find + * its necessary files. + * @param phonetic the phonetic file used by the spellchecker. + * @param block if a new word db needs to be created, there can be a considerable delay before + * the constructor returns. If block is true, this method will block while the db is created + * and return when done. If block is false, this method will create a thread to create the new + * dictionary and return immediately. + * @throws java.io.FileNotFoundException indicates problems locating the + * files on the system + * @throws java.io.IOException indicates problems reading the files + */ + public SpellDictionaryDisk(File base, File phonetic, boolean block) throws FileNotFoundException, IOException { + super(phonetic); + this.ready = false; + + this.base = base; + this.words = new File(base, DIRECTORY_WORDS); + this.db = new File(base, DIRECTORY_DB); + + if (!this.base.exists()) throw new FileNotFoundException("Couldn't find required path '" + this.base + "'"); + if (!this.words.exists()) throw new FileNotFoundException("Couldn't find required path '" + this.words + "'"); + if (!this.db.exists()) db.mkdirs(); + + if (newDictionaryFiles()) { + if (block) { + buildNewDictionaryDatabase(); + loadIndex(); + ready = true; + } else { + Thread t = new Thread() { + @Override + public void run() { + try { + buildNewDictionaryDatabase(); + loadIndex(); + ready = true; + } catch (Exception e) { + e.printStackTrace(); + } + } + }; + t.start(); + } + } else { + loadIndex(); + ready = true; + } + } + + /** + * Builds the file words database file and the contents file for the on + * disk dictionary. + */ + protected void buildNewDictionaryDatabase() throws FileNotFoundException, IOException { + /* combine all dictionary files into one sorted file */ + File sortedFile = buildSortedFile(); + + /* create the db for the sorted file */ + buildCodeDb(sortedFile); + sortedFile.delete(); + + /* build contents file */ + buildContentsFile(); + } + + /** + * Adds another word to the dictionary. This method is not yet implemented + * for this class. + * @param word The word to add. + */ + public void addWord(String word) { + throw new UnsupportedOperationException("addWord not yet implemented (sorry)"); + } + + /** + * Returns a list of words that have the same phonetic code. + * @param code The phonetic code common to the list of words + * @return A list of words having the same phonetic code + */ + @Override +@SuppressWarnings("unchecked") +public List getWords(String code) { + Vector words = new Vector(); + + int[] posLen = getStartPosAndLen(code); + if (posLen != null) { + try { + InputStream input = new FileInputStream(new File(db, FILE_DB)); + input.skip(posLen[0]); + byte[] bytes = new byte[posLen[1]]; + input.read(bytes, 0, posLen[1]); + input.close(); + + String data = new String(bytes); + String[] lines = split(data, "\n"); + for (String line : lines) { + String[] s = split(line, ","); + if (s[0].equals(code)) words.addElement(s[1]); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + return words; + } + + /** + * Indicates if the initial preparation or loading of the on disk dictionary + * is complete. + * @return the indication that the dictionary initial setup is done. + */ + public boolean isReady() { + return ready; + } + + @SuppressWarnings("unchecked") +private boolean newDictionaryFiles() throws FileNotFoundException, IOException { + /* load in contents file, which indicates the files and sizes of the last db build */ + List contents = new ArrayList(); + File c = new File(db, FILE_CONTENTS); + if (c.exists()) { + BufferedReader reader = null; + try { + reader = new BufferedReader(new FileReader(c)); + String line; + while ((line = reader.readLine()) != null) { + // format of file should be [filename],[size] + String[] s = split(line, ","); + contents.add(new FileSize(s[0], Integer.parseInt(s[1]))); + } + } catch (FileNotFoundException e) { + throw e; + } catch (IOException e) { + throw e; + } finally { + if (reader != null) reader.close(); + } + } + + /* compare this to the actual directory */ + boolean changed = false; + File[] wordFiles = words.listFiles(); + if (contents.size() != wordFiles.length) { + // if the size of the contents list and the number of word files are different, it + // means we've definitely got to reindex + changed = true; + } else { + // check and make sure that all the word files haven't changed on us + for (File wordFile : wordFiles) { + FileSize fs = new FileSize(wordFile.getName(), wordFile.length()); + if (!contents.contains(fs)) { + changed = true; + break; + } + } + } + + return changed; + } + + @SuppressWarnings("unchecked") +private File buildSortedFile() throws FileNotFoundException, IOException { + List w = new ArrayList(); + + /* + * read every single word into the list. eeek. if this causes problems, + * we may wish to explore disk-based sorting or more efficient memory-based storage + */ + File[] wordFiles = words.listFiles(); + for (File wordFile : wordFiles) { + BufferedReader r = new BufferedReader(new FileReader(wordFile)); + String word; + while ((word = r.readLine()) != null) { + if (!word.equals("")) { + w.add(word.trim()); + } + } + r.close(); + } + + Collections.sort(w); + + // FIXME - error handling for running out of disk space would be nice. + File file = File.createTempFile("jazzy", "sorted"); + BufferedWriter writer = new BufferedWriter(new FileWriter(file)); + String prev = null; + for (int i = 0; i < w.size(); i++) { + String word = (String) w.get(i); + if (prev == null || !prev.equals(word)) { + writer.write(word); + writer.newLine(); + } + prev = word; + } + writer.close(); + + return file; + } + + @SuppressWarnings("unchecked") +private void buildCodeDb(File sortedWords) throws FileNotFoundException, IOException { + List codeList = new ArrayList(); + + BufferedReader reader = new BufferedReader(new FileReader(sortedWords)); + String word; + while ((word = reader.readLine()) != null) { + codeList.add(new CodeWord(this.getCode(word), word)); + } + reader.close(); + + Collections.sort(codeList); + + List index = new ArrayList(); + + BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(db, FILE_DB))); + String currentCode = null; + int currentPosition = 0; + int currentLength = 0; + for (int i = 0; i < codeList.size(); i++) { + CodeWord cw = (CodeWord) codeList.get(i); + String thisCode = cw.getCode(); +// if (thisCode.length() > 3) thisCode = thisCode.substring(0, 3); + thisCode = getIndexCode(thisCode, codeList); + String toWrite = cw.getCode() + "," + cw.getWord() + "\n"; + byte[] bytes = toWrite.getBytes(); + + if (currentCode == null) currentCode = thisCode; + if (!currentCode.equals(thisCode)) { + index.add(new Object[]{currentCode, new int[]{currentPosition, currentLength}}); + currentPosition += currentLength; + currentLength = bytes.length; + currentCode = thisCode; + } else { + currentLength += bytes.length; + } + out.write(bytes); + } + out.close(); + + // Output the last iteration + if (currentCode != null && currentPosition != 0 && currentLength != 0) + index.add(new Object[]{currentCode, new int[]{currentPosition, currentLength}}); + + BufferedWriter writer = new BufferedWriter(new FileWriter(new File(db, FILE_INDEX))); + for (int i = 0; i < index.size(); i++) { + Object[] o = (Object[]) index.get(i); + writer.write(o[0].toString()); + writer.write(","); + writer.write(String.valueOf(((int[]) o[1])[0])); + writer.write(","); + writer.write(String.valueOf(((int[]) o[1])[1])); + writer.newLine(); + } + writer.close(); + } + + private void buildContentsFile() throws IOException { + File[] wordFiles = words.listFiles(); + if (wordFiles.length > 0) { + BufferedWriter writer = new BufferedWriter(new FileWriter(new File(db, FILE_CONTENTS))); + for (File wordFile : wordFiles) { + writer.write(wordFile.getName()); + writer.write(","); + writer.write(String.valueOf(wordFile.length())); + writer.newLine(); + } + writer.close(); + } else { + new File(db, FILE_CONTENTS).delete(); + } + } + + /** + * Loads the index file from disk. The index file accelerates words lookup + * into the dictionary db file. + */ + @SuppressWarnings("unchecked") +protected void loadIndex() throws IOException { + index = new HashMap(); + File idx = new File(db, FILE_INDEX); + BufferedReader reader = new BufferedReader(new FileReader(idx)); + String line; + while ((line = reader.readLine()) != null) { + String[] fields = split(line, ","); + index.put(fields[0], new int[]{Integer.parseInt(fields[1]), Integer.parseInt(fields[2])}); + } + reader.close(); + } + + private int[] getStartPosAndLen(String code) { + while (code.length() > 0) { + int[] posLen = (int[]) index.get(code); + if (posLen == null) { + code = code.substring(0, code.length() - 1); + } else { + return posLen; + } + } + return null; + } + + @SuppressWarnings("unchecked") +private String getIndexCode(String code, List codes) { + if (indexCodeCache == null) indexCodeCache = new ArrayList(); + + if (code.length() <= 1) return code; + + for (int i = 0; i < indexCodeCache.size(); i++) { + String c = (String) indexCodeCache.get(i); + if (code.startsWith(c)) return c; + } + + int foundSize = -1; + boolean cacheable = false; + for (int z = 1; z < code.length(); z++) { + String thisCode = code.substring(0, z); + int count = 0; + for (int i = 0; i < codes.size();) { + if (i == 0) { + i = Collections.binarySearch(codes, new CodeWord(thisCode, "")); + if (i < 0) i = 0; + } + + CodeWord cw = (CodeWord) codes.get(i); + if (cw.getCode().startsWith(thisCode)) { + count++; + if (count > INDEX_SIZE_MAX) break; + } else if (cw.getCode().compareTo(thisCode) > 0) break; + i++; + } + if (count <= INDEX_SIZE_MAX) { + cacheable = true; + foundSize = z; + break; + } + } + + String newCode = (foundSize == -1) ? code : code.substring(0, foundSize); + if (cacheable) indexCodeCache.add(newCode); + return newCode; + } + + private static String[] split(String input, String delimiter) { + StringTokenizer st = new StringTokenizer(input, delimiter); + int count = st.countTokens(); + String[] out = new String[count]; + + for (int i = 0; i < count; i++) { + out[i] = st.nextToken(); + } + + return out; + } + + @SuppressWarnings("unchecked") +private class CodeWord implements Comparable { + private final String code; + private final String word; + + public CodeWord(String code, String word) { + this.code = code; + this.word = word; + } + + public String getCode() { + return code; + } + + public String getWord() { + return word; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CodeWord)) return false; + + final CodeWord codeWord = (CodeWord) o; + + if (!word.equals(codeWord.word)) return false; + + return true; + } + + @Override + public int hashCode() { + return word.hashCode(); + } + + public int compareTo(Object o) { + return code.compareTo(((CodeWord) o).getCode()); + } + } + + private class FileSize { + private final String filename; + private final long size; + + public FileSize(String filename, long size) { + this.filename = filename; + this.size = size; + } + + @SuppressWarnings("unused") + public String getFilename() { + return filename; + } + + @SuppressWarnings("unused") + public long getSize() { + return size; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof FileSize)) return false; + + final FileSize fileSize = (FileSize) o; + + if (size != fileSize.size) return false; + if (!filename.equals(fileSize.filename)) return false; + + return true; + } + + @Override + public int hashCode() { + int result; + result = filename.hashCode(); + result = (int) (29 * result + size); + return result; + } + } +} diff --git a/src/com/swabunga/spell/engine/SpellDictionaryHashMap.java b/src/com/swabunga/spell/engine/SpellDictionaryHashMap.java new file mode 100644 index 0000000..55a29ea --- /dev/null +++ b/src/com/swabunga/spell/engine/SpellDictionaryHashMap.java @@ -0,0 +1,328 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +/* + * put your module comment here + * formatted with JxBeauty (c) johann.langhofer@nextra.at + */ + +package com.swabunga.spell.engine; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Reader; +import java.util.Hashtable; +import java.util.List; +import java.util.Vector; + +/** + * The SpellDictionaryHashMap holds the dictionary + *

+ * This class is thread safe. Derived classes should ensure that this preserved. + *

+ * There are many open source dictionary files. For just a few see: + * http://wordlist.sourceforge.net/ + *

+ * This dictionary class reads words one per line. Make sure that your word list + * is formatted in this way (most are). + *

+ * Note that you must create the dictionary with a word list for the added + * words to persist. + */ +public class SpellDictionaryHashMap extends SpellDictionaryASpell { + /** A field indicating the initial hash map capacity (16KB) for the main + * dictionary hash map. Interested to see what the performance of a + * smaller initial capacity is like. + */ + private final static int INITIAL_CAPACITY = 16 * 1024; + + /** + * The hashmap that contains the word dictionary. The map is hashed on the doublemeta + * code. The map entry contains a LinkedList of words that have the same double meta code. + */ + @SuppressWarnings("unchecked") +protected Hashtable mainDictionary = new Hashtable(INITIAL_CAPACITY); + + /** Holds the dictionary file for appending*/ + private File dictFile = null; + + /** + * Dictionary Constructor. + * @throws java.io.IOException indicates a problem with the file system + */ + public SpellDictionaryHashMap() throws IOException { + super((File) null); + } + + /** + * Dictionary Constructor. + * @param wordList The file containing the words list for the dictionary + * @throws java.io.IOException indicates problems reading the words list + * file + */ + public SpellDictionaryHashMap(Reader wordList) throws IOException { + super((File) null); + createDictionary(new BufferedReader(wordList)); + } + + /** + * Dictionary convenience Constructor. + * @param wordList The file containing the words list for the dictionary + * @throws java.io.FileNotFoundException indicates problems locating the + * words list file on the system + * @throws java.io.IOException indicates problems reading the words list + * file + */ + public SpellDictionaryHashMap(File wordList) throws FileNotFoundException, IOException { + this(new FileReader(wordList)); + dictFile = wordList; + } + + /** + * Dictionary constructor that uses an aspell phonetic file to + * build the transformation table. + * @param wordList The file containing the words list for the dictionary + * @param phonetic The file to use for phonetic transformation of the + * wordlist. + * @throws java.io.FileNotFoundException indicates problems locating the + * file on the system + * @throws java.io.IOException indicates problems reading the words list + * file + */ + public SpellDictionaryHashMap(File wordList, File phonetic) throws FileNotFoundException, IOException { + super(phonetic); + dictFile = wordList; + createDictionary(new BufferedReader(new FileReader(wordList))); + } + + /** + * Dictionary constructor that uses an aspell phonetic file to + * build the transformation table. Encoding is used for phonetic file only; + * default encoding is used for wordList + * @param wordList The file containing the words list for the dictionary + * @param phonetic The file to use for phonetic transformation of the + * wordlist. + * @param phoneticEncoding Uses the character set encoding specified + * @throws java.io.FileNotFoundException indicates problems locating the + * file on the system + * @throws java.io.IOException indicates problems reading the words list + * or phonetic information + */ + public SpellDictionaryHashMap(File wordList, File phonetic, String phoneticEncoding) throws FileNotFoundException, IOException { + super(phonetic, phoneticEncoding); + dictFile = wordList; + createDictionary(new BufferedReader(new FileReader(wordList))); + } + + /** + * Dictionary constructor that uses an aspell phonetic file to + * build the transformation table. + * @param wordList The file containing the words list for the dictionary + * @param phonetic The reader to use for phonetic transformation of the + * wordlist. + * @throws java.io.IOException indicates problems reading the words list + * or phonetic information + */ + public SpellDictionaryHashMap(Reader wordList, Reader phonetic) throws IOException { + super(phonetic); + dictFile = null; + createDictionary(new BufferedReader(wordList)); + } + + /** + * Add words from a file to existing dictionary hashmap. + * This function can be called as many times as needed to + * build the internal word list. Duplicates are not added. + *

+ * Note that adding a dictionary does not affect the target + * dictionary file for the addWord method. That is, addWord() continues + * to make additions to the dictionary file specified in createDictionary() + *

+ * @param wordList a File object that contains the words, on word per line. + * @throws FileNotFoundException + * @throws IOException + */ + public void addDictionary(File wordList) throws FileNotFoundException, IOException { + addDictionaryHelper(new BufferedReader(new FileReader(wordList))); + } + + /** + * Add words from a Reader to existing dictionary hashmap. + * This function can be called as many times as needed to + * build the internal word list. Duplicates are not added. + *

+ * Note that adding a dictionary does not affect the target + * dictionary file for the addWord method. That is, addWord() continues + * to make additions to the dictionary file specified in createDictionary() + *

+ * @param wordList a Reader object that contains the words, on word per line. + * @throws IOException + */ + public void addDictionary(Reader wordList) throws IOException { + addDictionaryHelper(new BufferedReader(wordList)); + } + + /** + * Add a word permanently to the dictionary (and the dictionary file). + *

This needs to be made thread safe (synchronized)

+ */ + public void addWord(String word) { + putWord(word); + if (dictFile == null) + return; + try { + FileWriter w = new FileWriter(dictFile.toString(), true); + // Open with append. + w.write(word); + w.write("\n"); + w.close(); + } catch (IOException ex) { + System.out.println("Error writing to dictionary file"); + } + } + + /** + * Constructs the dictionary from a word list file. + *

+ * Each word in the reader should be on a separate line. + *

+ * This is a very slow function. On my machine it takes quite a while to + * load the data in. I suspect that we could speed this up quite allot. + */ + protected void createDictionary(BufferedReader in) throws IOException { + String line = ""; + while (line != null) { + line = in.readLine(); + if (line != null && line.length() > 0) { + line = new String(line.toCharArray()); + putWord(line); + } + } + } + + /** + * Adds to the existing dictionary from a word list file. If the word + * already exists in the dictionary, a new entry is not added. + *

+ * Each word in the reader should be on a separate line. + *

+ * Note: for whatever reason that I haven't yet looked into, the phonetic codes + * for a particular word map to a vector of words rather than a hash table. + * This is a drag since in order to check for duplicates you have to iterate + * through all the words that use the phonetic code. + * If the vector-based implementation is important, it may be better + * to subclass for the cases where duplicates are bad. + */ + protected void addDictionaryHelper(BufferedReader in) throws IOException { + + String line = ""; + while (line != null) { + line = in.readLine(); + if (line != null && line.length() > 0) { + line = new String(line.toCharArray()); + putWordUnique(line); + } + } + } + + /** + * Allocates a word in the dictionary + * @param word The word to add + */ + @SuppressWarnings("unchecked") +protected void putWord(String word) { + String code = getCode(word); + Vector list = (Vector) mainDictionary.get(code); + if (list != null) { + list.addElement(word); + } else { + list = new Vector(); + list.addElement(word); + mainDictionary.put(code, list); + } + } + + /** + * Allocates a word, if it is not already present in the dictionary. A word + * with a different case is considered the same. + * @param word The word to add + */ + @SuppressWarnings("unchecked") +protected void putWordUnique(String word) { + + String code = getCode(word); + Vector list = (Vector) mainDictionary.get(code); + + if (list != null) { + + boolean isAlready = false; + + for (int i = 0; i < list.size(); i++) { + + if (word.equalsIgnoreCase((String) list.elementAt(i))) { + isAlready = true; + break; + } + } + + if (!isAlready) + list.addElement(word); + + } else { + + list = new Vector(); + list.addElement(word); + mainDictionary.put(code, list); + + } + } + + /** + * Returns a list of strings (words) for the code. + */ + @Override +@SuppressWarnings("unchecked") +public List getWords(String code) { + //Check the main dictionary. + Vector mainDictResult = (Vector) mainDictionary.get(code); + if (mainDictResult == null) + return new Vector(); + return mainDictResult; + } + + /** + * Returns true if the word is correctly spelled against the current word list. + */ + @Override +@SuppressWarnings("unchecked") +public boolean isCorrect(String word) { + List possible = getWords(getCode(word)); + if (possible.contains(word)) + return true; + //JMH should we always try the lowercase version. If I dont then capitalised + //words are always returned as incorrect. + else if (possible.contains(word.toLowerCase())) + return true; + return false; + } +} diff --git a/src/com/swabunga/spell/engine/Transformator.java b/src/com/swabunga/spell/engine/Transformator.java new file mode 100644 index 0000000..39d0bec --- /dev/null +++ b/src/com/swabunga/spell/engine/Transformator.java @@ -0,0 +1,54 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.engine; + +/** + * An interface for all Transformators - which take a dictionary word and converts into its + * phonetic hash. These phonetic hashes are useful for determining what other words are + * similar to it, and then list those words as suggestions. + * + * @author Robert Gustavsson (robert@lindesign.se) + */ +public interface Transformator { + + /** + * Take the given word, and return the best phonetic hash for it. + * @param word the word to transform + * @return the phonetic transformation of the word + */ + public String transform(String word); + + /** + * gets the list of characters that should be swapped in to the misspelled word + * in order to try to find more suggestions. + * In general, this list represents all of the unique phonetic characters + * for this Transformator. + *

+ * The replace list is used in the getSuggestions method. + * All of the letters in the misspelled word are replaced with the characters from + * this list to try and generate more suggestions, which implies l*n tries, + * if l is the size of the string, and n is the size of this list. + *

+ * In addition to that, each of these letters is added to the misspelled word. + *

+ * @return char[] misspelled words should try replacing with these characters to get more suggestions + */ + public char[] getReplaceList(); +} diff --git a/src/com/swabunga/spell/engine/Word.java b/src/com/swabunga/spell/engine/Word.java new file mode 100644 index 0000000..8927e5f --- /dev/null +++ b/src/com/swabunga/spell/engine/Word.java @@ -0,0 +1,115 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.engine; + +import java.util.Comparator; + +/** + * The Word object holds information for one suggested spelling. + * It contains both the suggested word string and the distance cost, which represents how different the suggested + * word is from the misspelling. + *

This class is now immutable. + *

+ */ +@SuppressWarnings("unchecked") +public class Word implements Comparator { + private String word; + private final int score; + + /** + * Constructs a new Word. + * @param word The text of a word. + * @param score The word's distance cost + */ + public Word(String word, int score) { + this.word = word; + this.score = score; + } + + /** + * Constructs a new Word. + */ + public Word() { + this.word = ""; + this.score = 0; + } + + /** + * Compares two words, mostly for the purpose of sorting words. + * @param o1 the first word + * @param o2 the second word + * @return -1 if the first word is more similar to the misspelled word + *
1 if the second word is more similar to the misspelled word + *
0 if both words are equally similar + * + */ + public int compare(Object o1, Object o2) { + if (((Word) o1).getCost() < ((Word) o2).getCost()) return -1; + if (((Word) o1).getCost() == ((Word) o2).getCost()) return 0; + return 1; + } + + /** + * Indicates if this word is equal to another one. + * @param o The other word to compare + * @return The indication of equality + */ + @Override +public boolean equals(Object o) { + if (o instanceof Word) // added by bd + return(((Word)o).getWord().equals(getWord())); + return false; + } + + /** + * gets suggested spelling + * @return the actual text of the suggest spelling + */ + public String getWord() { + return word; + } + + /** + * sets suggested spelling + * @param word The text to set for suggestd spelling + */ + public void setWord(String word) { + this.word = word; + } + + /** + * A cost measures how close a match this word was to the original word + * @return 0 if an exact match. Higher numbers are worse matches. + * @see EditDistance + */ + public int getCost() { + return score; + } + + /** + * returns the suggested spelling + * @return The word's text + */ + @Override +public String toString() { + return word; + } +} + diff --git a/src/com/swabunga/spell/engine/configuration.properties b/src/com/swabunga/spell/engine/configuration.properties new file mode 100644 index 0000000..a38b9d4 --- /dev/null +++ b/src/com/swabunga/spell/engine/configuration.properties @@ -0,0 +1,18 @@ +EDIT_DEL1=95 +EDIT_DEL2=95 +EDIT_SWAP=90 +EDIT_SUB=100 +EDIT_CASE=10 + +#DMV: the following commented out settings do not seem to be used at all +#EDIT_SIMILAR=10 +#EDIT_MIN=90 +#EDIT_MAX=100 + +SPELL_THRESHOLD=140 +SPELL_IGNOREUPPERCASE=true +SPELL_IGNOREMIXEDCASE=false +SPELL_IGNOREINTERNETADDRESS=true +SPELL_IGNOREDIGITWORDS=true +SPELL_IGNOREMULTIPLEWORDS=false +SPELL_IGNORESENTENCECAPTILIZATION=true diff --git a/src/com/swabunga/spell/event/AbstractWordFinder.java b/src/com/swabunga/spell/event/AbstractWordFinder.java new file mode 100644 index 0000000..da8e247 --- /dev/null +++ b/src/com/swabunga/spell/event/AbstractWordFinder.java @@ -0,0 +1,392 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.event; + +import java.text.BreakIterator; + +/** + * Defines common methods and behaviour for the various word finding + * subclasses. + * + * @author Anthony Roy (ajr@antroy.co.uk) + */ +public abstract class AbstractWordFinder implements WordFinder { + + //~ Instance/static variables ............................................. + + /** The word being analyzed */ + protected Word currentWord; + /** The word following the current one */ + protected Word nextWord; + /** Indicate if the current word starts a new sentence */ + protected boolean startsSentence; + /** Holds the text to analyze */ + protected String text; + /** An iterator to work through the sentence */ + protected BreakIterator sentenceIterator; + + //~ Constructors .......................................................... + + /** + * Creates a new AbstractWordFinder object. + * + * @param inText the String to iterate through. + */ + public AbstractWordFinder(String inText) { + text = inText; + setup(); + } + + /** + * Creates a new default AbstractWordFinder object. + */ + public AbstractWordFinder() { + text = ""; + setup(); + } + //~ Methods ............................................................... + + /** + * This method scans the text from the end of the last word, and returns + * a new Word object corresponding to the next word. + * + * @return the following word. + */ + public abstract Word next(); + + /** + * Return the text being searched. May have changed since first set + * through calls to replace. + * + * @return the text being searched. + */ + public String getText() { + + return text; + } + + /** + * Defines the text to search. + * @param newText The text to be analyzed + */ + public void setText(String newText) { + text = newText; + setup(); + } + + /** + * Returns the current word in the iteration . + * + * @return the current word. + * @throws WordNotFoundException current word has not yet been set. + */ + public Word current() { + + if (currentWord == null) { + throw new WordNotFoundException("No Words in current String"); + } + + return currentWord; + } + + /** + * Indicates if there is some more word to analyze + * @return true if there are further words in the string. + */ + public boolean hasNext() { + + return nextWord != null; + + } + + /** + * Replace the current word in the search with a replacement string. + * + * @param newWord the replacement string. + * @throws WordNotFoundException current word has not yet been set. + */ + public void replace(String newWord) { + + if (currentWord == null) { + throw new WordNotFoundException("No Words in current String"); + } + + StringBuffer sb = new StringBuffer(text.substring(0, currentWord.getStart())); + sb.append(newWord); + sb.append(text.substring(currentWord.getEnd())); + int diff = newWord.length() - currentWord.getText().length(); + currentWord.setText(newWord); + /* Added Conditional to ensure a NullPointerException is avoided (11 Feb 2003) */ + if (nextWord != null) { + nextWord.setStart(nextWord.getStart() + diff); + } + text = sb.toString(); + + sentenceIterator.setText(text); + int start = currentWord.getStart(); + sentenceIterator.following(start); + startsSentence = sentenceIterator.current() == start; + + } + + /** + * @return true if the current word starts a new sentence. + * @throws WordNotFoundException current word has not yet been set. + */ + public boolean startsSentence() { + + if (currentWord == null) { + throw new WordNotFoundException("No Words in current String"); + } + + return startsSentence; + } + + /** + * Return the text being searched. May have changed since first set + * through calls to replace. + * + * @return the text being searched. + */ + public String toString() { + + return text; + } + + /** + * Adjusts the sentence iterator and the startSentence flag according to the + * currentWord. + * @param wd the wd parameter is not presently used. + */ + protected void setSentenceIterator(Word wd) { + int current = sentenceIterator.current(); + + if (current == currentWord.getStart()) + startsSentence = true; + else { + startsSentence = false; + + if (currentWord.getEnd() > current) { + sentenceIterator.next(); + } + } + } + + /** + * Indicates if the character at the specified position is acceptable as + * part of a word. To be acceptable, the character need to be a letter + * or a digit. It is also acceptable if the character is one of ''', '@', + * '.' or '_' and is preceded and followed by letter or digit. + * @param posn The character position to analyze. + * @return true if the character is a letter or digit + */ + //Added more intelligent character recognition (11 Feb '03) + protected boolean isWordChar(int posn) { + boolean out = false; + + char curr = text.charAt(posn); + + if ((posn == 0) || (posn == text.length() - 1)) { + return Character.isLetterOrDigit(curr); + } + + char prev = text.charAt(posn - 1); + char next = text.charAt(posn + 1); + + + switch (curr) { + case '\'': + case '@': + case '.': + case '_': + out = (Character.isLetterOrDigit(prev) && Character.isLetterOrDigit(next)); + break; + default : + out = Character.isLetterOrDigit(curr); + } + + return out; + } + + /** + * Indicates if the character at the specified character is acceptable as + * part of a word. To be acceptable, the character need to be a letter + * or a digit or a ' (an apostrophe). + * @param c The character to evaluates if it can be part of a word + * @return true if the character is a letter, digit or a ' (an apostrophe). + */ + protected boolean isWordChar(char c) { + boolean out = false; + + if (Character.isLetterOrDigit(c) || (c == '\'')) { + out = true; + } + + return out; + } + + /** + * Ignores or skip over text starting from the index position specified + * if it contains the startIgnore, and until the + * first non letter or digit character is encountered or end of text is + * detected. + * @param index The start position in text. + * @param startIgnore The character that should be at index + * position to start skipping through. + * @return The index position pointing after the skipped characters or the + * original index if the ignore condition could not be met. + */ + protected int ignore(int index, char startIgnore) { + return ignore(index, new Character(startIgnore), null); + } + + /** + * Ignores or skip over text starting from the index position specified + * if it contains the startIgnore, and until the + * endIgnore character is encountered or end of text is + * detected. + * @param index The start position in text. + * @param startIgnore The character that should be at index + * position to start skipping through. + * @param endIgnore The character which mark the end of skipping through. If + * the value of endIgnore is null, skipping characters stop + * at first non letter or digit character. + * @return The index position pointing after the skipped characters or the + * original index if the ignore condition could not be met. + */ + protected int ignore(int index, char startIgnore, char endIgnore) { + return ignore(index, new Character(startIgnore), new Character(endIgnore)); + } + + /** + * Ignores or skip over text starting from the index position specified + * if it contains the startIgnore, and until the + * endIgnore character is encountered or end of text is + * detected. + * @param index The start position in text. + * @param startIgnore The character that should be at index + * position to start skipping through. + * @param endIgnore The character which mark the end of skipping through. If + * the value of endIgnore is null, skipping characters stop + * at first non letter or digit character. + * @return The index position pointing after the skipped characters or the + * original index if the ignore condition could not be met. + */ + protected int ignore(int index, Character startIgnore, Character endIgnore) { + int newIndex = index; + + if (newIndex < text.length()) { + Character curChar = new Character(text.charAt(newIndex)); + + if (curChar.equals(startIgnore)) { + newIndex++; + while (newIndex < text.length()) { + curChar = new Character(text.charAt(newIndex)); + if (endIgnore != null && curChar.equals(endIgnore)){ + newIndex++; + break; + } else if (endIgnore == null && !Character.isLetterOrDigit(curChar.charValue())){ + break; + } + newIndex++; + } + } + } + + return newIndex; + } + + /** + * Ignores or skip over text starting from the index position specified + * if it contains the startIgnore string, and until the + * endIgnore string is encountered or end of text is + * detected. + * @param index The start position in text. + * @param startIgnore The string that should be at index + * position to start skipping through. + * @param endIgnore The string which mark the end of skipping through. + * @return The index position pointing after the skipped characters or the + * original index if the ignore condition could not be met. + */ + protected int ignore(int index, String startIgnore, String endIgnore) { + + //{{{ + int newIndex = index; + int len = text.length(); + int slen = startIgnore.length(); + int elen = endIgnore.length(); + + if (!((newIndex + slen) >= len)) { + String seg = text.substring(newIndex, newIndex + slen); + + // System.out.println(seg + ":" + seg.length()+ ":" + startIgnore + ":" + slen); + if (seg.equals(startIgnore)) { + newIndex += slen; + cycle: while (true) { + + if (newIndex == (text.length() - elen)) { + + break cycle; + } + + String ss = text.substring(newIndex, newIndex + elen); + + if (ss.equals(endIgnore)) { + newIndex += elen; + + break cycle; + } else { + newIndex++; + } + } + } + } + + return newIndex; + } //}}} + + /** + * Initializes the sentenseIterator + */ + protected void init() { + sentenceIterator = BreakIterator.getSentenceInstance(); + sentenceIterator.setText(text); + } + + /** + * Defines the starting positions for text analysis + */ + private void setup() { + currentWord = new Word("", 0); + nextWord = new Word("", 0); + startsSentence = true; + + init(); + + try { + next(); + } catch (WordNotFoundException e) { + currentWord = null; + nextWord = null; + } + } + + +} diff --git a/src/com/swabunga/spell/event/AbstractWordTokenizer.java b/src/com/swabunga/spell/event/AbstractWordTokenizer.java new file mode 100644 index 0000000..9335592 --- /dev/null +++ b/src/com/swabunga/spell/event/AbstractWordTokenizer.java @@ -0,0 +1,164 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.event; + +import java.text.BreakIterator; + + +/** + * This class tokenizes a input string. + * + *

+ * It also allows for the string to be mutated. The result after the spell + * checking is completed is available to the call to getFinalText + *

+ * + * @author Jason Height(jheight@chariot.net.au) + * @author Anthony Roy (ajr@antroy.co.uk) + */ +public abstract class AbstractWordTokenizer implements WordTokenizer { + + //~ Instance/static variables ............................................... + + /** The word being analyzed */ + protected Word currentWord; + /** The word finder used to filter out words which are non pertinent to + * spell checking */ + protected WordFinder finder; + /** An iterator to work through the sentence */ + protected BreakIterator sentenceIterator; + + /** The cumulative word count that have been processed */ + protected int wordCount = 0; + + //~ Constructors ............................................................ + + /** + * Creates a new AbstractWordTokenizer object. + * + * @param text the text to process. + */ + public AbstractWordTokenizer(String text) { + this(new DefaultWordFinder(text)); + } + + /** + * Creates a new AbstractWordTokenizer object. + * + * @param wf the custom WordFinder to use in searching for words. + */ + public AbstractWordTokenizer(WordFinder wf) { + this.finder = wf; + } + + //~ Methods ................................................................. + + /** + * Returns the current number of words that have been processed + * + * @return number of words so far iterated. + */ + public int getCurrentWordCount() { + + return wordCount; + } + + /** + * Returns the end of the current word in the text + * + * @return index in string of the end of the current word. + * @throws WordNotFoundException current word has not yet been set. + */ + public int getCurrentWordEnd() { + + if (currentWord == null) { + throw new WordNotFoundException("No Words in current String"); + } + + return currentWord.getEnd(); + } + + /** + * Returns the index of the start of the current word in the text + * + * @return index in string of the start of the current word. + * @throws WordNotFoundException current word has not yet been set. + */ + public int getCurrentWordPosition() { + + if (currentWord == null) { + throw new WordNotFoundException("No Words in current String"); + } + + return currentWord.getStart(); + } + + /** + * Returns true if there are more words that can be processed in the string + * + * @return true if there are further words in the text. + */ + public boolean hasMoreWords() { + + return finder.hasNext(); + } + + /** + * Returns searches for the next word in the text, and returns that word. + * + * @return the string representing the current word. + * @throws WordNotFoundException search string contains no more words. + */ + public String nextWord() { + currentWord = finder.next(); + + return currentWord.getText(); + } + + /** + * Replaces the current word token + * + * @param newWord replacement word. + * @throws WordNotFoundException current word has not yet been set. + */ + public abstract void replaceWord(String newWord); + + /** + * Returns the current text that is being tokenized (includes any changes + * that have been made) + * + * @return the text being tokenized. + */ + public String getContext() { + + return finder.toString(); + } + + /** + * returns true if the current word is at the start of a sentence + * + * @return true if the current word starts a sentence. + * @throws WordNotFoundException current word has not yet been set. + */ + public boolean isNewSentence() { + + return finder.startsSentence(); + } +} \ No newline at end of file diff --git a/src/com/swabunga/spell/event/BasicSpellCheckEvent.java b/src/com/swabunga/spell/event/BasicSpellCheckEvent.java new file mode 100644 index 0000000..7b071c9 --- /dev/null +++ b/src/com/swabunga/spell/event/BasicSpellCheckEvent.java @@ -0,0 +1,151 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.event; + +import java.util.List; + +/** This event is fired off by the SpellChecker and is passed to the + * registered SpellCheckListeners + * + * @author Jason Height (jheight@chariot.net.au) + */ +class BasicSpellCheckEvent implements SpellCheckEvent { + + /**The list holding the suggested Word objects for the misspelt word*/ + @SuppressWarnings("unchecked") +private final List suggestions; + /**The misspelt word*/ + private final String invalidWord; + /**The action to be done when the event returns*/ + private short action = INITIAL; + /**Contains the word to be replaced if the action is REPLACE or REPLACEALL*/ + private String replaceWord = null; + + @SuppressWarnings("unused") +private final String context; + private final int startPosition; + + + /**Constructs the SpellCheckEvent + * @param invalidWord The word that is misspelt + * @param suggestions A list of Word objects that are suggested to replace the currently misspelt word + * @param tokenizer The reference to the tokenizer that caused this + * event to fire. + */ + @SuppressWarnings("unchecked") +public BasicSpellCheckEvent(String invalidWord, List suggestions, WordTokenizer tokenizer) { + this.invalidWord = invalidWord; + this.suggestions = suggestions; + this.context = tokenizer.getContext(); + this.startPosition = tokenizer.getCurrentWordPosition(); + } + + /** Returns the list of suggested Word objects + * @return A list of words phonetically close to the misspelt word + */ + @SuppressWarnings("unchecked") +public List getSuggestions() { + return suggestions; + } + + /** Returns the currently misspelt word + * @return The text misspelt + */ + public String getInvalidWord() { + return invalidWord; + } + + /** Returns the context in which the misspelt word is used + * @return The text containing the context + */ + public String getWordContext() { + //JMH TBD + return null; + } + + /** Returns the start position of the misspelt word in the context + * @return The position of the word + */ + public int getWordContextPosition() { + return startPosition; + } + + /** Returns the action type the user has to handle + * @return The type of action the event is carrying + */ + public short getAction() { + return action; + } + + /** Returns the text to replace + * @return the text of the word to replace + */ + public String getReplaceWord() { + return replaceWord; + } + + /** Set the action to replace the currently misspelt word with the new word + * @param newWord The word to replace the currently misspelt word + * @param replaceAll If set to true, the SpellChecker will replace all + * further occurrences of the misspelt word without firing a SpellCheckEvent. + */ + public void replaceWord(String newWord, boolean replaceAll) { + if (action != INITIAL) + throw new IllegalStateException("The action can can only be set once"); + if (replaceAll) + action = REPLACEALL; + else + action = REPLACE; + replaceWord = newWord; + } + + /** + * Set the action it ignore the currently misspelt word. + * @param ignoreAll If set to true, the SpellChecker will replace all + * further occurrences of the misspelt word without firing a SpellCheckEvent. + */ + public void ignoreWord(boolean ignoreAll) { + if (action != INITIAL) + throw new IllegalStateException("The action can can only be set once"); + if (ignoreAll) + action = IGNOREALL; + else + action = IGNORE; + } + + /** Set the action to add a new word into the dictionary. This will also replace the + * currently misspelt word. + * @param newWord The new word to add to the dictionary. + */ + public void addToDictionary(String newWord) { + if (action != INITIAL) + throw new IllegalStateException("The action can can only be set once"); + action = ADDTODICT; + replaceWord = newWord; + } + + /** Set the action to terminate processing of the spellchecker. + */ + public void cancel() { + if (action != INITIAL) + throw new IllegalStateException("The action can can only be set once"); + action = CANCEL; + } +} \ No newline at end of file diff --git a/src/com/swabunga/spell/event/DefaultWordFinder.java b/src/com/swabunga/spell/event/DefaultWordFinder.java new file mode 100644 index 0000000..350a88a --- /dev/null +++ b/src/com/swabunga/spell/event/DefaultWordFinder.java @@ -0,0 +1,116 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.event; + +/** + * A basic word finder, which searches text for sequences of letters. + * + * @author Anthony Roy (ajr@antroy.co.uk) + */ +public class DefaultWordFinder extends AbstractWordFinder { + + //~ Instance/static variables ............................................... + + //~ Constructors ............................................................ + + /** + * Creates a new DefaultWordFinder object. + * + * @param inText the String to search + */ + public DefaultWordFinder(String inText) { + super(inText); + } + + /** + * Creates a new DefaultWordFinder object. + */ + public DefaultWordFinder() { + super(); + } + + //~ Methods ................................................................. + + /** + * This method scans the text from the end of the last word, and returns a + * new Word object corresponding to the next word. + * + * @return the next word. + * @throws WordNotFoundException search string contains no more words. + */ + public Word next() { + if (nextWord == null) { + throw new WordNotFoundException("No more words found."); + } + currentWord.copy(nextWord); + setSentenceIterator(currentWord); + + int i = currentWord.getEnd(); + boolean finished = false; + + while (i < text.length() && !finished) { + if (isWordChar(i)) { + nextWord.setStart(i); + int end = getNextWordEnd(text, i); + nextWord.setText(text.substring(i, end)); + finished = true; + } + i++; + } + if (!finished) + nextWord = null; + + return currentWord; + } + + /** + * Returns the position in the string after the end of the next word. + * Note that this return value should not be used as an index into the string + * without checking first that it is in range, since it is possible for the + * value text.length() to be returned by this method. + */ + private int getNextWordEnd(String text, int startPos) { + // If we're dealing with a possible 'internet word' we need to provide + // some special handling + if (SpellChecker.isINETWord(text.substring(startPos))) { + for (int i = startPos; i < text.length(); i++) { + char ch = text.charAt(i); + if (Character.isLetterOrDigit(ch)) + continue; + + if (ch == '\r' || ch == '\n') + return i; + // Chop off any characters that might be enclosing the 'internet word'. eg ',",),] + if (Character.isSpaceChar(ch)) + if (i > 0 && Character.isLetterOrDigit(text.charAt(i - 1))) + return i; + else + return i - 1; + } + return text.length(); + } else { + for (int i = startPos; i < text.length(); i++) { + if (!isWordChar(i)) + return i; + } + return text.length(); + } + } +} diff --git a/src/com/swabunga/spell/event/DocumentWordTokenizer.java b/src/com/swabunga/spell/event/DocumentWordTokenizer.java new file mode 100644 index 0000000..f2b961f --- /dev/null +++ b/src/com/swabunga/spell/event/DocumentWordTokenizer.java @@ -0,0 +1,267 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.event; + + +import java.text.BreakIterator; + +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.Segment; +import javax.swing.text.StyledDocument; + + +/** This class tokenizes a swing document model. It also allows for the + * document model to be changed when corrections occur. + * + * @author Jason Height (jheight@chariot.net.au) + */ +public class DocumentWordTokenizer implements WordTokenizer { + /** Holds the start character position of the current word*/ + private int currentWordPos = 0; + /** Holds the end character position of the current word*/ + private int currentWordEnd = 0; + /** Holds the start character position of the next word*/ + private int nextWordPos = -1; + /** The actual text that is being tokenized*/ + private final Document document; + /** The character iterator over the document*/ + private final Segment text; + /** The cumulative word count that have been processed*/ + private int wordCount = 0; + /** Flag indicating if there are any more tokens (words) left*/ + private boolean moreTokens = true; + /** Is this a special case where the currentWordStart, currntWordEnd and + * nextWordPos have already been calculated. (see nextWord) + */ + private boolean first = true; + private final BreakIterator sentenceIterator; + private boolean startsSentence = true; + + /** + * Creates a new DocumentWordTokenizer to work on a document + * @param document The document to spell check + */ + public DocumentWordTokenizer(Document document) { + this.document = document; + //Create a text segment over the entire document + text = new Segment(); + sentenceIterator = BreakIterator.getSentenceInstance(); + try { + document.getText(0, document.getLength(), text); + sentenceIterator.setText(text); + currentWordPos = getNextWordStart(text, 0); + //If the current word pos is -1 then the string was all white space + if (currentWordPos != -1) { + currentWordEnd = getNextWordEnd(text, currentWordPos); + nextWordPos = getNextWordStart(text, currentWordEnd); + } else { + moreTokens = false; + } + } catch (BadLocationException ex) { + moreTokens = false; + } + } + + /** This helper method will return the start character of the next + * word in the buffer from the start position + */ + private static int getNextWordStart(Segment text, int startPos) { + if (startPos <= text.getEndIndex()) + for (char ch = text.setIndex(startPos); ch != Segment.DONE; ch = text.next()) { + if (Character.isLetterOrDigit(ch)) { + return text.getIndex(); + } + } + return -1; + } + + /** This helper method will return the end of the next word in the buffer. + * + */ + private static int getNextWordEnd(Segment text, int startPos) { + for (char ch = text.setIndex(startPos); ch != Segment.DONE; ch = text.next()) { + if (!Character.isLetterOrDigit(ch)) { + if (ch == '-' || ch == '\'') { // handle ' and - inside words + char ch2 = text.next(); + text.previous(); + if (ch2 != Segment.DONE && Character.isLetterOrDigit(ch2)) + continue; + } + return text.getIndex(); + } + } + return text.getEndIndex(); + } + + /** + * Indicates if there are more words left + * @return true if more words can be found in the text. + */ + public boolean hasMoreWords() { + return moreTokens; + } + + /** + * Sets the current word position at the start of the word containing + * the char at position pos. This way a call to nextWord() will return + * this word. + * + * @param pos position in the word we want to set as current. + */ + public void posStartFullWordFrom(int pos){ + currentWordPos=text.getBeginIndex(); + if(pos>text.getEndIndex()) + pos=text.getEndIndex(); + for (char ch = text.setIndex(pos); ch != Segment.DONE; ch = text.previous()) { + if (!Character.isLetterOrDigit(ch)) { + if (ch == '-' || ch == '\'') { // handle ' and - inside words + char ch2 = text.previous(); + text.next(); + if (ch2 != Segment.DONE && Character.isLetterOrDigit(ch2)) + continue; + } + currentWordPos=text.getIndex()+1; + break; + } + } + //System.out.println("CurPos:"+currentWordPos); + if(currentWordPos==0) + first=true; + moreTokens=true; + currentWordEnd = getNextWordEnd(text, currentWordPos); + nextWordPos = getNextWordStart(text, currentWordEnd + 1); + } + + /** + * Returns the number of word tokens that have been processed thus far + * @return the number of words found so far. + */ + public int getCurrentWordPosition() { + return currentWordPos; + } + + /** + * Returns an index representing the end location of the current word in the text. + * @return index of the end of the current word in the text. + */ + public int getCurrentWordEnd() { + return currentWordEnd; + } + + /** + * This returns the next word in the iteration. Note that any implementation should return + * the current word, and then replace the current word with the next word found in the + * input text (if one exists). + * @return the next word in the iteration. + */ + public String nextWord() { + if (!first) { + currentWordPos = nextWordPos; + currentWordEnd = getNextWordEnd(text, currentWordPos); + nextWordPos = getNextWordStart(text, currentWordEnd + 1); + } + int current = sentenceIterator.current(); + if (current == currentWordPos) + startsSentence = true; + else { + startsSentence = false; + if (currentWordEnd > current) + sentenceIterator.next(); + } + //The nextWordPos has already been populated + String word = null; + try { + word = document.getText(currentWordPos, currentWordEnd - currentWordPos); + } catch (BadLocationException ex) { + moreTokens = false; + } + wordCount++; + first = false; + if (nextWordPos == -1) + moreTokens = false; + return word; + } + + /** + * Returns the number of word tokens that have been processed thus far + * @return the number of words found so far. + */ + public int getCurrentWordCount() { + return wordCount; + } + + /** Replaces the current word token + * @param newWord The new word to replace the misspelt one + */ + public void replaceWord(String newWord) { + @SuppressWarnings("unused") + AttributeSet attr=null; + if (currentWordPos != -1) { + try { + if(document instanceof StyledDocument) + attr=((StyledDocument)document).getCharacterElement(currentWordPos).getAttributes(); + document.remove(currentWordPos, currentWordEnd - currentWordPos); + document.insertString(currentWordPos, newWord, null); + //Need to reset the segment + document.getText(0, document.getLength(), text); + } catch (BadLocationException ex) { + throw new RuntimeException(ex.getMessage()); + } + //Position after the newly replaced word(s) + first = true; + currentWordPos = getNextWordStart(text, currentWordPos + newWord.length()); + if (currentWordPos != -1) { + currentWordEnd = getNextWordEnd(text, currentWordPos); + nextWordPos = getNextWordStart(text, currentWordEnd); + sentenceIterator.setText(text); + sentenceIterator.following(currentWordPos); + } else + moreTokens = false; + } + } + + /** Returns the current text that is being tokenized (includes any changes + * that have been made) + * @return The text, including changes. + */ + public String getContext() { + return text.toString(); + } + + /** Indicates if the current word is at the start of a sentence + * @return true if the current word is at the start of a sentence + */ + public boolean isNewSentence() { + // BreakIterator doesn't work when the first word in a sentence is not capitalised, + // but we need to check for capitalisation + if (startsSentence || currentWordPos < 2) + return(true); + + String textBefore = null; + try { + textBefore = document.getText(currentWordPos-2, 2); + } catch (BadLocationException ex) { + return(false); + } + return(textBefore != null && ".".equals(textBefore.trim())); + } +} \ No newline at end of file diff --git a/src/com/swabunga/spell/event/FileWordTokenizer.java b/src/com/swabunga/spell/event/FileWordTokenizer.java new file mode 100644 index 0000000..10edb06 --- /dev/null +++ b/src/com/swabunga/spell/event/FileWordTokenizer.java @@ -0,0 +1,94 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.event; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; + + +/** + * This class tokenizes a input file. + * + *

+ * Any takers to do this efficiently?? doesn't need to replace any words to + * start with. I need this to get an idea of how quick the spell checker is. + *

+ */ +public class FileWordTokenizer extends AbstractWordTokenizer { + + //~ Instance/static variables ............................................... + +// private File inFile; + + //~ Constructors ............................................................ + + /** + * Creates a new FileWordTokenizer object. + * + * @param inputFile the file to work upon + */ + public FileWordTokenizer(File inputFile) { + super(stringValue(inputFile)); + } + + /** + * Creates a new FileWordTokenizer object and associate a WordFinder to it's + * processing. + * + * @param inputFile the file to word upon. + * @param finder the specialize processing for words. + */ + public FileWordTokenizer(File inputFile, WordFinder finder) { + super(finder); + finder.setText(stringValue(inputFile)); + } + //~ Methods ................................................................. + + /** + * Replaces the current word token + * + * @param s the new string + * @throws WordNotFoundException current word not yet set. + */ + @Override +public void replaceWord(String s) { + } + + private static String stringValue(File inFile) { + @SuppressWarnings("unused") + File stringFile = inFile; + StringBuffer out = new StringBuffer(""); + + try{ + BufferedReader in = new BufferedReader(new FileReader(inFile)); + char[] c = new char[100]; + int count; + while ((count = in.read(c, 0, c.length)) != -1){ + out.append(c,0,count); + } + in.close(); + } catch(IOException e){ + System.err.println("File input error trying to open " + inFile.toString() + " : " + e); + } + return out.toString(); + } +} \ No newline at end of file diff --git a/src/com/swabunga/spell/event/JavaWordFinder.java b/src/com/swabunga/spell/event/JavaWordFinder.java new file mode 100644 index 0000000..9c700b0 --- /dev/null +++ b/src/com/swabunga/spell/event/JavaWordFinder.java @@ -0,0 +1,142 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.event; + + +/** + * A word finder Java source files, which searches text for sequences of + * letters formated as Java comments. + * + * @author Anthony Roy (ajr@antroy.co.uk) + */ +public class JavaWordFinder extends AbstractWordFinder { + + //~ Instance/static variables ............................................... + + private boolean inComment; + + //~ Constructors ............................................................ + + /** + * Creates a new JavaWordFinder object. + * + * @param inText the String to search + */ + public JavaWordFinder(String inText) { + super(inText); + } + + /** + * Creates a new JavaWordFinder object. + */ + public JavaWordFinder() { + super(); + } + + //~ Methods ................................................................. + + + /** + * This method scans the text from the end of the last word, and returns a + * new Word object corresponding to the next word. + * + * @return the next word. + * @throws WordNotFoundException search string contains no more words. + */ + @Override +public Word next() { + + if (nextWord == null) { + throw new WordNotFoundException("No more words found."); + } + + currentWord.copy(nextWord); + + @SuppressWarnings("unused") + int current = sentenceIterator.current(); + setSentenceIterator(currentWord); + + int i = currentWord.getEnd(); + boolean finished = false; + boolean started = false; + + search: + while (i < text.length() && !finished) { + + i = ignore(i, '@'); + i = ignore(i, "", ""); + i = ignore(i, "", ""); + i = ignore(i, '<', '>'); + + if (i >= text.length()) break search; + + char currentLetter = text.charAt(i); + if (inComment) { + //Reset on new line. + if (currentLetter == '\n') { + inComment = false; + i++; + continue search; + } else if (!isWordChar(i)) { + i++; + continue search; + } + //Find words. + while (i < text.length() - 1) { + if (!started && isWordChar(i)) { + nextWord.setStart(i); + started = true; + } else if (started && !isWordChar(i)) { + nextWord.setText(text.substring(nextWord.getStart(), i)); + finished = true; + break search; + } + + currentLetter = text.charAt(++i); + } + } else if (currentLetter == '*') { + inComment = true; + i++; + } else { + i++; + } + } + + if (!started) { + nextWord = null; + } else if (!finished) { + nextWord.setText(text.substring(nextWord.getStart(), i)); + } + + return currentWord; + } + + /** + * Initializes this word finder + */ + + @Override +protected void init() { +// sentenceIterator = BreakIterator.getSentenceInstance(); +// sentenceIterator.setText(text); + super.init(); + inComment = false; + } +} diff --git a/src/com/swabunga/spell/event/SpellCheckEvent.java b/src/com/swabunga/spell/event/SpellCheckEvent.java new file mode 100644 index 0000000..c695a0c --- /dev/null +++ b/src/com/swabunga/spell/event/SpellCheckEvent.java @@ -0,0 +1,103 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.event; + +import java.util.List; + +/** + * This event is fired off by the SpellChecker and is passed to the + * registered SpellCheckListeners + *

+ * As far as I know, we will only require one implementation of the SpellCheckEvent + * (BasicSpellCheckEvent) but I have defined this interface just in case. The + * BasicSpellCheckEvent implementation is currently package private. + * + * @author Jason Height (jheight@chariot.net.au) + */ +public interface SpellCheckEvent { + /** Field indicating that the incorrect word should be ignored*/ + public static final short IGNORE = 0; + /** Field indicating that the incorrect word should be ignored forever*/ + public static final short IGNOREALL = 1; + /** Field indicating that the incorrect word should be replaced*/ + public static final short REPLACE = 2; + /** Field indicating that the incorrect word should be replaced always*/ + public static final short REPLACEALL = 3; + /** Field indicating that the incorrect word should be added to the dictionary*/ + public static final short ADDTODICT = 4; + /** Field indicating that the spell checking should be terminated*/ + public static final short CANCEL = 5; + /** Initial case for the action */ + public static final short INITIAL = -1; + + /** Returns the list of suggested Word objects + * @return A list of words phonetically close to the misspelt word + */ + @SuppressWarnings("unchecked") +public List getSuggestions(); + + /** Returns the currently misspelt word + * @return The text misspelt + */ + public String getInvalidWord(); + + /** Returns the context in which the misspelt word is used + * @return The text containing the context + */ + public String getWordContext(); + + /** Returns the start position of the misspelt word in the context + * @return The position of the word + */ + public int getWordContextPosition(); + + /** Returns the action type the user has to handle + * @return The type of action the event is carrying + */ + public short getAction(); + + /** Returns the text to replace + * @return the text of the word to replace + */ + public String getReplaceWord(); + + /** Set the action to replace the currently misspelt word with the new word + * @param newWord The word to replace the currently misspelt word + * @param replaceAll If set to true, the SpellChecker will replace all + * further occurrences of the misspelt word without firing a SpellCheckEvent. + */ + public void replaceWord(String newWord, boolean replaceAll); + + /** Set the action it ignore the currently misspelt word. + * @param ignoreAll If set to true, the SpellChecker will replace all + * further occurrences of the misspelt word without firing a SpellCheckEvent. + */ + public void ignoreWord(boolean ignoreAll); + + /** Set the action to add a new word into the dictionary. This will also replace the + * currently misspelt word. + *@param newWord The new word to add + */ + public void addToDictionary(String newWord); + + /** Set the action to terminate processing of the spell checker. + */ + public void cancel(); +} \ No newline at end of file diff --git a/src/com/swabunga/spell/event/SpellCheckListener.java b/src/com/swabunga/spell/event/SpellCheckListener.java new file mode 100644 index 0000000..f0c9ba8 --- /dev/null +++ b/src/com/swabunga/spell/event/SpellCheckListener.java @@ -0,0 +1,36 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.event; + +import java.util.EventListener; + +/** + * This is the event based listener interface. + * + * @author Jason Height (jheight@chariot.net.au) + */ +public interface SpellCheckListener extends EventListener { + + /** + * Propagates the spelling errors to listeners. + * @param event The event to handle + */ + public void spellingError(SpellCheckEvent event); +} diff --git a/src/com/swabunga/spell/event/SpellChecker.java b/src/com/swabunga/spell/event/SpellChecker.java new file mode 100644 index 0000000..6b24e2e --- /dev/null +++ b/src/com/swabunga/spell/event/SpellChecker.java @@ -0,0 +1,577 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.event; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import com.swabunga.spell.engine.Configuration; +import com.swabunga.spell.engine.SpellDictionary; +import com.swabunga.spell.engine.SpellDictionaryHashMap; +import com.swabunga.spell.engine.Word; +import com.swabunga.util.VectorUtility; + + +/** + * This is the main class for spell checking (using the new event based spell + * checking). + *

+ * By default, the class makes a user dictionary to accumulate added words. + * Since this user directory has no file assign to persist added words, they + * will be retained for the duration of the spell checker instance. + * If you set a user dictionary like + * {@link com.swabunga.spell.engine.SpellDictionaryHashMap SpellDictionaryHashMap} + * to persist the added word, the user dictionary will have the possibility to + * grow and be available across differents invocations of the spell checker. + * + * @author Jason Height (jheight@chariot.net.au) + * 19 June 2002 + */ +public class SpellChecker { + /** Flag indicating that the Spell Check completed without any errors present*/ + public static final int SPELLCHECK_OK = -1; + /** Flag indicating that the Spell Check completed due to user cancellation*/ + public static final int SPELLCHECK_CANCEL = -2; + + @SuppressWarnings("unchecked") +private final Vector eventListeners = new Vector(); + @SuppressWarnings("unchecked") +private final Vector dictionaries = new Vector(); + private SpellDictionary userdictionary; + + private final Configuration config = Configuration.getConfiguration(); + + /**This variable holds all of the words that are to be always ignored */ + @SuppressWarnings("unchecked") +private Vector ignoredWords = new Vector(); + @SuppressWarnings("unchecked") +private Hashtable autoReplaceWords = new Hashtable(); + + // added caching - bd + // For cached operation a separate user dictionary is required + @SuppressWarnings("unchecked") +private Map cache; + private int threshold = 0; + private int cacheSize = 0; + + + /** + * Constructs the SpellChecker. + */ + public SpellChecker() { + try { + userdictionary = new SpellDictionaryHashMap(); + } catch (IOException e) { + throw new RuntimeException("this exception should never happen because we are using null phonetic file"); + } + } + + /** + * Constructs the SpellChecker. The default threshold is used + * + * @param dictionary The dictionary used for looking up words. + */ + public SpellChecker(SpellDictionary dictionary) { + this(); + addDictionary(dictionary); + } + + + /** + * Constructs the SpellChecker with a threshold + * + * @param dictionary the dictionary used for looking up words. + * @param threshold the cost value above which any suggestions are + * thrown away + */ + public SpellChecker(SpellDictionary dictionary, int threshold) { + this(dictionary); + config.setInteger(Configuration.SPELL_THRESHOLD, threshold); + } + + /** + * Accumulates a dictionary at the end of the dictionaries list used + * for looking up words. Adding a dictionary give the flexibility to + * assign the base language dictionary, then a more technical, then... + * + * @param dictionary the dictionary to add at the end of the dictionary list. + */ + @SuppressWarnings("unchecked") +public void addDictionary(SpellDictionary dictionary) { + if (dictionary == null) { + throw new IllegalArgumentException("dictionary must be non-null"); + } + this.dictionaries.addElement(dictionary); + } + + /** + * Registers the user dictionary to which words are added. + * + * @param dictionary the dictionary to use when the user specify a new word + * to add. + */ + public void setUserDictionary(SpellDictionary dictionary) { + userdictionary = dictionary; + } + + /** + * Supply the instance of the configuration holding the spell checking engine + * parameters. + * + * @return Current Configuration + */ + public Configuration getConfiguration() { + return config; + } + + /** + * Adds a SpellCheckListener to the listeners list. + * + * @param listener The feature to be added to the SpellCheckListener attribute + */ + @SuppressWarnings("unchecked") +public void addSpellCheckListener(SpellCheckListener listener) { + eventListeners.addElement(listener); + } + + + /** + * Removes a SpellCheckListener from the listeners list. + * + * @param listener The listener to be removed from the listeners list. + */ + public void removeSpellCheckListener(SpellCheckListener listener) { + eventListeners.removeElement(listener); + } + + + /** + * Fires off a spell check event to the listeners. + * + * @param event The event that need to be processed by the spell checking + * system. + */ + protected void fireSpellCheckEvent(SpellCheckEvent event) { + for (int i = eventListeners.size() - 1; i >= 0; i--) { + ((SpellCheckListener) eventListeners.elementAt(i)).spellingError(event); + } + } + + + /** + * This method clears the words that are currently being remembered as + * Ignore All words and Replace All words. + */ + @SuppressWarnings("unchecked") +public void reset() { + ignoredWords = new Vector(); + autoReplaceWords = new Hashtable(); + } + + + /** + * Checks the text string. + *

+ * Returns the corrected string. + * + * @param text The text that need to be spelled checked + * @return The text after spell checking + * @deprecated use checkSpelling(WordTokenizer) + */ + @Deprecated +public String checkString(String text) { + StringWordTokenizer tokens = new StringWordTokenizer(text); + checkSpelling(tokens); + return tokens.getContext(); + } + + + /** + * Verifies if the word that is being spell checked contains at least a + * digit. + * Returns true if this word contains a digit. + * + * @param word The word to analyze for digit. + * @return true if the word contains at least a digit. + */ + private final static boolean isDigitWord(String word) { + for (int i = word.length() - 1; i >= 0; i--) { + if (Character.isDigit(word.charAt(i))) { + return true; + } + } + return false; + } + + + /** + * Verifies if the word that is being spell checked contains an Internet + * address. The method look for typical protocol or the habitual string + * in the word: + *

+ * + * One limitation is that this method cannot currently recognize email + * addresses. Since the 'word' that is passed in, may in fact contain + * the rest of the document to be checked, it is not (yet!) a good + * idea to scan for the @ character. + * + * @param word The word to analyze for an Internet address. + * @return true if this word looks like an Internet address. + */ + public final static boolean isINETWord(String word) { + String lowerCaseWord = word.toLowerCase(); + return lowerCaseWord.startsWith("http://") || + lowerCaseWord.startsWith("www.") || + lowerCaseWord.startsWith("ftp://") || + lowerCaseWord.startsWith("https://") || + lowerCaseWord.startsWith("ftps://"); + } + + + /** + * Verifies if the word that is being spell checked contains all + * uppercases characters. + * + * @param word The word to analyze for uppercases characters + * @return true if this word contains all upper case characters + */ + private final static boolean isUpperCaseWord(String word) { + for (int i = word.length() - 1; i >= 0; i--) { + if (Character.isLowerCase(word.charAt(i))) { + return false; + } + } + return true; + } + + + /** + * Verifies if the word that is being spell checked contains lower and + * upper cased characters. Note that a phrase beginning with an upper cased + * character is not considered a mixed case word. + * + * @param word The word to analyze for mixed cases characters + * @param startsSentence True if this word is at the start of a sentence + * @return true if this word contains mixed case characters + */ + private final static boolean isMixedCaseWord(String word, boolean startsSentence) { + int strLen = word.length(); + boolean isUpper = Character.isUpperCase(word.charAt(0)); + //Ignore the first character if this word starts the sentence and the first + //character was upper cased, since this is normal behaviour + if ((startsSentence) && isUpper && (strLen > 1)) + isUpper = Character.isUpperCase(word.charAt(1)); + if (isUpper) { + for (int i = word.length() - 1; i > 0; i--) { + if (Character.isLowerCase(word.charAt(i))) { + return true; + } + } + } else { + for (int i = word.length() - 1; i > 0; i--) { + if (Character.isUpperCase(word.charAt(i))) { + return true; + } + } + } + return false; + } + + + /** + * This method will fire the spell check event and then handle the event + * action that has been selected by the user. + * + * @param tokenizer Description of the Parameter + * @param event The event to handle + * @return Returns true if the event action is to cancel the current spell checking, false if the spell checking should continue + */ + @SuppressWarnings("unchecked") +protected boolean fireAndHandleEvent(WordTokenizer tokenizer, SpellCheckEvent event) { + fireSpellCheckEvent(event); + String word = event.getInvalidWord(); + //Work out what to do in response to the event. + switch (event.getAction()) { + case SpellCheckEvent.INITIAL: + break; + case SpellCheckEvent.IGNORE: + break; + case SpellCheckEvent.IGNOREALL: + ignoreAll(word); + break; + case SpellCheckEvent.REPLACE: + tokenizer.replaceWord(event.getReplaceWord()); + break; + case SpellCheckEvent.REPLACEALL: + String replaceAllWord = event.getReplaceWord(); + if (!autoReplaceWords.containsKey(word)) { + autoReplaceWords.put(word, replaceAllWord); + } + tokenizer.replaceWord(replaceAllWord); + break; + case SpellCheckEvent.ADDTODICT: + String addWord = event.getReplaceWord(); + if (!addWord.equals(word)) + tokenizer.replaceWord(addWord); + userdictionary.addWord(addWord); + break; + case SpellCheckEvent.CANCEL: + return true; + default: + throw new IllegalArgumentException("Unhandled case."); + } + return false; + } + + /** + * Adds a word to the list of ignored words + * @param word The text of the word to ignore + */ + @SuppressWarnings("unchecked") +public void ignoreAll(String word) { + if (!ignoredWords.contains(word)) { + ignoredWords.addElement(word); + } + } + + /** + * Adds a word to the user dictionary + * @param word The text of the word to add + */ + public void addToDictionary(String word) { + if (!userdictionary.isCorrect(word)) + userdictionary.addWord(word); + } + + /** + * Indicates if a word is in the list of ignored words + * @param word The text of the word check + */ + public boolean isIgnored(String word){ + return ignoredWords.contains(word); + } + + /** + * Verifies if the word to analyze is contained in dictionaries. The order + * of dictionary lookup is: + * + * + * @param word The word to verify that it's spelling is known. + * @return true if the word is in a dictionary. + */ + @SuppressWarnings("unchecked") +public boolean isCorrect(String word) { + if (userdictionary.isCorrect(word)) return true; + for (Enumeration e = dictionaries.elements(); e.hasMoreElements();) { + SpellDictionary dictionary = (SpellDictionary) e.nextElement(); + if (dictionary.isCorrect(word)) return true; + } + return false; + } + + /** + * Produces a list of suggested word after looking for suggestions in various + * dictionaries. The order of dictionary lookup is: + * + * + * @param word The word for which we want to gather suggestions + * @param threshold the cost value above which any suggestions are + * thrown away + * @return the list of words suggested + */ + @SuppressWarnings("unchecked") +public List getSuggestions(String word, int threshold) { + if (this.threshold != threshold && cache != null) { + this.threshold = threshold; + cache.clear(); + } + + ArrayList suggestions = null; + + if (cache != null) + suggestions = (ArrayList) cache.get(word); + + if (suggestions == null) { + suggestions = new ArrayList(50); + + for (Enumeration e = dictionaries.elements(); e.hasMoreElements();) { + SpellDictionary dictionary = (SpellDictionary) e.nextElement(); + + if (dictionary != userdictionary) + VectorUtility.addAll(suggestions, dictionary.getSuggestions(word, threshold), false); + } + + if (cache != null && cache.size() < cacheSize) + cache.put(word, suggestions); + } + + VectorUtility.addAll(suggestions, userdictionary.getSuggestions(word, threshold), false); + suggestions.trimToSize(); + + return suggestions; + } + + /** + * Activates a cache with the maximum number of entries set to 300 + */ + public void setCache() { + setCache(300); + } + + /** + * Activates a cache with specified size + * @param size - max. number of cache entries (0 to disable chache) + */ + @SuppressWarnings("unchecked") +public void setCache(int size) { + cacheSize = size; + if (size == 0) + cache = null; + else + cache = new HashMap((size + 2) / 3 * 4); + } + + /** + * This method is called to check the spelling of the words that are returned + * by the WordTokenizer. + *

+ * For each invalid word the action listeners will be informed with a new + * SpellCheckEvent.

+ * + * @param tokenizer The media containing the text to analyze. + * @return Either SPELLCHECK_OK, SPELLCHECK_CANCEL or the number of errors found. The number of errors are those that + * are found BEFORE any corrections are made. + */ + @SuppressWarnings("unchecked") +public final int checkSpelling(WordTokenizer tokenizer) { + int errors = 0; + boolean terminated = false; + //Keep track of the previous word +// String previousWord = null; + while (tokenizer.hasMoreWords() && !terminated) { + String word = tokenizer.nextWord(); + //Check the spelling of the word + if (!isCorrect(word)) { + if ((config.getBoolean(Configuration.SPELL_IGNOREMIXEDCASE) && isMixedCaseWord(word, tokenizer.isNewSentence())) || + (config.getBoolean(Configuration.SPELL_IGNOREUPPERCASE) && isUpperCaseWord(word)) || + (config.getBoolean(Configuration.SPELL_IGNOREDIGITWORDS) && isDigitWord(word)) || + (config.getBoolean(Configuration.SPELL_IGNOREINTERNETADDRESSES) && isINETWord(word))) { + //Null event. Since we are ignoring this word due + //to one of the above cases. + } else { + //We cant ignore this misspelt word + //For this invalid word are we ignoring the misspelling? + if (!isIgnored(word)) { + errors++; + //Is this word being automagically replaced + if (autoReplaceWords.containsKey(word)) { + tokenizer.replaceWord((String) autoReplaceWords.get(word)); + } else { + //JMH Need to somehow capitalise the suggestions if + //ignoreSentenceCapitalisation is not set to true + //Fire the event. + List suggestions = getSuggestions(word, config.getInteger(Configuration.SPELL_THRESHOLD)); + if (capitalizeSuggestions(word, tokenizer)) + suggestions = makeSuggestionsCapitalized(suggestions); + SpellCheckEvent event = new BasicSpellCheckEvent(word, suggestions, tokenizer); + terminated = fireAndHandleEvent(tokenizer, event); + } + } + } + } else { + //This is a correctly spelt word. However perform some extra checks + /* + * JMH TBD //Check for multiple words + * if (!ignoreMultipleWords &&) { + * } + */ + //Check for capitalisation + if (isSupposedToBeCapitalized(word, tokenizer)) { + errors++; + StringBuffer buf = new StringBuffer(word); + buf.setCharAt(0, Character.toUpperCase(word.charAt(0))); + Vector suggestion = new Vector(); + suggestion.addElement(new Word(buf.toString(), 0)); + SpellCheckEvent event = new BasicSpellCheckEvent(word, suggestion, tokenizer); + terminated = fireAndHandleEvent(tokenizer, event); + } + } + } + if (terminated) + return SPELLCHECK_CANCEL; + else if (errors == 0) + return SPELLCHECK_OK; + else + return errors; + } + + + @SuppressWarnings("unchecked") +private List makeSuggestionsCapitalized(List suggestions) { + Iterator iterator = suggestions.iterator(); + while(iterator.hasNext()) { + Word word = (Word)iterator.next(); + String suggestion = word.getWord(); + StringBuffer stringBuffer = new StringBuffer(suggestion); + stringBuffer.setCharAt(0, Character.toUpperCase(suggestion.charAt(0))); + word.setWord(stringBuffer.toString()); + } + return suggestions; + } + + + private boolean isSupposedToBeCapitalized(String word, WordTokenizer wordTokenizer) { + boolean configCapitalize = !config.getBoolean(Configuration.SPELL_IGNORESENTENCECAPITALIZATION); + return configCapitalize && wordTokenizer.isNewSentence() && Character.isLowerCase(word.charAt(0)); + } + + private boolean capitalizeSuggestions(String word, WordTokenizer wordTokenizer) { + // if SPELL_IGNORESENTENCECAPITALIZATION and the initial word is capitalized, suggestions should also be capitalized + // if !SPELL_IGNORESENTENCECAPITALIZATION, capitalize suggestions only for the first word in a sentence + boolean configCapitalize = !config.getBoolean(Configuration.SPELL_IGNORESENTENCECAPITALIZATION); + boolean uppercase = Character.isUpperCase(word.charAt(0)); + return (configCapitalize && wordTokenizer.isNewSentence()) || (!configCapitalize && uppercase); + } +} diff --git a/src/com/swabunga/spell/event/StringWordTokenizer.java b/src/com/swabunga/spell/event/StringWordTokenizer.java new file mode 100644 index 0000000..7f9ca70 --- /dev/null +++ b/src/com/swabunga/spell/event/StringWordTokenizer.java @@ -0,0 +1,91 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.event; + + +/** + * This class tokenizes a input string. + * + *

+ * It also allows for the string to be altered by calls to replaceWord(). The result after the spell + * checking is completed is available to the call to getContext. + *

+ * + * @author Jason Height (jheight@chariot.net.au) + * @author Anthony Roy (ajr@antroy.co.uk) + */ +public class StringWordTokenizer extends AbstractWordTokenizer { + + //~ Constructors ............................................................ + + /** + * Creates a new StringWordTokenizer object. + * + * @param s the string to tokenize. + */ + public StringWordTokenizer(String s) { + super(s); + } + + /** + * Creates a new StringWordTokenizer object. + * + * @param wf the custom WordFinder to use in tokenizing. Note + * that the string to tokenize will be encapsulated within the WordFinder. + */ + public StringWordTokenizer(WordFinder wf) { + super(wf); + } + + /** + * Creates a new StringWordTokenizer object. + * @param s the string to work on + * @param finder the custom WordFinder to use in tokenizing. Note + * that the string to tokenize will be encapsulated within the WordFinder. + */ + public StringWordTokenizer(String s, WordFinder finder) { + super(finder); + finder.setText(s); + } + + + //~ Methods ................................................................. + + /** + * + * @deprecated use getContext() instead as per the WordTokenizer + * interface specification. + * @return the final text. + */ + public String getFinalText() { + + return getContext(); + } + + /** + * Replace the current word in the iteration with the String s. + * + * @param s the String to replace the current word. + * @throws WordNotFoundException current word not yet set. + */ + public void replaceWord(String s) { + finder.replace(s); + } +} \ No newline at end of file diff --git a/src/com/swabunga/spell/event/TeXWordFinder.java b/src/com/swabunga/spell/event/TeXWordFinder.java new file mode 100644 index 0000000..c347a74 --- /dev/null +++ b/src/com/swabunga/spell/event/TeXWordFinder.java @@ -0,0 +1,193 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +//{{{ package and imports +//:folding=explicit: +package com.swabunga.spell.event; + +import java.util.Collection; +import java.util.HashSet; + +/** + * A word finder for TeX and LaTeX documents, which searches text for + * sequences of letters, but ignores any commands and environments as well + * as Math environments. + * + * @author Anthony Roy (ajr@antroy.co.uk) + */ + +//}}} + +public class TeXWordFinder extends AbstractWordFinder { + +//{{{ ~ Instance/static variables ............................................... + + @SuppressWarnings("unused") +private boolean IGNORE_COMMENTS = true; + @SuppressWarnings("unchecked") +private final HashSet user_defined_ignores = new HashSet(); + @SuppressWarnings("unused") +private int regex_user_defined_ignores = STRING_EXPR; + /** + * A type where string expressions are used to define expression to ignore + */ + public static final int STRING_EXPR = 0; + /** + * A type where regular expressions are used to define expression to ignore + */ + public static final int REG_EXPR = 1; +// public static final int GLOB_EXPR = 2; +//}}} +//{{{ ~ Constructors ............................................................ + + /** + * Creates a new DefaultWordFinder object. + * + * @param inText the text to search. + */ + public TeXWordFinder(String inText) { + super(inText); + } + + /** + * Creates a new DefaultWordFinder object. + */ + public TeXWordFinder() { + super(); + } +//}}} +//{{{ ~ Methods ................................................................. + + /** + * This method scans the text from the end of the last word, and returns a + * new Word object corresponding to the next word. + * + * @return the next word. + * @throws WordNotFoundException search string contains no more words. + */ + @Override +public Word next() { +//{{{ + + if (!hasNext())//currentWord == null) + throw new WordNotFoundException("No more words found."); + + currentWord.copy(nextWord); + setSentenceIterator(currentWord); + + + int i = currentWord.getEnd(); + boolean finished = false; + boolean started = false; + + search: + while (i < text.length() && !finished) { + +//{{{ Find words. + if (!started && isWordChar(i)) { + nextWord.setStart(i++); + started = true; + continue search; + } else if (started) { + if (isWordChar(i)) { + i++; + continue search; + } else { + nextWord.setText(text.substring(nextWord.getStart(), i)); + finished = true; + break search; + } + } //}}} +// Ignores should be in order of importance and then specificity. + int j = i; +// Ignore Comments: + j = ignore(j, '%', '\n'); + +// Ignore Maths: + j = ignore(j, "$$", "$$"); + j = ignore(j, '$', '$'); + +// Ignore user defined. + j = ignoreUserDefined(j); + +// Ignore certain command parameters. + j = ignore(j, "\\newcommand", "}"); + j = ignore(j, "\\documentclass", "}"); + j = ignore(j, "\\usepackage", "}"); + j = ignore(j, "\\newcounter{", "}"); + j = ignore(j, "\\setcounter{", "}"); + j = ignore(j, "\\addtocounter{", "}"); + j = ignore(j, "\\value{", "}"); + j = ignore(j, "\\arabic{", "}"); + j = ignore(j, "\\usecounter{", "}"); + j = ignore(j, "\\newenvironment", "}"); + j = ignore(j, "\\setlength", "}"); + j = ignore(j, "\\setkeys", "}"); + +// Ignore environment names. + j = ignore(j, "\\begin{", "}"); + j = ignore(j, "\\end{", "}"); + if (i != j){ + i = j; + continue search; + } + +// Ignore commands. + j = ignore(j, '\\'); + + if (i != j){ + i = j; + continue search; + } + i++; + } + + if (!started) { + nextWord = null; + } else if (!finished) { + nextWord.setText(text.substring(nextWord.getStart(), i)); + } + + return currentWord; + } +//}}} + /** + * This method is used to import a user defined set of either strings or regular expressions to ignore. + * @param expressions a collection of Objects whose toString() value should be the expression. Typically String objects. + * @param regex is an integer specifying the type of expression to use. e.g. REG_EXPR, STRING_EXPR. + */ + @SuppressWarnings("unchecked") +public void addUserDefinedIgnores(Collection expressions, int regex){ + user_defined_ignores.addAll(expressions); + regex_user_defined_ignores = regex; + } + + private int ignoreUserDefined(int i){ + return i; + } + + /** + * Define if comments contents are ignored during spell checking + * @param ignore an indication if comments content is to be ignored + */ + public void setIgnoreComments(boolean ignore) { + IGNORE_COMMENTS = ignore; + } +//}}} +} diff --git a/src/com/swabunga/spell/event/Word.java b/src/com/swabunga/spell/event/Word.java new file mode 100644 index 0000000..54b5902 --- /dev/null +++ b/src/com/swabunga/spell/event/Word.java @@ -0,0 +1,141 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.event; + +/** + * Offers basic methods to manipulate a text string representing a word. + */ +public class Word { + + //~ Instance/static variables ............................................... + + private int end; + private int start; + private String text; + + //~ Constructors ............................................................ + + /** + * Creates a new Word object. + * + * @param text the String representing the word. + * @param start the start index of the word. + */ + public Word(String text, int start) { + this.text = text; + this.start = start; + setEnd(); + } + + /** + * Creates a new Word object by cloning an existing Word object. + * + * @param w the word object to clone. + */ + public Word(Word w) { + this.copy(w); + } + + //~ Methods ................................................................. + + /** + * Evaluate the end of word position. + * @return the end index of the word. + */ + public int getEnd() { + + return end; + } + + /** + * Set the start index of the word. + * + * @param s the start index. + */ + public void setStart(int s) { + start = s; + setEnd(); + } + + /** + * Evaluate the start of word position. + * @return the start index. + */ + public int getStart() { + + return start; + } + + /** + * Set the text to a new string value. + * + * @param s the new text + */ + public void setText(String s) { + text = s; + setEnd(); + } + + /** + * Supply the text string representing the word + * @return the String representing the word. + */ + public String getText() { + + return text; + } + + /** + * Sets the value of this Word to be a copy of another. + * + * @param w the Word to copy. + */ + public void copy(Word w) { + text = w.toString(); + start = w.getStart(); + setEnd(); + } + + /** + * Evaluate the length of the word. + * @return the length of the word. + */ + public int length() { + + return text.length(); + } + + /** + * Supply the text representing the word. + * @return the text representing the word. + */ + public String toString() { + + return text; + } + + /** + * Set the end index of the word. + * + */ + private void setEnd() { + end = start + text.length(); + } +} diff --git a/src/com/swabunga/spell/event/WordFinder.java b/src/com/swabunga/spell/event/WordFinder.java new file mode 100644 index 0000000..a8d01e3 --- /dev/null +++ b/src/com/swabunga/spell/event/WordFinder.java @@ -0,0 +1,102 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.event; + +/** + *

An interface for objects which take a String as input, and iterates through + * the words in the string. + *

+ * + *

+ * When the object is instantiated, and before the first call to next() is made, + * the following methods should throw a WordNotFoundException:
+ * current(), + * startsSentence() and replace(). + *

+ * + *

A call to next() when hasMoreWords() returns false + * should throw a WordNotFoundException.

+ * @author Jason Height (jheight@chariot.net.au) + */ + +public interface WordFinder { + + //~ Methods ................................................................. + + /** + * This method returns the text through which the WordFinder is iterating. + * The text may have been modified through calls to replace(). + * + * @return the (possibly modified) text being searched. + */ + public String getText(); + + /** + * This method resets the text through which the WordFinder iterates. + * It must also re-initialize the WordFinder. + * + * @param newText the new text to search. + */ + public void setText(String newText); + + /** + * This method should return the Word object representing the current word + * in the iteration. + * This method should not affect the state of the WordFinder object. + * + * @return the current Word object. + * @throws WordNotFoundException current word has not yet been set. + */ + public Word current(); + + /** + * Tests the finder to see if any more words are available. + * + * @return true if more words are available. + */ + public boolean hasNext(); + + /** + * This method should return the Word object representing the next word + * in the iteration (the first word if next() has not yet been called.) + * + * @return the next Word in the iteration. + * @throws WordNotFoundException search string contains no more words. + */ + public Word next(); + + /** + * This method should replace the current Word object with a Word object + * representing the String newWord. + * + * @param newWord the word to replace the current word with. + * @throws WordNotFoundException current word has not yet been set. + */ + public void replace(String newWord); + + /** + * Indicates if the current word starts a new sentence. + * @return true if the current word starts a new sentence. + * @throws WordNotFoundException current word has not yet been set. + */ + public boolean startsSentence(); + + // public void setText(); +} diff --git a/src/com/swabunga/spell/event/WordNotFoundException.java b/src/com/swabunga/spell/event/WordNotFoundException.java new file mode 100644 index 0000000..6fec052 --- /dev/null +++ b/src/com/swabunga/spell/event/WordNotFoundException.java @@ -0,0 +1,45 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.event; + +/** + * An exception to indicate that there not enough words as expected. + */ +@SuppressWarnings("serial") +public class WordNotFoundException extends RuntimeException { + + //~ Constructors ............................................................ + + /** + * Creates a new WordNotFoundException object. + */ + public WordNotFoundException() { + super(); + } + + /** + * Creates a new WordNotFoundException object. + * + * @param s a message. + */ + public WordNotFoundException(String s) { + super(s); + } +} diff --git a/src/com/swabunga/spell/event/WordTokenizer.java b/src/com/swabunga/spell/event/WordTokenizer.java new file mode 100644 index 0000000..913ec6c --- /dev/null +++ b/src/com/swabunga/spell/event/WordTokenizer.java @@ -0,0 +1,105 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.event; + +/** + *

An interface for objects which take a text-based media as input, and iterate through + * the words in the text stored in that media. Examples of such media could be Strings, + * Documents, Files, TextComponents etc. + *

+ * + *

+ * When the object is instantiated, and before the first call to next() is made, + * the following methods should throw a WordNotFoundException:
+ * getCurrentWordEnd(), getCurrentWordPosition(), + * isNewSentence() and replaceWord(). + *

+ * + *

A call to next() when hasMoreWords() returns false + * should throw a WordNotFoundException.

+ * @author Jason Height (jheight@chariot.net.au) + */ +public interface WordTokenizer { + + //~ Methods ................................................................. + + /** + * Returns the context text that is being tokenized (should include any + * changes that have been made). + * @return the text being searched. + */ + public String getContext(); + + /** + * Returns the number of word tokens that have been processed thus far + * @return the number of words found so far. + */ + public int getCurrentWordCount(); + + /** + * Returns an index representing the end location of the current word in the text. + * @return index of the end of the current word in the text. + * @throws WordNotFoundException current word has not yet been set. + */ + public int getCurrentWordEnd(); + + /** + * Returns an index representing the start location of the current word in the text. + * @return index of the start of the current word in the text. + * @throws WordNotFoundException current word has not yet been set. + */ + public int getCurrentWordPosition(); + + /** + * Returns true if the current word is at the start of a sentence + * @return true if the current word starts a sentence. + * @throws WordNotFoundException current word has not yet been set. + */ + public boolean isNewSentence(); + + /** + * Indicates if there are more words left + * @return true if more words can be found in the text. + */ + public boolean hasMoreWords(); + + /** + * This returns the next word in the iteration. Note that any implementation should return + * the current word, and then replace the current word with the next word found in the + * input text (if one exists). + * @return the next word in the iteration. + * @throws WordNotFoundException search string contains no more words. + */ + public String nextWord(); + + /** + * Replaces the current word token + * + *

+ * When a word is replaced care should be taken that the WordTokenizer + * repositions itself such that the words that were added aren't rechecked. + * Of course this is not mandatory, maybe there is a case when an + * application doesn't need to do this. + *

+ * @param newWord the string which should replace the current word. + * @throws WordNotFoundException current word has not yet been set. + */ + public void replaceWord(String newWord); +} \ No newline at end of file diff --git a/src/com/swabunga/spell/event/XMLWordFinder.java b/src/com/swabunga/spell/event/XMLWordFinder.java new file mode 100644 index 0000000..2098983 --- /dev/null +++ b/src/com/swabunga/spell/event/XMLWordFinder.java @@ -0,0 +1,97 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +//:folding=indent: +package com.swabunga.spell.event; + + +/** + * A word finder for XML or HTML documents, which searches text for sequences + * of letters, but ignores the text inside any tags. + * + * @author Anthony Roy (ajr@antroy.co.uk) + */ +public class XMLWordFinder extends AbstractWordFinder { + + //~ Instance/static variables ............................................... + + //~ Constructors ............................................................ + + /** + * Creates a new DefaultWordFinder object. + * + * @param inText the text to search. + */ + public XMLWordFinder(String inText) { + super(inText); + } + + //~ Methods ................................................................. + + /** + * This method scans the text from the end of the last word, and returns a + * new Word object corresponding to the next word. + * + * @return the next word. + * @throws WordNotFoundException search string contains no more words. + */ + public Word next() { + + if (currentWord == null) + throw new WordNotFoundException("No more words found."); + + currentWord.copy(nextWord); + + setSentenceIterator(currentWord); + + int i = currentWord.getEnd(); + boolean finished = false; + boolean started = false; + + search: /* Find words. */ + while (i < text.length() && !finished) { + if (!started && isWordChar(i)) { + nextWord.setStart(i++); + started = true; + continue search; + } else if (started) { + if (isWordChar(i)) { + i++; + continue search; + } else { + nextWord.setText(text.substring(nextWord.getStart(), i)); + finished = true; + break search; + } + } + + //Ignore things inside tags. + int i2 = ignore(i, '<', '>'); + i = (i2 == i ? i + 1 : i2); + } + + if (!started) { + nextWord = null; + } else if (!finished) { + nextWord.setText(text.substring(nextWord.getStart(), i)); + } + + return currentWord; + } +} diff --git a/src/com/swabunga/spell/swing/autospell/AutoSpellCheckHandler.java b/src/com/swabunga/spell/swing/autospell/AutoSpellCheckHandler.java new file mode 100644 index 0000000..5727bee --- /dev/null +++ b/src/com/swabunga/spell/swing/autospell/AutoSpellCheckHandler.java @@ -0,0 +1,318 @@ +/* +Jazzy - a Java library for Spell Checking +Copyright (C) 2001 Mindaugas Idzelis +Full text of license can be found in LICENSE.txt + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +package com.swabunga.spell.swing.autospell; + +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ResourceBundle; + +import javax.swing.JEditorPane; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.AttributeSet; +import javax.swing.text.Document; +import javax.swing.text.Element; +import javax.swing.text.Segment; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyledDocument; + +import com.swabunga.spell.engine.Configuration; +import com.swabunga.spell.event.DocumentWordTokenizer; +import com.swabunga.spell.event.SpellChecker; + +/** + * This class handles the actual autospelling by implementing some listeners + * on the spellchecked JEditorPane and Document. + * + * @author Robert Gustavsson (robert@lindesign.se) + * + */ +public class AutoSpellCheckHandler extends MouseAdapter implements DocumentListener, + AutoSpellConstants{ + + private SpellChecker sCheck=null; + private final Configuration config = Configuration.getConfiguration(); + private ResourceBundle messages=null; + + public AutoSpellCheckHandler(SpellChecker sc){ + sCheck=sc; + } + + public AutoSpellCheckHandler(SpellChecker sc, ResourceBundle rs){ + this(sc); + messages=rs; + } + + public void addJEditorPane(JEditorPane pane){ + StyledDocument doc=(StyledDocument)pane.getDocument(); + markupSpelling(doc, 0, doc.getLength()-1); + doc.addDocumentListener(this); + pane.addMouseListener(this); + } + + public void removeJEditorPane(JEditorPane pane){ + Document doc=pane.getDocument(); + pane.removeMouseListener(this); + doc.removeDocumentListener(this); + } + + private void markupSpelling(StyledDocument doc, int start, int end){ + int wordStart=-1, + wordEnd=-1; + String word; + DocumentWordTokenizer docTok; + @SuppressWarnings("unused") + Segment seg=new Segment(); + + docTok=new DocumentWordTokenizer(doc); + if(start>0){ + docTok.posStartFullWordFrom(start); + } + + while(docTok.hasMoreWords() && docTok.getCurrentWordPosition()<=end){ + word=docTok.nextWord(); + wordStart=docTok.getCurrentWordPosition(); + + // Mark non word parts (spaces) as correct + if(wordEnd!=-1){ + //System.out.println("Space:"+wordEnd+","+wordStart); + markAsCorrect(doc, wordEnd, wordStart); + } + wordEnd=docTok.getCurrentWordEnd(); + + if(wordEnd>doc.getLength()) + wordEnd=doc.getLength()-1; + if(wordStart>=wordEnd) + continue; + //System.out.println("Word:"+wordStart+","+wordEnd); + if(sCheck.isCorrect(word) || sCheck.isIgnored(word)){ + markAsCorrect(doc, wordStart, wordEnd); + }else{ + markAsMisspelled(doc, wordStart, wordEnd); + } + } + // Mark the rest (if any) as correct. + if(wordEnd=start) + doc.setCharacterAttributes(start, end-start, attr, true); + } + + private void handleDocumentChange(DocumentEvent evt){ + Element curElem, + parElem; + StyledDocument doc; + int start, + end; + + if(evt.getDocument() instanceof StyledDocument){ + doc=(StyledDocument)evt.getDocument(); + curElem=doc.getCharacterElement(evt.getOffset()); + parElem=curElem.getParentElement(); + if(parElem!=null){ + start=parElem.getStartOffset(); + end=parElem.getEndOffset(); + }else{ + start=curElem.getStartOffset(); + end=curElem.getEndOffset(); + } + //System.out.println("curElem: "+curElem.getStartOffset()+", "+curElem.getEndOffset()); + //System.out.println("parElem: "+parElem.getStartOffset()+", "+parElem.getEndOffset()); + //System.out.println("change: "+start+", "+end); + markupSpelling(doc,start, end); + } + } + + @SuppressWarnings("unchecked") + private void showSuggestionPopup(JEditorPane pane, Point p){ + StyledDocument doc; + JMenuItem item; + AttributeSet attr; + int pos = pane.viewToModel(p); + DocumentWordTokenizer docTok; + String word; + java.util.List suggestions; + JPopupMenu popup; + ReplaceListener repList; + + if (pos >= 0) { + doc=(StyledDocument)pane.getDocument(); + attr=doc.getCharacterElement(pos).getAttributes(); + if(attr.containsAttribute(wordMisspelled, wordMisspelledTrue)){ + docTok=new DocumentWordTokenizer(doc); + docTok.posStartFullWordFrom(pos); + word=docTok.nextWord(); + suggestions=sCheck.getSuggestions(word, config.getInteger(Configuration.SPELL_THRESHOLD)); + + popup=new JPopupMenu(); + repList=new ReplaceListener(docTok); + for(int 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 epk=yBs4BieE9v3Gt literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/Global.java b/src/cx/fbn/nevernote/Global.java new file mode 100644 index 0000000..11f2106 --- /dev/null +++ b/src/cx/fbn/nevernote/Global.java @@ -0,0 +1,1137 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote; + + +//import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; + +import com.evernote.edam.type.Accounting; +import com.evernote.edam.type.PrivilegeLevel; +import com.evernote.edam.type.User; +import com.evernote.edam.type.UserAttributes; +import com.trolltech.qt.core.QByteArray; +import com.trolltech.qt.core.QMutex; +import com.trolltech.qt.core.QSettings; +import com.trolltech.qt.gui.QPalette; + +import cx.fbn.nevernote.gui.ContainsAttributeFilterTable; +import cx.fbn.nevernote.gui.DateAttributeFilterTable; +import cx.fbn.nevernote.gui.ShortcutKeys; +import cx.fbn.nevernote.signals.DBRunnerSignal; +import cx.fbn.nevernote.threads.DBRunner; +import cx.fbn.nevernote.utilities.ApplicationLogger; + +public class Global { + public static String version = "0.88"; + public static String username = ""; + public static String password = ""; + + public static DBRunner dbRunner; // Database thread + public static DBRunnerSignal dbRunnerSignal; // Signals to the database runner + public static QMutex dbrunnerWorkLock; // mutex lock for work queue + + + public static int mainThreadId=0; + private static ArrayBlockingQueue mainThreadWaiter = new ArrayBlockingQueue(1); + + public static int syncThreadId=1; + private static ArrayBlockingQueue syncThreadWaiter = new ArrayBlockingQueue(1); + + public static int tagCounterThreadId=2; + private static ArrayBlockingQueue tagCounterThreadWaiter = new ArrayBlockingQueue(1); + + public static int trashCounterThreadId=3; // This should always be the highest thread ID + private static ArrayBlockingQueue trashCounterThreadWaiter = new ArrayBlockingQueue(1); + + public static int indexThreadId=4; // Thread for indexing words + private static ArrayBlockingQueue indexThreadWaiter = new ArrayBlockingQueue(1); + + public static int saveThreadId=5; // Thread used for processing data to saving content + private static ArrayBlockingQueue saveThreadWaiter = new ArrayBlockingQueue(1); + + public static int notebookCounterThreadId=6; // Notebook Thread + private static ArrayBlockingQueue notebookCounterThreadWaiter = new ArrayBlockingQueue(1); + + public static int indexThread03Id=7; // unused + private static ArrayBlockingQueue indexThread03ThreadWaiter = new ArrayBlockingQueue(1); + + public static int indexThread04Id=8; // unused + private static ArrayBlockingQueue indexThread04ThreadWaiter = new ArrayBlockingQueue(1); + + public static int dbThreadId=9; // This should always be the highest thread ID + + + public static HashMap passwordSafe = new HashMap(); + public static List passwordRemember = new ArrayList(); + public static String currentNotebookGuid; + public static User user; + public static long authTimeRemaining; + public static long authRefreshTime; + public static long failedRefreshes = 0; + public static String currentDir; + public static boolean keepRunning; + + public static String userStoreUrl; + public static String noteStoreUrl; + public static String noteStoreUrlBase; + + public static int noteTableCreationPosition = 0; + public static int noteTableTitlePosition = 1; + public static int noteTableTagPosition = 2; + public static int noteTableNotebookPosition = 3; + public static int noteTableChangedPosition = 4; + public static int noteTableGuidPosition = 5; + public static int noteTableAuthorPosition = 6; + public static int noteTableSourceUrlPosition = 7; + public static int noteTableSubjectDatePosition = 8; + public static int noteTableSynchronizedPosition = 9; + public static int noteTableColumnCount = 10; + public static Integer cryptCounter = 0; + + public static int minimumWordCount = 2; + private static String wordRegex; + public static boolean enableCarriageReturnFix = false; + + public static String name = null; + public static QSettings settings; + public static boolean isConnected; + public static boolean showDeleted = false; + public static boolean disableUploads = false; + public static int messageLevel; + public static String tagDelimeter = ","; + public static String attachmentNameDelimeter = "------"; + + public static String databaseName = new String("NeverNote"); + public static String indexDatabaseName = new String("IndexDatabase.db"); + public static DateAttributeFilterTable createdSinceFilter; + public static DateAttributeFilterTable createdBeforeFilter; + public static DateAttributeFilterTable changedSinceFilter; + public static DateAttributeFilterTable changedBeforeFilter; + public static ContainsAttributeFilterTable containsFilter; +// public static DBLock dbLock; +// public static DBLock indexLock; + public static ApplicationLogger logger; + PrintStream stdoutStream; + public static QPalette originalPalette; + public static ShortcutKeys shortcutKeys; + public static boolean disableViewing = false; + + public static List invalidElements = new ArrayList(); + public static HashMap> invalidAttributes = new HashMap>(); + public static boolean mimicEvernoteInterface; + public static HashMap resourceMap; + public static String cipherPassword = ""; + + static Calendar startTraceTime; + static Calendar intervalTraceTime; + + // Do initial setup + public static void setup() { + if (name == null) + name = "NeverNote"; + settings = new QSettings("fbn.cx", name); + currentDir = getDirectoryPath(); + getServer(); + settings.beginGroup("General"); + String regex = (String) settings.value("regex", "[,\\s]+"); + setWordRegex(regex); + String wordString = settings.value("wordLength", "4").toString(); + Integer wordLen = new Integer(wordString); + Global.minimumWordCount = wordLen; + settings.endGroup(); + settings.beginGroup("Debug"); + String msglevel = (String) settings.value("messageLevel", "Low"); + settings.endGroup(); + messageLevel = 1; + setMessageLevel(msglevel); + keepRunning = true; + disableUploads = disableUploads(); + enableCarriageReturnFix = enableCarriageReturnFix(); +// dbLock = new DBLock(); +// indexLock = new DBLock(); + logger = new ApplicationLogger("global.log"); + shortcutKeys = new ShortcutKeys(); + dbrunnerWorkLock = new QMutex(); + mimicEvernoteInterface = getMimicEvernoteInterface(); + resourceMap = new HashMap(); + + } + public static void setName(String n) { + if (!n.trim().equals("")) { + name = "NeverNote-"+n; + } + } + public static String getDirectoryPath() { + if (currentDir == null) { + currentDir = System.getProperty("user.dir"); + } + if (!currentDir.substring(currentDir.length()-1).equals(File.separator)) { + currentDir = currentDir+File.separator; + } + return currentDir; + } + public static void setDirectoryPath(String path) { + if (path.trim().equals("")) + path = System.getProperty("user.dir"); + if (!path.substring(path.length()-1).equals(File.separator)) + path = path+File.separator; + currentDir = path; + } + public static String getWordRegex() { + return wordRegex; + } + public static void setWordRegex(String r) { + wordRegex = r; + } + public static void setMessageLevel(String msglevel) { + if (msglevel.equalsIgnoreCase("low")) + messageLevel = 1; + if (msglevel.equalsIgnoreCase("medium")) + messageLevel = 2; + if (msglevel.equalsIgnoreCase("high")) + messageLevel = 3; + if (msglevel.equalsIgnoreCase("extreme")) + messageLevel = 4; + settings.beginGroup("Debug"); + settings.setValue("messageLevel", msglevel); + settings.endGroup(); + } + + public static void saveUserInformation(User user) { + settings.beginGroup("User"); + settings.setValue("id", user.getId()); + settings.setValue("username", user.getUsername()); + settings.setValue("email", user.getEmail()); + settings.setValue("name", user.getName()); + settings.setValue("timezone", user.getTimezone()); + settings.setValue("privilege", user.getPrivilege().getValue()); + settings.setValue("created", user.getCreated()); + settings.setValue("updated", user.getUpdated()); + settings.setValue("deleted", user.getDeleted()); + settings.endGroup(); + isPremium(); + if (user.getAttributes()!=null) + saveUserAttributes(user.getAttributes()); + if (user.getAccounting()!=null) + saveUserAccounting(user.getAccounting()); + + } + public static void saveUserAttributes(UserAttributes attrib) { + settings.beginGroup("UserAttributes"); + settings.setValue("defaultLocationName", attrib.getDefaultLocationName()); + settings.setValue("defaultLatitude", attrib.getDefaultLocationName()); + settings.setValue("defaultLongitude", attrib.getDefaultLocationName()); + settings.setValue("incomingEmailAddress", attrib.getIncomingEmailAddress()); + settings.endGroup(); + } + public static UserAttributes getUserAttributes() { + settings.beginGroup("UserAttributes"); + UserAttributes attrib = new UserAttributes(); + attrib.setDefaultLocationName((String)settings.value("defaultLocationName","")); + attrib.setDefaultLatitudeIsSet(false); + attrib.setDefaultLongitudeIsSet(false); + attrib.setIncomingEmailAddress((String)settings.value("incomingEmailAddress", "")); + settings.endGroup(); + return attrib; + } + public static void saveUserAccounting(Accounting acc) { + settings.beginGroup("UserAccounting"); + settings.setValue("uploadLimit", acc.getUploadLimit()); + settings.setValue("uploadLimitEnd", acc.getUploadLimitEnd()); + settings.setValue("uploadLimitNextMonth", acc.getUploadLimitNextMonth()); + settings.setValue("premiumServiceStart", acc.getPremiumServiceStart()); + settings.setValue("nextPaymentDue", acc.getNextPaymentDue()); + settings.setValue("uploadAmount", acc.getUpdated()); + settings.endGroup(); + } + public static long getUploadLimitEnd() { + Long limit; + settings.beginGroup("UserAccounting"); + + // Upload limit + try { + String val = (String)settings.value("uploadLimitEnd", "0"); + limit = new Long(val.trim()); + } catch (Exception e) { + try { + limit = (Long)settings.value("uploadLimitEnd", 0); + } catch (Exception e1) { + limit = new Long(0); + } + } + + // return value + settings.endGroup(); + return limit; + } + public static void saveUploadAmount(long amount) { + settings.beginGroup("UserAccounting"); + settings.setValue("uploadAmount", amount); + settings.endGroup(); + } + public static long getUploadAmount() { + long amt=0; + settings.beginGroup("UserAccounting"); + try { + String num = (String)settings.value("uploadAmount", "0"); + amt = new Long(num.trim()); + } catch (Exception e) { + try { + amt = (Integer)settings.value("uploadAmount", 0); + } catch (Exception e1) { + amt = 0; + } + } + settings.endGroup(); + return amt; + } + public static void saveEvernoteUpdateCount(long amount) { + settings.beginGroup("UserAccounting"); + settings.setValue("updateCount", amount); + settings.endGroup(); + } + public static long getEvernoteUpdateCount() { + long amt; + settings.beginGroup("UserAccounting"); + try { + String num = (String)settings.value("updateCount", new Long(0).toString()); + amt = new Long(num.trim()); + } catch (java.lang.ClassCastException e) { + amt = 0; + } + settings.endGroup(); + return amt; + } + public static boolean isPremium() { + int level; + settings.beginGroup("User"); + try { + String num = (String)settings.value("privilege", "1"); + level = new Integer(num.trim()); + } catch (java.lang.ClassCastException e) { + try { + level = (Integer)settings.value("privilege", 1); + } catch (Exception e1) { + level = 1; + } + } + settings.endGroup(); + PrivilegeLevel userLevel = PrivilegeLevel.findByValue(level); + if (userLevel == PrivilegeLevel.NORMAL) + return false; + return true; + + } + public static long getUploadLimit() { + settings.beginGroup("UserAccounting"); + long limit; + try { + String num = (String)settings.value("uploadLimit", new Long(0).toString()); + limit = new Long(num.trim()); + } catch (java.lang.ClassCastException e) { + limit = 0; + } + settings.endGroup(); + return limit; + } + public static boolean showTrayIcon() { + settings.beginGroup("General"); + String max = (String) settings.value("showTrayIcon", "true"); + settings.endGroup(); + if (!max.equalsIgnoreCase("true")) + return false; + return true; + } + public static void setShowTrayIcon(boolean val) { + settings.beginGroup("General"); + if (val) + settings.setValue("showTrayIcon", "true"); + else + settings.setValue("showTrayIcon", "false"); + settings.endGroup(); + } + public static boolean wasWindowMaximized() { + settings.beginGroup("General"); + String max = (String) settings.value("isMaximized", "true"); + settings.endGroup(); + if (!max.equalsIgnoreCase("true")) + return false; + return true; + } + public static void saveWindowMaximized(boolean isMax) { + settings.beginGroup("General"); + if (isMax) + settings.setValue("isMaximized", "true"); + else + settings.setValue("isMaximized", "false"); + settings.endGroup(); + } + public static String getLastViewedNoteGuid() { + settings.beginGroup("General"); + String guid = (String) settings.value("lastViewedNote", ""); + settings.endGroup(); + return guid; + } + public static void saveCurrentNoteGuid(String guid) { + settings.beginGroup("General"); + if (guid != null) + settings.setValue("lastViewedNote", guid); + else + settings.setValue("lastViewedNote", ""); + settings.endGroup(); + } + public static void setSortColumn(int i) { + settings.beginGroup("General"); + settings.setValue("sortColumn", i); + settings.endGroup(); + } + public static int getSortColumn() {; + settings.beginGroup("General"); + int order; + try { + String val = settings.value("sortColumn", new Integer(0)).toString(); + order = new Integer(val.trim()); + } catch (Exception e) { + try { + order = (Integer)settings.value("sortColumn", 0); + } catch (Exception e1) { + order = 0; + } + } + + settings.endGroup(); + return order; + } + public static void setSortOrder(int i) { + settings.beginGroup("General"); + settings.setValue("sortOrder", i); + settings.endGroup(); + } + public static int getSortOrder() { + settings.beginGroup("General"); + int order; + try { + String val = settings.value("sortOrder", new Integer(0)).toString(); + order = new Integer(val.trim()); + } catch (Exception e) { + try { + order = (Integer)settings.value("sortOrder", 0); + } catch (Exception e1) { + order = 0; + } + } + + settings.endGroup(); + return order; + } + public static boolean automaticLogin() { + settings.beginGroup("General"); + String text = (String)settings.value("automaticLogin", "false"); + settings.endGroup(); + if (text.equalsIgnoreCase("true")) + return true; + else + return false; + } + public static void setAutomaticLogin(boolean val) { + settings.beginGroup("General"); + if (val) + settings.setValue("automaticLogin", "true"); + else + settings.setValue("automaticLogin", "false"); + settings.endGroup(); + } + public static boolean rememberPassword() { + settings.beginGroup("General"); + String text = (String)settings.value("rememberPassword", "false"); + settings.endGroup(); + if (text.equalsIgnoreCase("true")) + return true; + else + return false; + } + public static void setRememberPassword(boolean val) { + settings.beginGroup("General"); + if (val) + settings.setValue("rememberPassword", "true"); + else + settings.setValue("rememberPassword", "false"); + settings.endGroup(); + } + public static void setServer(String server) { + settings.beginGroup("General"); + settings.setValue("server", server); + settings.endGroup(); + } + public static String getServer() { + settings.beginGroup("General"); + String text = (String)settings.value("server", "www.evernote.com"); + if (text.equals("www.evernote.com")) { + userStoreUrl = "https://www.evernote.com/edam/user"; + noteStoreUrlBase = "www.evernote.com/edam/note/"; + } else { + userStoreUrl = "https://sandbox.evernote.com/edam/user"; + noteStoreUrlBase = "sandbox.evernote.com/edam/note/"; + } + settings.endGroup(); + if (isPremium()) + noteStoreUrlBase = "https://" + noteStoreUrlBase; + else + noteStoreUrlBase = "http://" + noteStoreUrlBase; + return text; + } + public static boolean disableUploads() { + settings.beginGroup("General"); + String text = (String)settings.value("disableUploads", "false"); + settings.endGroup(); + if (text.equalsIgnoreCase("true")) + return true; + else + return false; + } + public static void setDisableUploads(boolean val) { + settings.beginGroup("General"); + if (val) + settings.setValue("disableUploads", "true"); + else + settings.setValue("disableUploads", "false"); + settings.endGroup(); + disableUploads = val; + } + public static boolean pdfPreview() { + settings.beginGroup("General"); + String text = (String)settings.value("pdfPreview", "true"); + settings.endGroup(); + if (text.equalsIgnoreCase("true")) + return true; + else + return false; + } + public static void setPdfPreview(boolean val) { + settings.beginGroup("General"); + if (val) + settings.setValue("pdfPreview", "true"); + else + settings.setValue("pdfPreview", "false"); + settings.endGroup(); + } + public static void setMinimumWordLength(int len) { + settings.beginGroup("General"); + settings.setValue("minimumWordLength", len); + settings.endGroup(); + } + public static int getMinimumWordLength() { + settings.beginGroup("General"); + Integer len = 4; + try { + String val = (String)settings.value("minimumWordLength", "4"); + len = new Integer(val); + } catch (Exception e) { + try { + len = (Integer)settings.value("minimumWordLength", 4); + } catch (Exception e1) { + len = 4; + } + } + settings.endGroup(); + return len; + + } + public static void setRecognitionWeight(int len) { + settings.beginGroup("General"); + settings.setValue("recognitionWeight", len); + settings.endGroup(); + } + public static int getRecognitionWeight() { + settings.beginGroup("General"); + Integer len; + try { + len = (Integer)settings.value("recognitionWeight", 80); + } catch (Exception e) { + len = 80; + } + settings.endGroup(); + return len; + } + public static String getMessageLevel() { + settings.beginGroup("Debug"); + String text = (String)settings.value("messageLevel", "Low"); + settings.endGroup(); + return text; + } + public static void setDateFormat(String format) { + settings.beginGroup("General"); + settings.setValue("dateFormat", format); + settings.endGroup(); + } + public static String getDateFormat() { + settings.beginGroup("General"); + String text = (String)settings.value("dateFormat", "MM/dd/yyyy"); + settings.endGroup(); + return text; + } + public static void setTimeFormat(String format) { + settings.beginGroup("General"); + settings.setValue("timeFormat", format); + settings.endGroup(); + } + public static String getTimeFormat() { + settings.beginGroup("General"); + String text = (String)settings.value("timeFormat", "HH:mm:ss"); + settings.endGroup(); + return text; + } + public static String getSyncInterval() { + settings.beginGroup("General"); + String text = (String)settings.value("syncInterval", "15 minutes"); + settings.endGroup(); + return text; + } + public static void setSyncInterval(String format) { + settings.beginGroup("General"); + settings.setValue("syncInterval", format); + settings.endGroup(); + } + public static void setColumnWidth(String col, int width) { + settings.beginGroup("ColumnWidths"); + settings.setValue(col, width); + settings.endGroup(); + } + public static int getColumnWidth(String col) { + settings.beginGroup("ColumnWidths"); + Integer width; + try { + String val = (String)settings.value(col, "0"); + width = new Integer(val.trim()); + } catch (Exception e) { + try { + width = (Integer)settings.value(col, 0); + } catch (Exception e1) { + width = 0; + } + } + settings.endGroup(); + return width; + } + public static void setColumnPosition(String col, int width) { + settings.beginGroup("ColumnPosition"); + settings.setValue(col, width); + settings.endGroup(); + } + public static int getColumnPosition(String col) { + settings.beginGroup("ColumnPosition"); + Integer width; + try { + String val = (String)settings.value(col, "-1"); + width = new Integer(val.trim()); + } catch (Exception e) { + try { + width = (Integer)settings.value(col, 0); + } catch (Exception e1) { + width = 0; + } + } + settings.endGroup(); + return width; + } + public static boolean verifyDelete() { + settings.beginGroup("General"); + String text = (String)settings.value("verifyDelete", "true"); + settings.endGroup(); + if (text.equalsIgnoreCase("true")) + return true; + else + return false; + } + public static void setVerifyDelete(boolean val) { + settings.beginGroup("General"); + if (val) + settings.setValue("verifyDelete", "true"); + else + settings.setValue("verifyDelete", "false"); + settings.endGroup(); + } + public static boolean synchronizeDeletedContent() { + settings.beginGroup("General"); + String text = (String)settings.value("syncDeletedContent", "false"); + settings.endGroup(); + if (text.equalsIgnoreCase("true")) + return true; + else + return false; + } + public static void setSynchronizeDeletedContent(boolean val) { + settings.beginGroup("General"); + if (val) + settings.setValue("syncDeletedContent", "true"); + else + settings.setValue("syncDeletedContent", "false"); + settings.endGroup(); + } + public static boolean isWindowVisible(String window) { + settings.beginGroup("WindowsVisible"); + String text = (String)settings.value(window, "true"); + settings.endGroup(); + if (text.equalsIgnoreCase("true")) + return true; + else + return false; + } + public static void saveWindowVisible(String window, boolean val) { + settings.beginGroup("WindowsVisible"); + if (val) + settings.setValue(window, "true"); + else + settings.setValue(window, "false"); + settings.endGroup(); + } + public static boolean isColumnVisible(String window) { + settings.beginGroup("ColumnsVisible"); + String text = (String)settings.value(window, "true"); + settings.endGroup(); + if (text.equalsIgnoreCase("true")) + return true; + else + return false; + } + public static void saveColumnVisible(String column, boolean val) { + settings.beginGroup("ColumnsVisible"); + if (val) + settings.setValue(column, "true"); + else + settings.setValue(column, "false"); + settings.endGroup(); + } + public static boolean isEditorButtonVisible(String window) { + settings.beginGroup("EditorButtonsVisible"); + String text = (String)settings.value(window, "true"); + settings.endGroup(); + if (text.equalsIgnoreCase("true")) + return true; + else + return false; + } + public static void saveEditorButtonsVisible(String column, boolean val) { + settings.beginGroup("EditorButtonsVisible"); + if (val) + settings.setValue(column, "true"); + else + settings.setValue(column, "false"); + settings.endGroup(); + } + public static boolean enableCarriageReturnFix() { + settings.beginGroup("Debug"); + String text = (String)settings.value("enableCarriageReturnFix", "false"); + settings.endGroup(); + if (text.equalsIgnoreCase("true")) + return true; + else + return false; + } + public static void saveCarriageReturnFix(boolean val) { + settings.beginGroup("Debug"); + if (val) + settings.setValue("enableCarriageReturnFix", "true"); + else + settings.setValue("enableCarriageReturnFix", "false"); + settings.endGroup(); + } + public static void setIndexThreads(int val) { + settings.beginGroup("General"); + settings.setValue("indexThreads", val); + settings.endGroup(); + } + public static int getIndexThreads() { + settings.beginGroup("General"); + Integer threads; + try { + String val = (String)settings.value("indexThreads", "1"); + threads = new Integer(val.trim()); + } catch (Exception e) { + try { + threads = (Integer)settings.value("indexThreads", 1); + } catch (Exception e1) { + threads = 1; + } + } + settings.endGroup(); + threads = 1; + return threads; + } + public static void setZoomFactor(double val) { + settings.beginGroup("General"); + settings.setValue("zoomFactor", val); + settings.endGroup(); + } + public static double getZoomFactor() { + settings.beginGroup("General"); + Double threads; + try { + String val = (String)settings.value("zoomFactor", "1.0"); + threads = new Double(val.trim()); + } catch (Exception e) { + try { + threads = (Double)settings.value("zoomFactor", 1.0); + } catch (Exception e1) { + threads = new Double(1); + } + } + settings.endGroup(); + return threads; + } + public static void setTextSizeMultiplier(double val) { + settings.beginGroup("General"); + settings.setValue("textMultiplier", val); + settings.endGroup(); + } + public static double getTextSizeMultiplier() { + settings.beginGroup("General"); + Double threads; + try { + String val = (String)settings.value("textMultiplier", "1"); + threads = new Double(val.trim()); + } catch (Exception e) { + try { + threads = (Double)settings.value("textMultiplier", 1); + } catch (Exception e1) { + threads = new Double(1); + } + } + settings.endGroup(); + return threads; + } + + public static boolean getMimicEvernoteInterface() { + settings.beginGroup("General"); + String text = (String)settings.value("mimicEvernoteInterface", "true"); + settings.endGroup(); + if (text.equalsIgnoreCase("true")) + return true; + else + return false; + } + public static void setMimicEvernoteInterface(boolean value) { + settings.beginGroup("General"); + if (value) + settings.setValue("mimicEvernoteInterface", "true"); + else + settings.setValue("mimicEvernoteInterface", "false"); + settings.endGroup(); + } + + public static boolean synchronizeOnClose() { + settings.beginGroup("General"); + String text = (String)settings.value("synchronizeOnClose", "false"); + settings.endGroup(); + if (text.equalsIgnoreCase("true")) + return true; + else + return false; + } + public static void setSynchronizeOnClose(boolean val) { + settings.beginGroup("General"); + if (val) + settings.setValue("synchronizeOnClose", "true"); + else + settings.setValue("synchronizeOnClose", "false"); + settings.endGroup(); + } + public static void setDatabaseVersion(String version) { + settings.beginGroup("General"); + settings.setValue("databaseVersion", version); + settings.endGroup(); + } + public static String getDatabaseVersion() { + settings.beginGroup("General"); + String val = (String)settings.value("databaseVersion", "0.70"); + settings.endGroup(); + return val; + } + public static String getDatabaseUrl() { + settings.beginGroup("General"); + String val = (String)settings.value("DatabaseURL", ""); + settings.endGroup(); + if (val.equals("")) + val = "jdbc:h2:"+Global.getDirectoryPath() +File.separator +"db" +File.separator +Global.databaseName; + return val; + } + public static String getDatabaseUserid() { + settings.beginGroup("General"); + String val = (String)settings.value("databaseUserid", ""); + settings.endGroup(); + return val; + } + public static String getDatabaseUserPassword() { + settings.beginGroup("General"); + String val = (String)settings.value("databaseUserPassword", ""); + settings.endGroup(); + return val; + } + public static void setStyle(String style) { + settings.beginGroup("General"); + settings.setValue("style", style); + settings.endGroup(); + } + public static String getStyle() { + settings.beginGroup("General"); + String val = (String)settings.value("style", ""); + settings.endGroup(); + return val; + } + public static boolean useStandardPalette() { + settings.beginGroup("General"); + String text = (String)settings.value("standardPalette", "true"); + settings.endGroup(); + if (text.equalsIgnoreCase("true")) + return true; + else + return false; + } + public static void setStandardPalette(boolean val) { + settings.beginGroup("General"); + if (val) + settings.setValue("standardPalette", "true"); + else + settings.setValue("standardPalette", "false"); + settings.endGroup(); + } + + public static void dbWait() { + // Global.dbThreadWait.wait(Global.dbThreadWaitMutex); + } + public static void dbContinue() { +// Global.dbThreadWait.wakeAll(); + } + public static synchronized void dbClientWait(int id) { + if (id == mainThreadId) { + try {mainThreadWaiter.take(); } catch (InterruptedException e) {e.printStackTrace();} + } + if (id == syncThreadId) { + try {syncThreadWaiter.take();} catch (InterruptedException e) {e.printStackTrace();} + } + if (id == tagCounterThreadId) { + try {tagCounterThreadWaiter.take();} catch (InterruptedException e) {e.printStackTrace();} + } + if (id == trashCounterThreadId) { + try {trashCounterThreadWaiter.take();} catch (InterruptedException e) {e.printStackTrace();} + } + if (id == indexThreadId) { + try {indexThreadWaiter.take();} catch (InterruptedException e) {e.printStackTrace();} + } + if (id == saveThreadId) { + try {saveThreadWaiter.take();} catch (InterruptedException e) {e.printStackTrace();} + } + if (id == notebookCounterThreadId) { + try {notebookCounterThreadWaiter.take();} catch (InterruptedException e) {e.printStackTrace();} + } + if (id == indexThread03Id) { + try {indexThread03ThreadWaiter.take();} catch (InterruptedException e) {e.printStackTrace();} + } + if (id == indexThread04Id) { + try {indexThread04ThreadWaiter.take();} catch (InterruptedException e) {e.printStackTrace();} + } + } + public static void dbClientContinue(int id) { + if (id == mainThreadId) { + try { mainThreadWaiter.put(true); } catch (InterruptedException e) { e.printStackTrace();} + } + if (id == syncThreadId) { + try { syncThreadWaiter.put(true); } catch (InterruptedException e) { e.printStackTrace();} + } + if (id == tagCounterThreadId) { + try { tagCounterThreadWaiter.put(true); } catch (InterruptedException e) { e.printStackTrace();} + } + if (id == trashCounterThreadId) { + try { trashCounterThreadWaiter.put(true); } catch (InterruptedException e) { e.printStackTrace();} + } + if (id == indexThreadId) { + try { indexThreadWaiter.put(true); } catch (InterruptedException e) { e.printStackTrace();} + } + if (id == saveThreadId) { + try { saveThreadWaiter.put(true); } catch (InterruptedException e) { e.printStackTrace();} + } + if (id == notebookCounterThreadId) { + try { notebookCounterThreadWaiter.put(true); } catch (InterruptedException e) { e.printStackTrace();} + } + if (id == indexThread03Id) { + try { indexThread03ThreadWaiter.put(true); } catch (InterruptedException e) { e.printStackTrace();} + } + if (id == indexThread04Id) { + try { indexThread04ThreadWaiter.put(true); } catch (InterruptedException e) { e.printStackTrace();} + } + } + + public static void saveState(String name, QByteArray state) { + settings.beginGroup("SaveState"); + settings.setValue(name, state); + settings.endGroup(); + } + + public static QByteArray restoreState(String name) { + settings.beginGroup("SaveState"); + QByteArray state = (QByteArray)settings.value(name); + settings.endGroup(); + return state; + } + public static void saveGeometry(String name, QByteArray state) { + settings.beginGroup("SaveGeometry"); + settings.setValue(name, state); + settings.endGroup(); + } + + public static QByteArray restoreGeometry(String name) { + settings.beginGroup("SaveGeometry"); + QByteArray state = (QByteArray)settings.value(name); + settings.endGroup(); + return state; + } + + public static void setAutoSaveInterval(int interval) { + settings.beginGroup("General"); + settings.setValue("autoSaveInterval", interval); + settings.endGroup(); + } + public static int getAutoSaveInterval() { + settings.beginGroup("General"); + Integer value; + try { + String val = (String)settings.value("autoSaveInterval", "5"); + value = new Integer(val.trim()); + } catch (Exception e) { + try { + value = (Integer)settings.value("autoSaveInterval", 5); + } catch (Exception e1) { + value = 0; + } + } + settings.endGroup(); + return value; + } + + // Add invalid attributes + public static void addInvalidAttribute(String element, String attribute) { + + List attributes = invalidAttributes.get(element); + if (attributes != null) { + for (int i=0; i attributeList; + if (!invalidAttributes.containsKey(element)) { + attributeList = new ArrayList(); + attributeList.add(attribute); + invalidAttributes.put(element, attributeList); + } + else { + attributeList = invalidAttributes.get(element); + attributeList.add(attribute); + invalidAttributes.put(element,attributeList); + } + } + + + // Add invalid attributes + public static void addInvalidElement(String element) { + for (int i=0; i>> 4) & 0x0F; + int two_halfs = 0; + do { + if ((0 <= halfbyte) && (halfbyte <= 9)) + buf.append((char) ('0' + halfbyte)); + else + buf.append((char) ('a' + (halfbyte - 10))); + halfbyte = element & 0x0F; + } while(two_halfs++ < 1); + } + return buf.toString(); + } + + + // What to do with inactive tags? + public static String tagBehavior() { + settings.beginGroup("General"); + String text = (String)settings.value("tagBehavior", "DoNothing"); + settings.endGroup(); + return text; + } + // What to do with inactive tags? + public static void setTagBehavior(String value) { + settings.beginGroup("General"); + settings.setValue("tagBehavior", value); + settings.endGroup(); + } + + + // Print date/time. Used mainly for performance tracing + public static void trace(boolean resetInterval) { + String fmt = "MM/dd/yy HH:mm:ss.SSSSSS"; + String dateTimeFormat = new String(fmt); + SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat); + Calendar cal = Calendar.getInstance(); + if (intervalTraceTime == null) + intervalTraceTime = Calendar.getInstance(); + if (startTraceTime == null) + startTraceTime = Calendar.getInstance(); + + float interval = (cal.getTimeInMillis() - intervalTraceTime.getTimeInMillis()); + float total = (cal.getTimeInMillis() - startTraceTime.getTimeInMillis()); + +// if (interval > 00.0) { + StackTraceElement[] exceptions = Thread.currentThread().getStackTrace(); + System.out.println("------------------------------------------"); + + System.out.println("Date/Time " +simple.format(cal.getTime())); + System.out.format("Interval Time: %-10.6f%n", interval); + System.out.format("Total Time: %-10.6f%n", total); + for (int i=2; i<5 && ia*|-kwFwXqVRm=2J7jlenVHRj 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 emitLog; // Messages displayed in the status bar; + QSystemTrayIcon trayIcon; // little tray icon + QMenu trayMenu; // System tray menu + QAction trayExitAction; // Exit the application + QAction trayShowAction; // toggle the show/hide action + QAction trayAddNoteAction; // Add a note from the system tray + + NotebookTreeWidget notebookTree; // List of notebooks + AttributeTreeWidget attributeTree; // List of note attributes + TagTreeWidget tagTree; // list of user created tags + SavedSearchTreeWidget savedSearchTree; // list of saved searches + TrashTreeWidget trashTree; // Trashcan + TableView noteTableView; // List of notes (the widget). + + public BrowserWindow browserWindow; // Window containing browser & labels + QToolBar toolBar; // The tool bar under the menu +// QLineEdit searchField; // The search filter bar on the toolbar + QComboBox searchField; // search filter bar on the toolbar; + boolean searchPerformed = false; // Search was done? + QProgressBar quotaBar; // The current quota usage + + ApplicationLogger logger; + List selectedNotebookGUIDs; // List of notebook GUIDs + List selectedTagGUIDs; // List of selected tag GUIDs + List selectedNoteGUIDs; // List of selected notes + String selectedSavedSearchGUID; // Currently selected saved searches + + NoteFilter filter; // Note filter + String currentNoteGuid; // GUID of the current note + Note currentNote; // The currently viewed note + boolean noteDirty; // Has the note been changed? + boolean inkNote; // if this is an ink note, it is read only + + QThread dbThread; // Thread to handle DB communication + ListManager listManager; // DB runnable task + + List tempFiles; // Array of temporary files; + + QTimer indexTimer; // timer to start the index thread + IndexRunner indexRunner; // thread to index notes + QThread indexThread; + + QTimer syncTimer; // Sync on an interval + QTimer syncDelayTimer; // Sync delay to free up database + SyncRunner syncRunner; // thread to do a sync. + QThread syncThread; + QTimer saveTimer; // Timer to save note contents + + QTimer authTimer; // Refresh authentication + QTimer externalFileSaveTimer; // Save files altered externally + List externalFiles; // External files to save later + List importFilesKeep; // Auto-import files to save later + List importFilesDelete; // Auto-import files to save later + + int indexTime; // how often to try and index + boolean indexRunning; // Is indexing running? + boolean indexDisabled; // Is indexing disabled? + + int syncThreadsReady; // number of sync threads that are free + int syncTime; // Sync interval + boolean syncRunning; // Is sync running? + boolean automaticSync; // do sync automatically? + QTreeWidgetItem attributeTreeSelected; + + QAction prevButton; // Go to the previous item viewed + QAction nextButton; // Go to the next item in the history + 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 synchronizeAnimation; // Synchronize movie + QTimer synchronizeAnimationTimer; // Timer to change animation button + int synchronizeFrame; // Current frame being viewed + QAction printButton; // Print Button + QAction tagButton; // Tag edit button + QAction attributeButton; // Attribute information button + QAction emailButton; // Email button + QAction deleteButton; // Delete button + QAction newButton; // new Note Button; + QSpinBox zoomSpinner; // Zoom zoom + QAction searchClearButton; // Clear the search field + + QSplitter mainLeftRightSplitter; // main splitter for left/right side + QSplitter leftSplitter1; // first left hand splitter + QSplitter browserIndexSplitter; // splitter between note index & note text + + QFileSystemWatcher importKeepWatcher; // Watch & keep auto-import + QFileSystemWatcher importDeleteWatcher; // Watch & Delete auto-import + List importedFiles; // History of imported files (so we don't import twice) + + OnlineNoteHistory historyWindow; // online history window + List versions; // history versions + + QTimer threadMonitorTimer; // Timer to watch threads. + int dbThreadDeadCount=0; // number of consecutive dead times for the db thread + int syncThreadDeadCount=0; // number of consecutive dead times for the sync thread + int indexThreadDeadCount=0; // number of consecutive dead times for the index thread + int notebookThreadDeadCount=0; // number of consecutive dead times for the notebook thread + int tagDeadCount=0; // number of consecutive dead times for the tag thread + int trashDeadCount=0; // number of consecutive dead times for the trash thread + int saveThreadDeadCount=0; // number of consecutive dead times for the save thread + + HashMap noteCache; // Cash of note content + List historyGuids; // GUIDs of previously viewed items + 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 + ThumbnailViewer thumbnailViewer; // View preview thumbnail; + + String iconPath = new String("classpath:cx/fbn/nevernote/icons/"); + + + //*************************************************************** + //*************************************************************** + //** Constructor & main entry point + //*************************************************************** + //*************************************************************** + // Application Constructor + public NeverNote() { + + if (!lockApplication()) { + System.exit(0); + } + thread().setPriority(Thread.MAX_PRIORITY); + + logger = new ApplicationLogger("nevernote.log"); + logger.log(logger.HIGH, tr("Starting Application")); + conn = new DatabaseConnection(logger, Global.mainThreadId); + conn.dbSetup(); + + logger.log(logger.EXTREME, tr("Creating index connection")); + logger.log(logger.EXTREME, tr("Building DB thread")); + Global.dbRunnerSignal = new DBRunnerSignal(); + if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") > -1) { + boolean goodCheck = false; + while (!goodCheck) { + DatabaseLoginDialog dialog = new DatabaseLoginDialog(); + dialog.exec(); + if (!dialog.okPressed()) + System.exit(0); + Global.cipherPassword = dialog.getPassword(); + goodCheck = databaseCheck(Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword); + } + } + Global.dbRunner = new DBRunner(Global.getDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword); + logger.log(logger.EXTREME, tr("Starting DB thread")); + dbThread = new QThread(Global.dbRunner, "Database Thread"); + dbThread.start(); + logger.log(logger.EXTREME, tr("DB Thread has started")); + Global.dbRunnerSignal.start.emit(); + logger.log(logger.EXTREME, tr("Setting main thread DB connection")); + logger.log(logger.EXTREME, tr("main DB thread setup complete.")); + conn.checkDatabaseVersion(); + + // Start building the invalid XML tables + Global.invalidElements = conn.getInvalidXMLTable().getInvalidElements(); + List elements = conn.getInvalidXMLTable().getInvalidAttributeElements(); + + for (int i=0; i 0) { + automaticSync = true; + syncTimer.start(syncTime*60*1000); + } else { + automaticSync = false; + syncTimer.stop(); + } + syncRunner.setEvernoteUpdateCount(Global.getEvernoteUpdateCount()); + syncThread = new QThread(syncRunner, "Synchronization Thread"); + syncThread.start(); + + + logger.log(logger.EXTREME, tr("Starting authentication timer")); + authTimer = new QTimer(); + authTimer.timeout.connect(this, "authTimer()"); + authTimer.start(1000*60*15); + syncRunner.syncSignal.authRefreshComplete.connect(this, "authRefreshComplete(boolean)"); + + logger.log(logger.EXTREME, tr("Setting save note timer")); + saveTimer = new QTimer(); + 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.start(); + } + +// Global.trace(); + logger.log(logger.EXTREME, tr("Starting external file monitor timer")); + externalFileSaveTimer = new QTimer(); + externalFileSaveTimer.timeout.connect(this, "externalFileEditedSaver()"); + externalFileSaveTimer.setInterval(1000*5); // save every 5 seconds; + externalFiles = new ArrayList(); + importFilesDelete = new ArrayList(); + importFilesKeep = new ArrayList(); + externalFileSaveTimer.start(); + + notebookTree = new NotebookTreeWidget(); + attributeTree = new AttributeTreeWidget(); + tagTree = new TagTreeWidget(conn); + savedSearchTree = new SavedSearchTreeWidget(); + trashTree = new TrashTreeWidget(); + noteTableView = new TableView(logger); + + QGridLayout leftGrid = new QGridLayout(); + leftSplitter1.setLayout(leftGrid); + leftGrid.addWidget(notebookTree, 1, 1); + leftGrid.addWidget(tagTree,2,1); + leftGrid.addWidget(attributeTree,3,1); + leftGrid.addWidget(savedSearchTree,4,1); + leftGrid.addWidget(trashTree, 5, 1); + + // Setup the browser window + noteCache = new HashMap(); + browserWindow = new BrowserWindow(conn); + + browserIndexSplitter.addWidget(noteTableView); + browserIndexSplitter.addWidget(browserWindow); + + mainLeftRightSplitter.addWidget(leftSplitter1); + mainLeftRightSplitter.addWidget(browserIndexSplitter); + + searchField = new QComboBox(); + searchField.setEditable(true); + searchField.activatedIndex.connect(this, "searchFieldChanged()"); + searchField.setDuplicatesEnabled(false); + searchField.editTextChanged.connect(this,"searchFieldTextChanged(String)"); + + quotaBar = new QProgressBar(); + + // Setup the thumbnail viewer + thumbnailViewer = new ThumbnailViewer(); + thumbnailViewer.upArrow.connect(this, "upAction()"); + thumbnailViewer.downArrow.connect(this, "downAction()"); + thumbnailViewer.leftArrow.connect(this, "nextViewedAction()"); + thumbnailViewer.rightArrow.connect(this, "previousViewedAction()"); + + listManager.loadNotesIndex(); + initializeNotebookTree(); + initializeTagTree(); + initializeSavedSearchTree(); + attributeTree.itemClicked.connect(this, "attributeTreeClicked(QTreeWidgetItem, Integer)"); + attributeTreeSelected = null; + initializeNoteTable(); + + selectedNoteGUIDs = new ArrayList(); + statusBar = new QStatusBar(); + setStatusBar(statusBar); + menuBar = new MainMenuBar(this); + emitLog = new ArrayList(); + + tagTree.setDeleteAction(menuBar.tagDeleteAction); + tagTree.setEditAction(menuBar.tagEditAction); + tagTree.setAddAction(menuBar.tagAddAction); + tagTree.setVisible(Global.isWindowVisible("tagTree")); + tagTree.noteSignal.tagsAdded.connect(this, "tagsAdded(String, String)"); + menuBar.hideTags.setChecked(Global.isWindowVisible("tagTree")); + listManager.tagSignal.listChanged.connect(this, "reloadTagTree()"); + + notebookTree.setDeleteAction(menuBar.notebookDeleteAction); + notebookTree.setEditAction(menuBar.notebookEditAction); + notebookTree.setAddAction(menuBar.notebookAddAction); + notebookTree.setVisible(Global.isWindowVisible("notebookTree")); + notebookTree.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)"); + menuBar.hideNotebooks.setChecked(Global.isWindowVisible("notebookTree")); + + savedSearchTree.setAddAction(menuBar.savedSearchAddAction); + savedSearchTree.setEditAction(menuBar.savedSearchEditAction); + savedSearchTree.setDeleteAction(menuBar.savedSearchDeleteAction); + savedSearchTree.itemSelectionChanged.connect(this, "updateSavedSearchSelection()"); + savedSearchTree.setVisible(Global.isWindowVisible("savedSearchTree")); + menuBar.hideSavedSearches.setChecked(Global.isWindowVisible("savedSearchTree")); + + noteTableView.setAddAction(menuBar.noteAdd); + noteTableView.setDeleteAction(menuBar.noteDelete); + noteTableView.setRestoreAction(menuBar.noteRestoreAction); + noteTableView.setNoteDuplicateAction(menuBar.noteDuplicateAction); + noteTableView.setNoteHistoryAction(menuBar.noteOnlineHistoryAction); + noteTableView.noteSignal.titleColorChanged.connect(this, "titleColorChanged(Integer)"); + noteTableView.setMergeNotesAction(menuBar.noteMergeAction); + noteTableView.rowChanged.connect(this, "scrollToGuid(String)"); + noteTableView.resetViewport.connect(this, "scrollToCurrentGuid()"); + noteTableView.doubleClicked.connect(this, "listDoubleClick()"); + listManager.trashSignal.countChanged.connect(trashTree, "updateCounts(Integer)"); + trashTree.load(); + trashTree.itemSelectionChanged.connect(this, "trashTreeSelection()"); + trashTree.setEmptyAction(menuBar.emptyTrashAction); + 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")); + + noteTableView.setVisible(Global.isWindowVisible("noteList")); + menuBar.hideNoteList.setChecked(Global.isWindowVisible("noteList")); + + if (!Global.isWindowVisible("editorButtonBar")) + toggleEditorButtonBar(); + if (!Global.isWindowVisible("leftPanel")) + menuBar.hideLeftSide.setChecked(true); + + setMenuBar(menuBar); + setupToolBar(); + find = new FindDialog(); + find.getOkButton().clicked.connect(this, "doFindText()"); + + // Setup the tray icon menu bar + trayShowAction = new QAction("Show/Hide", this); + trayExitAction = new QAction("Exit", this); + trayAddNoteAction = new QAction("Add Note", this); + + trayExitAction.triggered.connect(this, "close()"); + trayAddNoteAction.triggered.connect(this, "addNote()"); + trayShowAction.triggered.connect(this, "trayToggleVisible()"); + + trayMenu = new QMenu(this); + trayMenu.addAction(trayAddNoteAction); + trayMenu.addAction(trayShowAction); + trayMenu.addAction(trayExitAction); + + + trayIcon = new QSystemTrayIcon(this); + trayIcon.setToolTip("NeverNote"); + trayIcon.setContextMenu(trayMenu); + trayIcon.activated.connect(this, "trayActivated(com.trolltech.qt.gui.QSystemTrayIcon$ActivationReason)"); + + currentNoteGuid=""; + currentNoteGuid = Global.getLastViewedNoteGuid(); + historyGuids = new ArrayList(); + historyPosition = 0; + fromHistory = false; + noteDirty = false; + if (!currentNoteGuid.trim().equals("")) { + currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true); + } + + noteIndexUpdated(true); + showColumns(); + menuBar.showEditorBar.setChecked(Global.isWindowVisible("editorButtonBar")); + if (menuBar.showEditorBar.isChecked()) + showEditorButtons(); + tagIndexUpdated(true); + savedSearchIndexUpdated(); + notebookIndexUpdated(); + updateQuotaBar(); + setupSyncSignalListeners(); + setupBrowserSignalListeners(); + setupIndexListeners(); + + + tagTree.tagSignal.listChanged.connect(this, "tagIndexUpdated()"); + tagTree.showAllTags(true); + + QIcon appIcon = new QIcon(iconPath+"nevernote.png"); + setWindowIcon(appIcon); + trayIcon.setIcon(appIcon); + if (Global.showTrayIcon()) + trayIcon.show(); + else + trayIcon.hide(); + + scrollToGuid(currentNoteGuid); + if (Global.automaticLogin()) { + remoteConnect(); + if (Global.isConnected) + syncTimer(); + } + setupFolderImports(); + + loadStyleSheet(); + restoreWindowState(); + + if (Global.mimicEvernoteInterface) { + notebookTree.selectGuid(""); + } + + threadMonitorTimer = new QTimer(); + threadMonitorTimer.timeout.connect(this, "threadMonitorCheck()"); + threadMonitorTimer.start(1000*10); // Check for threads every 10 seconds; + + historyGuids.add(currentNoteGuid); + historyPosition = 1; + + int sortCol = Global.getSortColumn(); + int sortOrder = Global.getSortOrder(); + noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder)); + } + + + // Main entry point + public static void main(String[] args) { + QApplication.initialize(args); + QPixmap pixmap = new QPixmap("classpath:cx/fbn/nevernote/icons/splash_logo.png"); + QSplashScreen splash = new QSplashScreen(pixmap); + + for (String arg : args) { + String lower = arg.toLowerCase(); + if (lower.startsWith("--name=")) + Global.setName(arg.substring(arg.indexOf('=')+1)); + if (lower.startsWith("--home=")) + Global.currentDir = arg.substring(arg.indexOf('=')+1); + if (lower.startsWith("--disable-viewing")) + Global.disableViewing = true; + } + Global.setup(); + boolean showSplash = Global.isWindowVisible("SplashScreen"); + if (showSplash) + splash.show(); + NeverNote application = new NeverNote(); + application.setAttribute(WidgetAttribute.WA_DeleteOnClose, true); + if (Global.wasWindowMaximized()) + application.showMaximized(); + else + application.show(); + if (showSplash) + splash.finish(application); + QApplication.exec(); + System.out.println("Goodbye."); + QApplication.exit(); + } + // Exit point + @Override + public void closeEvent(QCloseEvent event) { + logger.log(logger.HIGH, "Entering NeverNote.closeEvent"); + waitCursor(true); + + if (currentNote!= null & browserWindow!=null) { + if (!currentNote.getTitle().equals(browserWindow.getTitle())) + conn.getNoteTable().updateNoteTitle(currentNote.getGuid(), browserWindow.getTitle()); + } + saveNote(); + setMessage("Beginning shutdown."); + + externalFileEditedSaver(); + if (Global.isConnected && Global.synchronizeOnClose()) { + setMessage("Performing synchronization before closing."); + syncRunner.addWork("SYNC"); + } + setMessage("Closing Program."); + threadMonitorTimer.stop(); + + syncRunner.addWork("STOP"); + indexRunner.addWork("STOP"); + saveNote(); + listManager.stop(); + saveWindowState(); + + if (tempFiles != null) + tempFiles.clear(); + + browserWindow.noteSignal.tagsChanged.disconnect(); + browserWindow.noteSignal.titleChanged.disconnect(); + browserWindow.noteSignal.noteChanged.disconnect(); + browserWindow.noteSignal.notebookChanged.disconnect(); + browserWindow.noteSignal.createdDateChanged.disconnect(); + browserWindow.noteSignal.alteredDateChanged.disconnect(); + syncRunner.searchSignal.listChanged.disconnect(); + syncRunner.tagSignal.listChanged.disconnect(); + syncRunner.notebookSignal.listChanged.disconnect(); + syncRunner.noteIndexSignal.listChanged.disconnect(); + + + int position = noteTableView.header.visualIndex(Global.noteTableCreationPosition); + Global.setColumnPosition("noteTableCreationPosition", position); + position = noteTableView.header.visualIndex(Global.noteTableTagPosition); + Global.setColumnPosition("noteTableTagPosition", position); + position = noteTableView.header.visualIndex(Global.noteTableNotebookPosition); + Global.setColumnPosition("noteTableNotebookPosition", position); + position = noteTableView.header.visualIndex(Global.noteTableChangedPosition); + Global.setColumnPosition("noteTableChangedPosition", position); + position = noteTableView.header.visualIndex(Global.noteTableAuthorPosition); + Global.setColumnPosition("noteTableAuthorPosition", position); + position = noteTableView.header.visualIndex(Global.noteTableSourceUrlPosition); + Global.setColumnPosition("noteTableSourceUrlPosition", position); + position = noteTableView.header.visualIndex(Global.noteTableSubjectDatePosition); + Global.setColumnPosition("noteTableSubjectDatePosition", position); + position = noteTableView.header.visualIndex(Global.noteTableTitlePosition); + Global.setColumnPosition("noteTableTitlePosition", position); + position = noteTableView.header.visualIndex(Global.noteTableSynchronizedPosition); + Global.setColumnPosition("noteTableSynchronizedPosition", position); + + saveNoteIndexWidth(); + + int width = notebookTree.columnWidth(0); + Global.setColumnWidth("notebookTreeName", width); + width = tagTree.columnWidth(0); + Global.setColumnWidth("tagTreeName", width); + + Global.saveWindowMaximized(isMaximized()); + Global.saveCurrentNoteGuid(currentNoteGuid); + + int sortCol = noteTableView.proxyModel.sortColumn(); + int sortOrder = noteTableView.proxyModel.sortOrder().value(); + Global.setSortColumn(sortCol); + Global.setSortOrder(sortOrder); + + hide(); + trayIcon.hide(); + Global.keepRunning = false; + try { + logger.log(logger.MEDIUM, "Waiting for indexThread to stop"); + indexRunner.thread().join(50); + logger.log(logger.MEDIUM, "Index thread has stopped"); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + if (!syncRunner.isIdle()) { + try { + logger.log(logger.MEDIUM, "Waiting for syncThread to stop"); + syncThread.join(); + logger.log(logger.MEDIUM, "Sync thread has stopped"); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + } + + logger.log(logger.EXTREME, "Shutting down database"); + conn.dbShutdown(); + logger.log(logger.EXTREME, "Waiting for DB thread to terminate"); + try { + dbThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + logger.log(logger.EXTREME, "DB Thread has terminated"); + unlockApplication(); + logger.log(logger.HIGH, "Leaving NeverNote.closeEvent"); + } + + public void setMessage(String s) { + logger.log(logger.HIGH, "Entering NeverNote.setMessage"); + logger.log(logger.HIGH, "Message: " +s); + statusBar.showMessage(s); + emitLog.add(s); + logger.log(logger.HIGH, "Leaving NeverNote.setMessage"); + } + + private void waitCursor(boolean wait) { + if (wait) + QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.WaitCursor)); + else + QApplication.restoreOverrideCursor(); + } + + private void setupIndexListeners() { + indexRunner.noteSignal.noteIndexed.connect(this, "indexThreadComplete(String)"); + indexRunner.resourceSignal.resourceIndexed.connect(this, "indexThreadComplete(String)"); +// indexRunner.threadSignal.indexNeeded.connect(listManager, "setIndexNeeded(String, String, Boolean)"); + } + private void setupSyncSignalListeners() { + syncRunner.tagSignal.listChanged.connect(this, "tagIndexUpdated()"); + syncRunner.searchSignal.listChanged.connect(this, "savedSearchIndexUpdated()"); + syncRunner.notebookSignal.listChanged.connect(this, "notebookIndexUpdated()"); + syncRunner.noteIndexSignal.listChanged.connect(this, "noteIndexUpdated(boolean)"); + syncRunner.noteSignal.quotaChanged.connect(this, "updateQuotaBar()"); + +// syncRunner.syncSignal.setSequenceDate.connect(this,"setSequenceDate(long)"); + syncRunner.syncSignal.saveUploadAmount.connect(this,"saveUploadAmount(long)"); +// syncRunner.syncSignal.setUpdateSequenceNumber.connect(this,"setUpdateSequenceNumber(int)"); + syncRunner.syncSignal.saveUserInformation.connect(this,"saveUserInformation(User)"); + syncRunner.syncSignal.saveEvernoteUpdateCount.connect(this,"saveEvernoteUpdateCount(int)"); + + syncRunner.noteSignal.guidChanged.connect(this, "noteGuidChanged(String, String)"); + syncRunner.noteSignal.noteChanged.connect(this, "invalidateNoteCache(String, String)"); + syncRunner.resourceSignal.resourceGuidChanged.connect(this, "noteResourceGuidChanged(String,String,String)"); + + syncRunner.syncSignal.refreshLists.connect(this, "refreshLists()"); + } + + 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.titleChanged.connect(this, "updateListTitle(String, String)"); + browserWindow.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)"); + browserWindow.noteSignal.createdDateChanged.connect(listManager, "updateNoteCreatedDate(String, QDateTime)"); + browserWindow.noteSignal.createdDateChanged.connect(this, "updateListDateCreated(String, QDateTime)"); + browserWindow.noteSignal.alteredDateChanged.connect(listManager, "updateNoteAlteredDate(String, QDateTime)"); + browserWindow.noteSignal.alteredDateChanged.connect(this, "updateListDateChanged(String, QDateTime)"); + browserWindow.noteSignal.subjectDateChanged.connect(listManager, "updateNoteSubjectDate(String, QDateTime)"); + browserWindow.noteSignal.subjectDateChanged.connect(this, "updateListDateSubject(String, QDateTime)"); + browserWindow.noteSignal.authorChanged.connect(listManager, "updateNoteAuthor(String, String)"); + browserWindow.noteSignal.authorChanged.connect(this, "updateListAuthor(String, String)"); + browserWindow.noteSignal.sourceUrlChanged.connect(listManager, "updateNoteSourceUrl(String, String)"); + browserWindow.noteSignal.sourceUrlChanged.connect(this, "updateListSourceUrl(String, String)"); + browserWindow.focusLost.connect(this, "saveNote()"); + browserWindow.resourceSignal.contentChanged.connect(this, "externalFileEdited(String)"); +// browserWindow.resourceSignal.externalFileEdit.connect(this, "saveResourceLater(String, String)"); + } + private boolean lockApplication() { + + String fileName = Global.currentDir +"db" +File.separator +"NeverNote.lock.db"; +// QFile.remove(fileName); + if (QFile.exists(fileName)) { + QMessageBox.question(this, "Lock File Detected", + "While starting I've found a database lock file.\n" + + "to prevent multiple instances from accessing the database \n"+ + "at the same time. Please stop any other program, or (if you\n" + + "are sure nothing else is using the database) remove the file\n" + + fileName +"."); + return false; + + } + return true; +/* String fileName = Global.currentDir +"nevernote.lock"; + + + if (QFile.exists(fileName)) { + if (QMessageBox.question(this, "Confirmation", + "While starting I've found a lock file. This file is used to prevent multiple "+ + "instances of this program running at once. If NeverNote has crashed this " + + "is just a file that wasn't cleaned up and you can safely, "+ + "continue, but if there is another instance of this running you are " + + "running the risk of creating problems.\n\n" + + "Are you sure you want to continue?", + QMessageBox.StandardButton.Yes, + QMessageBox.StandardButton.No)==StandardButton.No.value()) { + return false; + } + } + + QFile file = new QFile(fileName); + file.open(OpenModeFlag.WriteOnly); + file.write(new QByteArray("This file is used to prevent multiple instances " + + "of NeverNote running more than once. " + + "It should be deleted when NeverNote ends")); + file.close(); + return true; +*/ + } + private void unlockApplication() { + String fileName = Global.currentDir +"nevernote.lock"; + if (QFile.exists(fileName)) { + QFile.remove(fileName); + } + } + + + //*************************************************************** + //*************************************************************** + //* Settings and look & feel + //*************************************************************** + //*************************************************************** + @SuppressWarnings("unused") + private void settings() { + logger.log(logger.HIGH, "Entering NeverNote.settings"); + ConfigDialog settings = new ConfigDialog(this); + String dateFormat = Global.getDateFormat(); + String timeFormat = Global.getTimeFormat(); + + settings.exec(); + if (Global.showTrayIcon()) + trayIcon.show(); + else + trayIcon.hide(); + showColumns(); + if (menuBar.showEditorBar.isChecked()) + showEditorButtons(); + + // Reset the save timer + if (Global.getAutoSaveInterval() > 0) + saveTimer.setInterval(1000*60*Global.getAutoSaveInterval()); + else + saveTimer.stop(); + + // This is a hack to force a reload of the index in case the date or time changed. +// if (!dateFormat.equals(Global.getDateFormat()) || +// !timeFormat.equals(Global.getTimeFormat())) { + noteCache.clear(); + noteIndexUpdated(true); +// } + + logger.log(logger.HIGH, "Leaving NeverNote.settings"); + } + // Restore things to the way they were + private void restoreWindowState() { + // We need to name things or this doesn't work. + setObjectName("NeverNote"); + mainLeftRightSplitter.setObjectName("mainLeftRightSplitter"); + browserIndexSplitter.setObjectName("browserIndexSplitter"); + leftSplitter1.setObjectName("leftSplitter1"); + + // Restore the actual positions. + restoreGeometry(Global.restoreGeometry(objectName())); + mainLeftRightSplitter.restoreState(Global.restoreState(mainLeftRightSplitter.objectName())); + browserIndexSplitter.restoreState(Global.restoreState(browserIndexSplitter.objectName())); + leftSplitter1.restoreState(Global.restoreState(leftSplitter1.objectName())); + + } + // Save window positions for the next start + private void saveWindowState() { + Global.saveGeometry(objectName(), saveGeometry()); + Global.saveState(mainLeftRightSplitter.objectName(), mainLeftRightSplitter.saveState()); + Global.saveState(browserIndexSplitter.objectName(), browserIndexSplitter.saveState()); + Global.saveState(leftSplitter1.objectName(), leftSplitter1.saveState()); + } + // Load the style sheet + private void loadStyleSheet() { + String fileName = Global.currentDir +"qss"+System.getProperty("file.separator")+ "default.qss"; + QFile file = new QFile(fileName); + file.open(OpenModeFlag.ReadOnly); + String styleSheet = file.readAll().toString(); + file.close(); + setStyleSheet(styleSheet); + } + // Save column widths for the next time + private void saveNoteIndexWidth() { + int width; + width = noteTableView.getColumnWidth(Global.noteTableCreationPosition); + Global.setColumnWidth("noteTableCreationPosition", width); + width = noteTableView.getColumnWidth(Global.noteTableChangedPosition); + Global.setColumnWidth("noteTableChangedPosition", width); + width = noteTableView.getColumnWidth(Global.noteTableGuidPosition); + Global.setColumnWidth("noteTableGuidPosition", width); + width = noteTableView.getColumnWidth(Global.noteTableNotebookPosition); + Global.setColumnWidth("noteTableNotebookPosition", width); + width = noteTableView.getColumnWidth(Global.noteTableTagPosition); + Global.setColumnWidth("noteTableTagPosition", width); + width = noteTableView.getColumnWidth(Global.noteTableTitlePosition); + Global.setColumnWidth("noteTableTitlePosition", width); + width = noteTableView.getColumnWidth(Global.noteTableSourceUrlPosition); + Global.setColumnWidth("noteTableSourceUrlPosition", width); + width = noteTableView.getColumnWidth(Global.noteTableAuthorPosition); + Global.setColumnWidth("noteTableAuthorPosition", width); + width = noteTableView.getColumnWidth(Global.noteTableSubjectDatePosition); + Global.setColumnWidth("noteTableSubjectDatePosition", width); + width = noteTableView.getColumnWidth(Global.noteTableSynchronizedPosition); + Global.setColumnWidth("noteTableSynchronizedPosition", width); + } + + + //*************************************************************** + //*************************************************************** + //** These functions deal with Notebook menu items + //*************************************************************** + //*************************************************************** + // Setup the tree containing the user's notebooks. + private void initializeNotebookTree() { + logger.log(logger.HIGH, "Entering NeverNote.initializeNotebookTree"); + notebookTree.itemSelectionChanged.connect(this, "notebookTreeSelection()"); + listManager.notebookSignal.refreshNotebookTreeCounts.connect(notebookTree, "updateCounts(List, List)"); + // notebookTree.resize(Global.getSize("notebookTree")); + logger.log(logger.HIGH, "Leaving NeverNote.initializeNotebookTree"); + } + // Listener when a notebook is selected + @SuppressWarnings("unused") + private void notebookTreeSelection() { + logger.log(logger.HIGH, "Entering NeverNote.notebookTreeSelection"); + + clearTrashFilter(); + clearAttributeFilter(); + clearSavedSearchFilter(); + if (Global.mimicEvernoteInterface) { + clearTagFilter(); + searchField.clear(); + } + + menuBar.noteRestoreAction.setVisible(false); + menuBar.notebookEditAction.setEnabled(true); + menuBar.notebookDeleteAction.setEnabled(true); + List selections = notebookTree.selectedItems(); + QTreeWidgetItem currentSelection; + selectedNotebookGUIDs.clear(); + if (!Global.mimicEvernoteInterface) { + for (int i=0; i 0) + guid = (selections.get(0).text(2)); + if (!guid.equals("")) + selectedNotebookGUIDs.add(guid); + } + listManager.setSelectedNotebooks(selectedNotebookGUIDs); + listManager.loadNotesIndex(); + noteIndexUpdated(false); + logger.log(logger.HIGH, "Leaving NeverNote.notebookTreeSelection"); + + } + private void clearNotebookFilter() { + notebookTree.blockSignals(true); + notebookTree.clearSelection(); + menuBar.noteRestoreAction.setVisible(false); + menuBar.notebookEditAction.setEnabled(false); + menuBar.notebookDeleteAction.setEnabled(false); + selectedNotebookGUIDs.clear(); + listManager.setSelectedNotebooks(selectedNotebookGUIDs); + notebookTree.blockSignals(false); + } + // Triggered when the notebook DB has been updated + private void notebookIndexUpdated() { + logger.log(logger.HIGH, "Entering NeverNote.notebookIndexUpdated"); + if (selectedNotebookGUIDs == null) + selectedNotebookGUIDs = new ArrayList(); + List books = conn.getNotebookTable().getAll(); + for (int i=books.size()-1; i>=0; i--) { + for (int j=0; j=0; i--) { + boolean found = notebookTree.selectGuid(selectedNotebookGUIDs.get(i)); + if (!found) + selectedNotebookGUIDs.remove(i); + } + notebookTree.blockSignals(false); + + logger.log(logger.HIGH, "Leaving NeverNote.notebookIndexUpdated"); + } + // Show/Hide note information + private void toggleNotebookWindow() { + logger.log(logger.HIGH, "Entering NeverNote.toggleNotebookWindow"); + if (notebookTree.isVisible()) + notebookTree.hide(); + else + notebookTree.show(); + menuBar.hideNotebooks.setChecked(notebookTree.isVisible()); + Global.saveWindowVisible("notebookTree", notebookTree.isVisible()); + logger.log(logger.HIGH, "Leaving NeverNote.toggleNotebookWindow"); + } + // Add a new notebook + @SuppressWarnings("unused") + private void addNotebook() { + logger.log(logger.HIGH, "Inside NeverNote.addNotebook"); + NotebookEdit edit = new NotebookEdit(); + edit.setNotebooks(listManager.getNotebookIndex()); + edit.exec(); + + if (!edit.okPressed()) + return; + + Calendar currentTime = new GregorianCalendar(); + Long l = new Long(currentTime.getTimeInMillis()); + String randint = new String(Long.toString(l)); + + Notebook newBook = new Notebook(); + newBook.setUpdateSequenceNum(0); + newBook.setGuid(randint); + newBook.setName(edit.getNotebook()); + newBook.setServiceCreated(new Date().getTime()); + newBook.setServiceUpdated(new Date().getTime()); + newBook.setDefaultNotebook(false); + newBook.setPublished(false); + + listManager.getNotebookIndex().add(newBook); + if (edit.isLocal()) + listManager.getLocalNotebooks().add(newBook.getGuid()); + conn.getNotebookTable().addNotebook(newBook, true, edit.isLocal()); + notebookIndexUpdated(); + listManager.countNotebookResults(listManager.getNoteIndex()); +// notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter()); + logger.log(logger.HIGH, "Leaving NeverNote.addNotebook"); + } + // Edit an existing notebook + @SuppressWarnings("unused") + private void editNotebook() { + logger.log(logger.HIGH, "Entering NeverNote.editNotebook"); + NotebookEdit edit = new NotebookEdit(); + edit.setTitle("Edit Notebook"); + edit.setLocalCheckboxEnabled(false); + List selections = notebookTree.selectedItems(); + QTreeWidgetItem currentSelection; + currentSelection = selections.get(0); + edit.setNotebook(currentSelection.text(0)); + edit.setNotebooks(listManager.getNotebookIndex()); + 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 nbooks = new ArrayList(); + for (int i=0; i selections = notebookTree.selectedItems(); + for (int i=0; i=0; i--) { + QTreeWidgetItem currentSelection; + currentSelection = selections.get(i); + String guid = currentSelection.text(2); + conn.getNotebookTable().expungeNotebook(guid, true); + listManager.deleteNotebook(guid); + } +// for (int i==0; i--) { + // if (dbRunner.getLocalNotebooks().get(i).equals(arg0)) + // } + notebookTree.load(listManager.getNotebookIndex(), listManager.getLocalNotebooks()); + listManager.countNotebookResults(listManager.getNoteIndex()); +// notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter()); + logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook"); + } + // A note's notebook has been updated + @SuppressWarnings("unused") + private void updateNoteNotebook(String guid, String notebookGuid) { + + // Update the list manager + listManager.updateNoteNotebook(guid, notebookGuid); + listManager.countNotebookResults(listManager.getNoteIndex()); +// notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter()); + + // Find the name of the notebook + String notebookName = null; + for (int i=0; i=0) + browserWindow.notebookBox.setCurrentIndex(pos); + } + } + + // If we're dealing with the current note, then we need to be sure and update the notebook there + if (guid.equals(currentNoteGuid)) { + if (currentNote != null) { + currentNote.setNotebookGuid(notebookGuid); + } + } + } + // Open/close notebooks + @SuppressWarnings("unused") + private void closeNotebooks() { + NotebookArchive na = new NotebookArchive(listManager.getNotebookIndex(), listManager.getArchiveNotebookIndex()); + na.exec(); + if (!na.okClicked()) + return; + + waitCursor(true); + listManager.getArchiveNotebookIndex().clear(); + + for (int i=na.getClosedBookList().count()-1; i>=0; i--) { + String text = na.getClosedBookList().takeItem(i).text(); + for (int j=0; j=0; i--) { + String text = na.getOpenBookList().takeItem(i).text(); + for (int j=0; j nbooks = new ArrayList(); + for (int i=0; i 0 + && !notebookTree.selectedItems().get(0).text(0).equalsIgnoreCase("All Notebooks")) + filter = true; + if (tagTree.selectedItems().size() > 0) + filter = true; + tagTree.showAllTags(!filter); + logger.log(logger.HIGH, "Leaving NeverNote.reloadTagTree"); + } + // Edit an existing tag + @SuppressWarnings("unused") + private void editTag() { + logger.log(logger.HIGH, "Entering NeverNote.editTag"); + TagEdit edit = new TagEdit(); + edit.setTitle("Edit Tag"); + List selections = tagTree.selectedItems(); + QTreeWidgetItem currentSelection; + currentSelection = selections.get(0); + edit.setTag(currentSelection.text(0)); + edit.setTagList(listManager.getTagIndex()); + edit.exec(); + + if (!edit.okPressed()) + return; + + String guid = currentSelection.text(2); + currentSelection.setText(0,edit.getTag()); + + for (int i=0; i selections = tagTree.selectedItems(); + for (int i=selections.size()-1; i>=0; i--) { + QTreeWidgetItem currentSelection; + currentSelection = selections.get(i); + removeTagItem(currentSelection.text(2)); + } + tagIndexUpdated(true); + listManager.countTagResults(listManager.getNoteIndex()); +// tagTree.updateCounts(listManager.getTagCounter()); + logger.log(logger.HIGH, "Leaving NeverNote.deleteTag"); + } + // Remove a tag tree item. Go recursively down & remove the children too + private void removeTagItem(String guid) { + for (int j=listManager.getTagIndex().size()-1; j>=0; j--) { + String parent = listManager.getTagIndex().get(j).getParentGuid(); + if (parent != null && parent.equals(guid)) { + //Remove this tag's children + removeTagItem(listManager.getTagIndex().get(j).getGuid()); + } + } + //Now, remove this tag + removeListTagName(guid); + conn.getTagTable().expungeTag(guid, true); + for (int a=0; a x = tagTree.selectedItems(); + for (int i=0; i selections = tagTree.selectedItems(); + QTreeWidgetItem currentSelection; + selectedTagGUIDs.clear(); + for (int i=0; i 0) { + menuBar.tagEditAction.setEnabled(true); + menuBar.tagDeleteAction.setEnabled(true); + } + else { + menuBar.tagEditAction.setEnabled(false); + menuBar.tagDeleteAction.setEnabled(false); + } + listManager.setSelectedTags(selectedTagGUIDs); + listManager.loadNotesIndex(); + noteIndexUpdated(false); + logger.log(logger.HIGH, "Leaving NeverNote.tagTreeSelection"); + } + // trigger the tag index to be refreshed + @SuppressWarnings("unused") + private void tagIndexUpdated() { + tagIndexUpdated(true); + } + private void tagIndexUpdated(boolean reload) { + logger.log(logger.HIGH, "Entering NeverNote.tagIndexUpdated"); + if (selectedTagGUIDs == null) + selectedTagGUIDs = new ArrayList(); +// selectedTagGUIDs.clear(); // clear out old entries + + tagTree.blockSignals(true); + if (reload) + tagTree.load(listManager.getTagIndex()); + for (int i=selectedTagGUIDs.size()-1; i>=0; i--) { + boolean found = tagTree.selectGuid(selectedTagGUIDs.get(i)); + if (!found) + selectedTagGUIDs.remove(i); + } + tagTree.blockSignals(false); + + browserWindow.setTag(getTagNamesForNote(currentNote)); + logger.log(logger.HIGH, "Leaving NeverNote.tagIndexUpdated"); + } + // Show/Hide note information + private void toggleTagWindow() { + logger.log(logger.HIGH, "Entering NeverNote.toggleTagWindow"); + if (tagTree.isVisible()) + tagTree.hide(); + else + tagTree.show(); + menuBar.hideTags.setChecked(tagTree.isVisible()); + Global.saveWindowVisible("tagTree", tagTree.isVisible()); + logger.log(logger.HIGH, "Leaving NeverNote.toggleTagWindow"); + } + // A note's tags have been updated + @SuppressWarnings("unused") + private void updateNoteTags(String guid, List tags) { + listManager.saveNoteTags(guid, tags); + listManager.countTagResults(listManager.getNoteIndex()); + StringBuffer names = new StringBuffer(""); + for (int i=0; i v = new Vector(); + List guids = n.getTagGuids(); + + if (guids == null) + return ""; + + for (int i=0; i comparator = Collections.reverseOrder(); + Collections.sort(v,comparator); + Collections.reverse(v); + + for (int i = 0; i0) + buffer.append(", "); + buffer.append(v.get(i)); + } + + logger.log(logger.HIGH, "Leaving NeverNote.getTagNamesForNote"); + return buffer.toString(); + } + // Tags were added via dropping notes from the note list + @SuppressWarnings("unused") + private void tagsAdded(String noteGuid, String tagGuid) { + String tagName = null; + for (int i=0; i ix = noteTableView.model.itemData(modelIndex); + String titleGuid = (String)ix.values().toArray()[0]; + if (titleGuid.equals(noteGuid)) { + String text = (String)noteTableView.model.data(i, Global.noteTableTagPosition); + if (!text.trim().equals("")) + text = text + Global.tagDelimeter + " " +tagName; + else + text = tagName; + noteTableView.model.setData(i, Global.noteTableTagPosition, text); + noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false"); + if (noteGuid.equals(currentNoteGuid)) + browserWindow.setTag(text); + i=noteTableView.model.rowCount(); + } + } + } + } + private void clearTagFilter() { + tagTree.blockSignals(true); + tagTree.clearSelection(); + menuBar.noteRestoreAction.setVisible(false); + menuBar.tagEditAction.setEnabled(false); + menuBar.tagDeleteAction.setEnabled(false); + selectedTagGUIDs.clear(); + listManager.setSelectedTags(selectedTagGUIDs); + tagTree.blockSignals(false); + } + + + //*************************************************************** + //*************************************************************** + //** These functions deal with Saved Search menu items + //*************************************************************** + //*************************************************************** + // Add a new notebook + @SuppressWarnings("unused") + private void addSavedSearch() { + logger.log(logger.HIGH, "Inside NeverNote.addSavedSearch"); + SavedSearchEdit edit = new SavedSearchEdit(); + edit.setSearchList(listManager.getSavedSearchIndex()); + edit.exec(); + + if (!edit.okPressed()) + return; + + Calendar currentTime = new GregorianCalendar(); + Long l = new Long(currentTime.getTimeInMillis()); + String randint = new String(Long.toString(l)); + + SavedSearch search = new SavedSearch(); + search.setUpdateSequenceNum(0); + search.setGuid(randint); + search.setName(edit.getName()); + search.setQuery(edit.getQuery()); + search.setFormat(QueryFormat.USER); + listManager.getSavedSearchIndex().add(search); + conn.getSavedSearchTable().addSavedSearch(search, true); + savedSearchIndexUpdated(); + logger.log(logger.HIGH, "Leaving NeverNote.addSavedSearch"); + } + // Edit an existing tag + @SuppressWarnings("unused") + private void editSavedSearch() { + logger.log(logger.HIGH, "Entering NeverNote.editSavedSearch"); + SavedSearchEdit edit = new SavedSearchEdit(); + edit.setTitle("Edit Search"); + List selections = savedSearchTree.selectedItems(); + QTreeWidgetItem currentSelection; + currentSelection = selections.get(0); + String guid = currentSelection.text(1); + SavedSearch s = conn.getSavedSearchTable().getSavedSearch(guid); + edit.setName(currentSelection.text(0)); + edit.setQuery(s.getQuery()); + edit.setSearchList(listManager.getSavedSearchIndex()); + edit.exec(); + + if (!edit.okPressed()) + return; + + List list = listManager.getSavedSearchIndex(); + SavedSearch search = null; + boolean found = false; + for (int i=0; i selections = savedSearchTree.selectedItems(); + for (int i=selections.size()-1; i>=0; i--) { + QTreeWidgetItem currentSelection; + currentSelection = selections.get(i); + for (int j=0; j selections = savedSearchTree.selectedItems(); + QTreeWidgetItem currentSelection; + selectedSavedSearchGUID = ""; + for (int i=0; i selections = savedSearchTree.selectedItems(); + + if (selections.size() > 0) { + menuBar.savedSearchEditAction.setEnabled(true); + menuBar.savedSearchDeleteAction.setEnabled(true); + selectedSavedSearchGUID = selections.get(0).text(1); + SavedSearch s = conn.getSavedSearchTable().getSavedSearch(selectedSavedSearchGUID); + searchField.setEditText(s.getQuery()); + } else { + menuBar.savedSearchEditAction.setEnabled(false); + menuBar.savedSearchDeleteAction.setEnabled(false); + selectedSavedSearchGUID = ""; + searchField.setEditText(""); + } + searchFieldChanged(); + + logger.log(logger.HIGH, "Leaving NeverNote.updateSavedSearchSelection()"); + + + } + // Show/Hide note information + private void toggleSavedSearchWindow() { + logger.log(logger.HIGH, "Entering NeverNote.toggleSavedSearchWindow"); + if (savedSearchTree.isVisible()) + savedSearchTree.hide(); + else + savedSearchTree.show(); + menuBar.hideSavedSearches.setChecked(savedSearchTree.isVisible()); + + Global.saveWindowVisible("savedSearchTree", savedSearchTree.isVisible()); + logger.log(logger.HIGH, "Leaving NeverNote.toggleSavedSearchWindow"); + } + + + + + //*************************************************************** + //*************************************************************** + //** These functions deal with Help menu & tool menu items + //*************************************************************** + //*************************************************************** + // Show database status + @SuppressWarnings("unused") + private void databaseStatus() { + waitCursor(true); + int dirty = conn.getNoteTable().getDirtyCount(); + int unindexed = conn.getNoteTable().getUnindexedCount(); + DatabaseStatus status = new DatabaseStatus(); + status.setUnsynchronized(dirty); + status.setUnindexed(unindexed); + status.setNoteCount(conn.getNoteTable().getNoteCount()); + status.setNotebookCount(listManager.getNotebookIndex().size()); + status.setSavedSearchCount(listManager.getSavedSearchIndex().size()); + status.setTagCount(listManager.getTagIndex().size()); + status.setResourceCount(conn.getNoteTable().noteResourceTable.getResourceCount()); + status.setWordCount(conn.getWordsTable().getWordCount()); + waitCursor(false); + status.exec(); + } + // Compact the database + @SuppressWarnings("unused") + private void compactDatabase() { + logger.log(logger.HIGH, "Entering NeverNote.compactDatabase"); + if (QMessageBox.question(this, "Confirmation", "This will free unused space in the database, "+ + "but please be aware that depending upon the size of your database this can be time consuming " + + "and NeverNote will be unresponsive until it is complete. Do you wish to continue?", + QMessageBox.StandardButton.Yes, + QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) { + return; + } + setMessage("Compacting database."); + waitCursor(true); + listManager.compactDatabase(); + waitCursor(false); + setMessage("Database compact is complete."); + logger.log(logger.HIGH, "Leaving NeverNote.compactDatabase"); + } + @SuppressWarnings("unused") + private void accountInformation() { + logger.log(logger.HIGH, "Entering NeverNote.accountInformation"); + AccountDialog dialog = new AccountDialog(); + dialog.show(); + logger.log(logger.HIGH, "Leaving NeverNote.accountInformation"); + } + @SuppressWarnings("unused") + private void releaseNotes() { + logger.log(logger.HIGH, "Entering NeverNote.releaseNotes"); + QDialog dialog = new QDialog(this); + QHBoxLayout layout = new QHBoxLayout(); + QTextEdit textBox = new QTextEdit(); + layout.addWidget(textBox); + textBox.setReadOnly(true); + QFile file = new QFile(Global.getDirectoryPath()+"release.txt"); + if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly, + QIODevice.OpenModeFlag.Text))) + return; + textBox.setText(file.readAll().toString()); + file.close(); + dialog.setWindowTitle("Release Notes"); + dialog.setLayout(layout); + dialog.show(); + logger.log(logger.HIGH, "Leaving NeverNote.releaseNotes"); + } + // Called when user picks Log from the help menu + @SuppressWarnings("unused") + private void logger() { + logger.log(logger.HIGH, "Entering NeverNote.logger"); + QDialog dialog = new QDialog(this); + QHBoxLayout layout = new QHBoxLayout(); + QListWidget textBox = new QListWidget(); + layout.addWidget(textBox); + textBox.addItems(emitLog); + + dialog.setLayout(layout); + dialog.setWindowTitle("Mesasge Log"); + dialog.show(); + logger.log(logger.HIGH, "Leaving NeverNote.logger"); + } + // Menu option "help/about" was selected + @SuppressWarnings("unused") + private void about() { + logger.log(logger.HIGH, "Entering NeverNote.about"); + QMessageBox.about(this, + tr("About NeverNote"), + tr("

NeverNote


Version "+Global.version+"
Evernote" + +" Generic client.

" + +"Licensed under GPL v2.


" + +"Evernote is copyright 2001-2010 by Evernote Corporation
" + +"Jambi and QT are the licensed trademark of Nokia Corporation
" + +"PDFRenderer is licened under the LGPL
" + +"Jazzy is licened under the LGPL
" + +"Java is a registered trademark of Sun Microsystems.

")); + logger.log(logger.HIGH, "Leaving NeverNote.about"); + } + // Hide the entire left hand side + @SuppressWarnings("unused") + private void toggleLeftSide() { + boolean hidden; + + hidden = !menuBar.hideLeftSide.isChecked(); + menuBar.hideLeftSide.setChecked(!hidden); + + if (notebookTree.isVisible() != hidden) + toggleNotebookWindow(); + if (savedSearchTree.isVisible() != hidden) + toggleSavedSearchWindow(); + if (tagTree.isVisible() != hidden) + toggleTagWindow(); + if (attributeTree.isVisible() != hidden) + toggleAttributesWindow(); + if (trashTree.isVisible() != hidden) + toggleTrashWindow(); + + Global.saveWindowVisible("leftPanel", hidden); + + } + + + //*************************************************************** + //*************************************************************** + //** These functions deal with the Toolbar + //*************************************************************** + //*************************************************************** + // Text in the search bar has been cleared + private void searchFieldCleared() { + searchField.setEditText(""); + saveNoteIndexWidth(); + } + // text in the search bar changed. We only use this to tell if it was cleared, + // otherwise we trigger off searchFieldChanged. + @SuppressWarnings("unused") + private void searchFieldTextChanged(String text) { + if (text.trim().equals("")) { + searchFieldCleared(); + if (searchPerformed) { + noteCache.clear(); + listManager.setEnSearch(""); +///// listManager.clearNoteIndexSearch(); + //noteIndexUpdated(true); + listManager.loadNotesIndex(); + refreshEvernoteNote(true); + noteIndexUpdated(false); + } + searchPerformed = false; + } + } + // Text in the toolbar has changed + private void searchFieldChanged() { + logger.log(logger.HIGH, "Entering NeverNote.searchFieldChanged"); + noteCache.clear(); + saveNoteIndexWidth(); + String text = searchField.currentText(); + listManager.setEnSearch(text.trim()); + listManager.loadNotesIndex(); +//--->>> noteIndexUpdated(true); + noteIndexUpdated(false); + refreshEvernoteNote(true); + searchPerformed = true; + logger.log(logger.HIGH, "Leaving NeverNote.searchFieldChanged"); + } + // Build the window tool bar + private void setupToolBar() { + logger.log(logger.HIGH, "Entering NeverNote.setupToolBar"); + toolBar = addToolBar(tr("toolBar")); + + prevButton = toolBar.addAction("Previous"); + QIcon prevIcon = new QIcon(iconPath+"back.png"); + prevButton.setIcon(prevIcon); + prevButton.triggered.connect(this, "previousViewedAction()"); + + nextButton = toolBar.addAction("Next"); + QIcon nextIcon = new QIcon(iconPath+"forward.png"); + nextButton.setIcon(nextIcon); + nextButton.triggered.connect(this, "nextViewedAction()"); + + upButton = toolBar.addAction("Up"); + QIcon upIcon = new QIcon(iconPath+"up.png"); + upButton.setIcon(upIcon); + upButton.triggered.connect(this, "upAction()"); + + downButton = toolBar.addAction("Down"); + QIcon downIcon = new QIcon(iconPath+"down.png"); + downButton.setIcon(downIcon); + downButton.triggered.connect(this, "downAction()"); + + synchronizeButton = toolBar.addAction("Synchronize"); + synchronizeAnimation = new ArrayList(); + 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.triggered.connect(this, "evernoteSync()"); + + printButton = toolBar.addAction("Print"); + QIcon printIcon = new QIcon(iconPath+"print.png"); + printButton.setIcon(printIcon); + printButton.triggered.connect(this, "printNote()"); + + tagButton = toolBar.addAction("Tag"); + QIcon tagIcon = new QIcon(iconPath+"tag.png"); + tagButton.setIcon(tagIcon); + tagButton.triggered.connect(browserWindow, "modifyTags()"); + + attributeButton = toolBar.addAction("Attributes"); + QIcon attributeIcon = new QIcon(iconPath+"attribute.png"); + attributeButton.setIcon(attributeIcon); + attributeButton.triggered.connect(this, "toggleNoteInformation()"); + + emailButton = toolBar.addAction("Email"); + QIcon emailIcon = new QIcon(iconPath+"email.png"); + emailButton.setIcon(emailIcon); + emailButton.triggered.connect(this, "emailNote()"); + + deleteButton = toolBar.addAction("Delete"); + QIcon deleteIcon = new QIcon(iconPath+"delete.png"); + deleteButton.setIcon(deleteIcon); + deleteButton.triggered.connect(this, "deleteNote()"); + + newButton = toolBar.addAction("New"); + QIcon newIcon = new QIcon(iconPath+"new.png"); + newButton.triggered.connect(this, "addNote()"); + newButton.setIcon(newIcon); + toolBar.addSeparator(); + toolBar.addWidget(new QLabel("Quota:")); + toolBar.addWidget(quotaBar); + //quotaBar.setSizePolicy(Policy.Minimum, Policy.Minimum); + updateQuotaBar(); + + // Setup the zoom + zoomSpinner = new QSpinBox(); + zoomSpinner.setMinimum(10); + zoomSpinner.setMaximum(1000); + zoomSpinner.setAccelerated(true); + zoomSpinner.setSingleStep(10); + zoomSpinner.setValue(100); + zoomSpinner.valueChanged.connect(this, "zoomChanged()"); + toolBar.addWidget(new QLabel("Zoom")); + toolBar.addWidget(zoomSpinner); + + //toolBar.addWidget(new QLabel(" ")); + toolBar.addSeparator(); + toolBar.addWidget(new QLabel(" Search:")); + toolBar.addWidget(searchField); + QSizePolicy sizePolicy = new QSizePolicy(); + sizePolicy.setHorizontalPolicy(Policy.MinimumExpanding); + searchField.setSizePolicy(sizePolicy); + searchField.setInsertPolicy(InsertPolicy.InsertAtTop); + + searchClearButton = toolBar.addAction("Search Clear"); + QIcon searchClearIcon = new QIcon(iconPath+"searchclear.png"); + searchClearButton.setIcon(searchClearIcon); + searchClearButton.triggered.connect(this, "searchFieldCleared()"); + + logger.log(logger.HIGH, "Leaving NeverNote.setupToolBar"); + } + // Update the sychronize button picture + @SuppressWarnings("unused") + private void updateSyncButton() { + synchronizeFrame++; + if (synchronizeFrame == 4) + synchronizeFrame = 0; + synchronizeButton.setIcon(synchronizeAnimation.get(synchronizeFrame)); + } + // Synchronize with Evernote + @SuppressWarnings("unused") + private void evernoteSync() { + logger.log(logger.HIGH, "Entering NeverNote.evernoteSync"); + if (!Global.isConnected) + remoteConnect(); + if (Global.isConnected) + synchronizeAnimationTimer.start(200); + syncTimer(); + logger.log(logger.HIGH, "Leaving NeverNote.evernoteSync"); + } + private void updateQuotaBar() { + long limit = Global.getUploadLimit(); + long amount = Global.getUploadAmount(); + if (amount>0 && limit>0) { + int percent =(int)(amount*100/limit); + quotaBar.setValue(percent); + } else + quotaBar.setValue(0); + } + // Zoom changed + @SuppressWarnings("unused") + private void zoomChanged() { + browserWindow.getBrowser().setZoomFactor(new Double(zoomSpinner.value())/100); + } + + //**************************************************************** + //**************************************************************** + //* System Tray functions + //**************************************************************** + //**************************************************************** + private void trayToggleVisible() { + if (isVisible()) { + hide(); + } else { + show(); + raise(); + } + } + @SuppressWarnings("unused") + private void trayActivated(QSystemTrayIcon.ActivationReason reason) { + if (reason == QSystemTrayIcon.ActivationReason.DoubleClick) { + String name = QSystemTrayIcon.MessageIcon.resolve(reason.value()).name(); + trayToggleVisible(); + } + } + + + //*************************************************************** + //*************************************************************** + //** These functions deal with the trash tree + //*************************************************************** + //*************************************************************** + // Setup the tree containing the trash. + @SuppressWarnings("unused") + private void trashTreeSelection() { + logger.log(logger.HIGH, "Entering NeverNote.trashTreeSelection"); + + clearNotebookFilter(); + clearTagFilter(); + clearAttributeFilter(); + clearSavedSearchFilter(); + + String tempGuid = currentNoteGuid; + +// currentNoteGuid = ""; + currentNote = new Note(); + selectedNoteGUIDs.clear(); + listManager.getSelectedNotebooks().clear(); + listManager.getSelectedTags().clear(); + listManager.setSelectedSavedSearch(""); + browserWindow.clear(); + + // toggle the add buttons + newButton.setEnabled(!newButton.isEnabled()); + menuBar.noteAdd.setEnabled(newButton.isEnabled()); + menuBar.noteAdd.setVisible(true); + + List selections = trashTree.selectedItems(); + if (selections.size() == 0) { + currentNoteGuid = trashNoteGuid; + trashNoteGuid = tempGuid; + Global.showDeleted = false; + menuBar.noteRestoreAction.setEnabled(false); + menuBar.noteRestoreAction.setVisible(false); + } + else { + currentNoteGuid = trashNoteGuid; + trashNoteGuid = tempGuid; + menuBar.noteRestoreAction.setEnabled(true); + menuBar.noteRestoreAction.setVisible(true); + Global.showDeleted = true; + } + listManager.loadNotesIndex(); + noteIndexUpdated(false); +//// browserWindow.setEnabled(newButton.isEnabled()); + browserWindow.setReadOnly(!newButton.isEnabled()); + logger.log(logger.HIGH, "Leaving NeverNote.trashTreeSelection"); + } + // Empty the trash file + @SuppressWarnings("unused") + private void emptyTrash() { +// browserWindow.clear(); + listManager.emptyTrash(); + if (trashTree.selectedItems().size() > 0) { + listManager.getSelectedNotebooks().clear(); + listManager.getSelectedTags().clear(); + listManager.setSelectedSavedSearch(""); + newButton.setEnabled(!newButton.isEnabled()); + menuBar.noteAdd.setEnabled(newButton.isEnabled()); + menuBar.noteAdd.setVisible(true); + browserWindow.clear(); + + clearTagFilter(); + clearNotebookFilter(); + clearSavedSearchFilter(); + clearAttributeFilter(); + + Global.showDeleted = false; + menuBar.noteRestoreAction.setEnabled(false); + menuBar.noteRestoreAction.setVisible(false); + + listManager.loadNotesIndex(); +//--->>> noteIndexUpdated(true); + noteIndexUpdated(false); + } + } + // Show/Hide trash window + private void toggleTrashWindow() { + logger.log(logger.HIGH, "Entering NeverNote.toggleTrashWindow"); + if (trashTree.isVisible()) + trashTree.hide(); + else + trashTree.show(); + menuBar.hideTrash.setChecked(trashTree.isVisible()); + + Global.saveWindowVisible("trashTree", trashTree.isVisible()); + logger.log(logger.HIGH, "Leaving NeverNote.trashWindow"); + } + private void clearTrashFilter() { + Global.showDeleted = false; + newButton.setEnabled(true); + menuBar.noteAdd.setEnabled(true); + menuBar.noteAdd.setVisible(true); + trashTree.blockSignals(true); + trashTree.clearSelection(); + trashTree.blockSignals(false); + + } + + + //*************************************************************** + //*************************************************************** + //** These functions deal with connection settings + //*************************************************************** + //*************************************************************** + // SyncRunner had a problem and things are disconnected + @SuppressWarnings("unused") + private void remoteErrorDisconnect() { + menuBar.connectAction.setText("Connect"); + menuBar.connectAction.setToolTip("Connect to Evernote"); + menuBar.synchronizeAction.setEnabled(false); + synchronizeAnimationTimer.stop(); + return; + } + // Do a manual connect/disconnect + private void remoteConnect() { + logger.log(logger.HIGH, "Entering NeverNote.remoteConnect"); + + if (Global.isConnected) { + Global.isConnected = false; + syncRunner.enDisconnect(); + setupConnectMenuOptions(); + setupOnlineMenu(); + return; + } + + AESEncrypter aes = new AESEncrypter(); + try { + aes.decrypt(new FileInputStream(Global.getDirectoryPath()+"secure.txt")); + } catch (FileNotFoundException e) { + // File not found, so we'll just get empty strings anyway. + } + String userid = aes.getUserid(); + String password = aes.getPassword(); + if (!userid.equals("") && !password.equals("")) { + Global.username = userid; + Global.password = password; + } + + // Show the login dialog box + if (!Global.automaticLogin() || userid.equals("")|| password.equals("")) { + LoginDialog login = new LoginDialog(); + login.exec(); + + if (!login.okPressed()) { + return; + } + + Global.username = login.getUserid(); + Global.password = login.getPassword(); + } + syncRunner.username = Global.username; + syncRunner.password = Global.password; + syncRunner.userStoreUrl = Global.userStoreUrl; + syncRunner.noteStoreUrl = Global.noteStoreUrl; + syncRunner.noteStoreUrlBase = Global.noteStoreUrlBase; + syncRunner.enConnect(); + Global.isConnected = syncRunner.isConnected; + setupOnlineMenu(); + setupConnectMenuOptions(); + logger.log(logger.HIGH, "Leaving NeverNote.remoteConnect"); + } + private void setupConnectMenuOptions() { + logger.log(logger.HIGH, "entering NeverNote.setupConnectMenuOptions"); + if (!Global.isConnected) { + menuBar.connectAction.setText("Connect"); + menuBar.connectAction.setToolTip("Connect to Evernote"); + menuBar.synchronizeAction.setEnabled(false); + } else { + menuBar.connectAction.setText("Disconnect"); + menuBar.connectAction.setToolTip("Disconnect from Evernote"); + menuBar.synchronizeAction.setEnabled(true); + } + logger.log(logger.HIGH, "Leaving NeverNote.setupConnectionMenuOptions"); + } + + + + //*************************************************************** + //*************************************************************** + //** These functions deal with the GUI Attribute tree + //*************************************************************** + //*************************************************************** + @SuppressWarnings("unused") + private void attributeTreeClicked(QTreeWidgetItem item, Integer integer) { + + clearTagFilter(); + clearNotebookFilter(); + clearTrashFilter(); + clearSavedSearchFilter(); + + if (attributeTreeSelected == null || item.nativeId() != attributeTreeSelected.nativeId()) { + if (item.childCount() > 0) { + item.setSelected(false); + } else { + Global.createdBeforeFilter.reset(); + Global.createdSinceFilter.reset(); + Global.changedBeforeFilter.reset(); + Global.changedSinceFilter.reset(); + Global.containsFilter.reset(); + attributeTreeSelected = item; + DateAttributeFilterTable f = null; + f = findDateAttributeFilterTable(item.parent()); + if (f!=null) + f.select(item.text(0)); + else { + String text = item.text(0); + Global.containsFilter.select(text); + } + } + listManager.loadNotesIndex(); + noteIndexUpdated(false); + return; + } + attributeTreeSelected = null; + item.setSelected(false); + Global.createdBeforeFilter.reset(); + Global.createdSinceFilter.reset(); + Global.changedBeforeFilter.reset(); + Global.changedSinceFilter.reset(); + Global.containsFilter.reset(); + listManager.loadNotesIndex(); + noteIndexUpdated(false); + } + // This determines what attribute filter we need, depending upon the selection + private DateAttributeFilterTable findDateAttributeFilterTable(QTreeWidgetItem w) { + if (w.parent() != null && w.childCount() > 0) { + QTreeWidgetItem parent = w.parent(); + if (parent.text(0).equalsIgnoreCase("created") && + w.text(0).equalsIgnoreCase("since")) + return Global.createdSinceFilter; + if (parent.text(0).equalsIgnoreCase("created") && + w.text(0).equalsIgnoreCase("before")) + return Global.createdBeforeFilter; + if (parent.text(0).equalsIgnoreCase("last modified") && + w.text(0).equalsIgnoreCase("since")) + return Global.changedSinceFilter; + if (parent.text(0).equalsIgnoreCase("last modified") && + w.text(0).equalsIgnoreCase("before")) + return Global.changedBeforeFilter; + } + return null; + } + // Show/Hide attribute search window + private void toggleAttributesWindow() { + logger.log(logger.HIGH, "Entering NeverNote.toggleAttributesWindow"); + if (attributeTree.isVisible()) + attributeTree.hide(); + else + attributeTree.show(); + menuBar.hideAttributes.setChecked(attributeTree.isVisible()); + + Global.saveWindowVisible("attributeTree", attributeTree.isVisible()); + logger.log(logger.HIGH, "Leaving NeverNote.toggleAttributeWindow"); + } + private void clearAttributeFilter() { + Global.createdBeforeFilter.reset(); + Global.createdSinceFilter.reset(); + Global.changedBeforeFilter.reset(); + Global.changedSinceFilter.reset(); + Global.containsFilter.reset(); + attributeTreeSelected = null; + attributeTree.blockSignals(true); + attributeTree.clearSelection(); + attributeTree.blockSignals(false); + } + + + //*************************************************************** + //*************************************************************** + //** These functions deal with the GUI Note index table + //*************************************************************** + //*************************************************************** + // Initialize the note list table + private void initializeNoteTable() { + logger.log(logger.HIGH, "Entering NeverNote.initializeNoteTable"); + noteTableView.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection); + noteTableView.selectionModel().selectionChanged.connect(this, "noteTableSelection()"); + logger.log(logger.HIGH, "Leaving NeverNote.initializeNoteTable"); + } + // Show/Hide trash window + @SuppressWarnings("unused") + private void toggleNoteListWindow() { + logger.log(logger.HIGH, "Entering NeverNote.toggleNoteListWindow"); + if (noteTableView.isVisible()) + noteTableView.hide(); + else + noteTableView.show(); + menuBar.hideNoteList.setChecked(noteTableView.isVisible()); + + Global.saveWindowVisible("noteList", noteTableView.isVisible()); + logger.log(logger.HIGH, "Leaving NeverNote.toggleNoteListWindow"); + } + // Handle the event that a user selects a note from the table + @SuppressWarnings("unused") + private void noteTableSelection() { + logger.log(logger.HIGH, "Entering NeverNote.noteTableSelection"); + saveNote(); + if (historyGuids.size() == 0) { + historyGuids.add(currentNoteGuid); + historyPosition = 1; + } + noteTableView.showColumn(Global.noteTableGuidPosition); + + List selections = noteTableView.selectionModel().selectedRows(); + noteTableView.hideColumn(Global.noteTableGuidPosition); + + if (selections.size() > 0) { + QModelIndex index; + menuBar.noteDuplicateAction.setEnabled(true); + menuBar.noteOnlineHistoryAction.setEnabled(true); + menuBar.noteMergeAction.setEnabled(true); + selectedNoteGUIDs.clear(); + if (selections.size() != 1 || Global.showDeleted) { + menuBar.noteDuplicateAction.setEnabled(false); + } + if (selections.size() != 1 || !Global.isConnected) { + menuBar.noteOnlineHistoryAction.setEnabled(false); + } + if (selections.size() == 1) { + menuBar.noteMergeAction.setEnabled(false); + } + for (int i=0; i ix = noteTableView.proxyModel.itemData(index); + currentNoteGuid = (String)ix.values().toArray()[0]; + selectedNoteGUIDs.add(currentNoteGuid); + } + } + + nextButton.setEnabled(true); + prevButton.setEnabled(true); + if (!fromHistory) { + int endPosition = historyGuids.size()-1; + for (int j=historyPosition; j<=endPosition; j++) { + historyGuids.remove(historyGuids.size()-1); + } + historyGuids.add(currentNoteGuid); + historyPosition = historyGuids.size(); + } + if (historyPosition <= 1) + prevButton.setEnabled(false); + if (historyPosition == historyGuids.size()) + nextButton.setEnabled(false); + + fromHistory = false; + scrollToGuid(currentNoteGuid); + refreshEvernoteNote(true); + logger.log(logger.HIGH, "Leaving NeverNote.noteTableSelection"); + } + // Trigger a refresh when the note db has been updated + private void noteIndexUpdated(boolean reload) { + logger.log(logger.HIGH, "Entering NeverNote.noteIndexUpdated"); + Global.traceReset(); + saveNote(); + refreshEvernoteNoteList(); + logger.log(logger.HIGH, "Calling note table reload in NeverNote.noteIndexUpdated() - "+reload); + noteTableView.load(listManager, reload); + scrollToGuid(currentNoteGuid); + logger.log(logger.HIGH, "Leaving NeverNote.noteIndexUpdated"); + } + // Called when the list of notes is updated + private void refreshEvernoteNoteList() { + logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNoteList"); + browserWindow.setDisabled(false); + if (selectedNoteGUIDs == null) + selectedNoteGUIDs = new ArrayList(); + selectedNoteGUIDs.clear(); // clear out old entries + + String saveCurrentNoteGuid = new String(); + String tempNoteGuid = new String(); + + historyGuids.clear(); + historyPosition = 0; + prevButton.setEnabled(false); + nextButton.setEnabled(false); + + if (currentNoteGuid == null) + currentNoteGuid = new String(); + + for (Note note : listManager.getNoteIndex()) { + tempNoteGuid = note.getGuid(); + if (currentNoteGuid.equals(tempNoteGuid)) { + saveCurrentNoteGuid = new String(tempNoteGuid); + } + } + + if (listManager.getNoteIndex().size() == 0) { + currentNoteGuid = ""; + currentNote = null; + browserWindow.clear(); + browserWindow.setDisabled(true); + } + + if (saveCurrentNoteGuid.equals("") && listManager.getNoteIndex().size() >0) { + currentNoteGuid = listManager.getNoteIndex().get(listManager.getNoteIndex().size()-1).getGuid(); + currentNote = listManager.getNoteIndex().get(listManager.getNoteIndex().size()-1); + refreshEvernoteNote(true); + } else { + refreshEvernoteNote(false); + } + reloadTagTree(); + + logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNoteList"); + } + // Called when the previous arrow button is clicked + @SuppressWarnings("unused") + private void previousViewedAction() { + if (!prevButton.isEnabled()) + return; + if (historyPosition == 0) + return; + historyPosition--; + if (historyPosition <= 0) + return; + String historyGuid = historyGuids.get(historyPosition-1); + fromHistory = true; + for (int i=0; i ix = noteTableView.model().itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + if (tableGuid.equals(historyGuid)) { + noteTableView.selectRow(i); + return; + } + } + } + } + @SuppressWarnings("unused") + private void nextViewedAction() { + if (!nextButton.isEnabled()) + return; + String historyGuid = historyGuids.get(historyPosition); + historyPosition++; + fromHistory = true; + for (int i=0; i ix = noteTableView.model().itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + if (tableGuid.equals(historyGuid)) { + noteTableView.selectRow(i); + return; + } + } + } + } + // Called when the up arrow is clicked + @SuppressWarnings("unused") + private void upAction() { + List selections = noteTableView.selectionModel().selectedRows(); + int row = selections.get(0).row(); + if (row > 0) { + noteTableView.selectRow(row-1); + } + } + // Called when the down arrow is clicked + @SuppressWarnings("unused") + private void downAction() { + List selections = noteTableView.selectionModel().selectedRows(); + int row = selections.get(0).row(); + int max = noteTableView.model.rowCount(); + if (row < max-1) { + noteTableView.selectRow(row+1); + } + } + // Update a tag string for a specific note in the list + @SuppressWarnings("unused") + private void updateListTags(String guid, List tags) { + logger.log(logger.HIGH, "Entering NeverNote.updateListTags"); + StringBuffer tagBuffer = new StringBuffer(); + for (int i=0; i ix = noteTableView.model.itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + if (tableGuid.equals(guid)) { + noteTableView.model.setData(i, Global.noteTableTagPosition,tagBuffer.toString()); + noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false"); + return; + } + } + } + logger.log(logger.HIGH, "Leaving NeverNote.updateListTags"); + } + // Update a title for a specific note in the list + @SuppressWarnings("unused") + private void updateListTitle(String guid, String title) { + logger.log(logger.HIGH, "Entering NeverNote.updateListTitle"); + + for (int i=0; i ix = noteTableView.proxyModel.itemData(modelIndex); + SortedMap ix = noteTableView.model.itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + if (tableGuid.equals(guid)) { + noteTableView.model.setData(i, Global.noteTableTitlePosition,title); + noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false"); + return; + } + } + } + logger.log(logger.HIGH, "Leaving NeverNote.updateListTitle"); + } + // Update a title for a specific note in the list + @SuppressWarnings("unused") + private void updateListAuthor(String guid, String author) { + logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor"); + + for (int i=0; i ix = noteTableView.proxyModel.itemData(modelIndex); + SortedMap ix = noteTableView.model.itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + if (tableGuid.equals(guid)) { + noteTableView.model.setData(i, Global.noteTableAuthorPosition,author); + noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false"); + return; + } + } + } + logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor"); + } + private void updateListNoteNotebook(String guid, String notebook) { + logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor"); + + for (int i=0; i ix = noteTableView.proxyModel.itemData(modelIndex); + SortedMap ix = noteTableView.model.itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + if (tableGuid.equals(guid)) { + noteTableView.model.setData(i, Global.noteTableNotebookPosition,notebook); + noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false"); + return; + } + } + } + logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor"); + } + // Update a title for a specific note in the list + @SuppressWarnings("unused") + private void updateListSourceUrl(String guid, String url) { + logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor"); + + for (int i=0; i ix = noteTableView.proxyModel.itemData(modelIndex); + SortedMap ix = noteTableView.model.itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + if (tableGuid.equals(guid)) { + noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false"); + noteTableView.model.setData(i, Global.noteTableSourceUrlPosition,url); + return; + } + } + } + logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor"); + } + private void updateListGuid(String oldGuid, String newGuid) { + logger.log(logger.HIGH, "Entering NeverNote.updateListTitle"); + + for (int i=0; i ix = noteTableView.model.itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + if (tableGuid.equals(oldGuid)) { + noteTableView.model.setData(i, Global.noteTableGuidPosition,newGuid); + //noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false"); + return; + } + } + } + logger.log(logger.HIGH, "Leaving NeverNote.updateListTitle"); + } + private void updateListTagName(String guid) { + logger.log(logger.HIGH, "Entering NeverNote.updateTagName"); + + for (int j=0; j ix = noteTableView.model.itemData(modelIndex); + String noteGuid = (String)ix.values().toArray()[0]; + if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) { + noteTableView.model.setData(i, Global.noteTableTagPosition, newName); + //noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false"); + i=noteTableView.model.rowCount(); + } + } + } + } + } + logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebook"); + } + private void removeListTagName(String guid) { + logger.log(logger.HIGH, "Entering NeverNote.updateTagName"); + + for (int j=0; j=0; i--) { + if (listManager.getNoteIndex().get(j).getTagGuids().get(i).equals(guid)) + listManager.getNoteIndex().get(j).getTagGuids().remove(i); + } + + String newName = listManager.getTagNamesForNote(listManager.getNoteIndex().get(j)); + for (int i=0; i ix = noteTableView.model.itemData(modelIndex); + String noteGuid = (String)ix.values().toArray()[0]; + if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) { + noteTableView.model.setData(i, Global.noteTableTagPosition, newName); +// noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false"); + i=noteTableView.model.rowCount(); + } + } + } + } + } + logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebook"); + } + private void updateListNotebookName(String oldName, String newName) { + logger.log(logger.HIGH, "Entering NeverNote.updateListNotebookName"); + + for (int i=0; i ix = noteTableView.model.itemData(modelIndex); + String tableName = (String)ix.values().toArray()[0]; + if (tableName.equalsIgnoreCase(oldName)) { +// noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false"); + noteTableView.model.setData(i, Global.noteTableNotebookPosition, newName); + } + } + } + logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebookName"); + } + @SuppressWarnings("unused") + private void updateListDateCreated(String guid, QDateTime date) { + logger.log(logger.HIGH, "Entering NeverNote.updateListDateCreated"); + + for (int i=0; i ix = noteTableView.model.itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + if (tableGuid.equals(guid)) { + noteTableView.model.setData(i, Global.noteTableCreationPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat())); + return; + } + } + } + logger.log(logger.HIGH, "Leaving NeverNote.updateListDateCreated"); + } + @SuppressWarnings("unused") + private void updateListDateSubject(String guid, QDateTime date) { + logger.log(logger.HIGH, "Entering NeverNote.updateListDateSubject"); + + for (int i=0; i ix = noteTableView.model.itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + if (tableGuid.equals(guid)) { + noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false"); + noteTableView.model.setData(i, Global.noteTableSubjectDatePosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat())); + return; + } + } + } + logger.log(logger.HIGH, "Leaving NeverNote.updateListDateCreated"); + } + @SuppressWarnings("unused") + private void updateListDateChanged(String guid, QDateTime date) { + logger.log(logger.HIGH, "Entering NeverNote.updateListDateChanged"); + + for (int i=0; i ix = noteTableView.model.itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + if (tableGuid.equals(guid)) { + noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false"); + noteTableView.model.setData(i, Global.noteTableChangedPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat())); + return; + } + } + } + logger.log(logger.HIGH, "Leaving NeverNote.updateListDateChanged"); + } + private void updateListDateChanged() { + logger.log(logger.HIGH, "Entering NeverNote.updateListDateChanged"); + QDateTime date = new QDateTime(QDateTime.currentDateTime()); + for (int i=0; i ix = noteTableView.model.itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + if (tableGuid.equals(currentNoteGuid)) { + noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false"); + noteTableView.model.setData(i, Global.noteTableChangedPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat())); + return; + } + } + } + logger.log(logger.HIGH, "Leaving NeverNote.updateListDateChanged"); + } + // Redo scroll + @SuppressWarnings("unused") + private void scrollToCurrentGuid() { + //scrollToGuid(currentNoteGuid); + List selections = noteTableView.selectionModel().selectedRows(); + if (selections.size() == 0) + return; + QModelIndex index = selections.get(0); + int row = selections.get(0).row(); + String guid = (String)index.model().index(row, Global.noteTableGuidPosition).data(); + scrollToGuid(guid); + } + // Scroll to a particular index item + private void scrollToGuid(String guid) { + if (currentNote == null || guid == null) + return; + if (currentNote.isActive() && Global.showDeleted) { + for (int i=0; i ix = noteTableView.model.itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + if (tableGuid.equals(selectedNoteGUIDs.get(j))) { + for (int k=0; k ix = noteTableView.model.itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + if (tableGuid.equals(currentNoteGuid)) { + noteTableView.model.setData(i, Global.noteTableSynchronizedPosition, "false"); + return; + } + } + } + logger.log(logger.EXTREME, "Leaving NeverNote.setNoteDirty()"); + } + 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()); + + 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()); + + logger.log(logger.EXTREME, "updating list manager"); + listManager.updateNoteContent(currentNoteGuid, browserWindow.getContent()); + logger.log(logger.EXTREME, "Updating title"); + listManager.updateNoteTitle(currentNoteGuid, browserWindow.getTitle()); + updateListDateChanged(); + + logger.log(logger.EXTREME, "Looking through note index for refreshed note"); + for (int i=0; i or encoded characters are ugly + js.append(""); + js.append(""); + js.append(""); + js.append(""); + js.append(""); + js.append(rebuildNoteHTML(currentNoteGuid, currentNote.getContent())); + js.append(""); + js.replace("", ""); + js.replace("", ""); + js.replace("", ""); + browserWindow.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()); + } + } 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)); + } + + browserWindow.getBrowser().page().setContentEditable(!inkNote); // We don't allow editing of ink notes + browserWindow.setNote(currentNote); + + // Build a list of non-closed notebooks + List nbooks = new ArrayList(); + for (int i=0; i 0) + browserWindow.setSubjectDate(currentNote.getAttributes().getSubjectDate()); + else + browserWindow.setSubjectDate(currentNote.getCreated()); + browserWindow.setUrl(currentNote.getAttributes().getSourceURL()); + browserWindow.setAllTags(listManager.getTagIndex()); + browserWindow.setCurrentTags(currentNote.getTagNames()); + noteDirty = false; + scrollToGuid(currentNoteGuid); + + browserWindow.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.currentDir+"res/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(); + menuBar.noteAttributes.setChecked(browserWindow.isExtended()); + logger.log(logger.HIGH, "Leaving NeverNote.toggleNoteInformation"); + } + // Listener triggered when a print button is pressed + @SuppressWarnings("unused") + private void printNote() { + logger.log(logger.HIGH, "Entering NeverNote.printNote"); + + QPrintDialog dialog = new QPrintDialog(); + if (dialog.exec() == QDialog.DialogCode.Accepted.value()) { + QPrinter printer = dialog.printer(); + browserWindow.getBrowser().print(printer); + } + logger.log(logger.HIGH, "Leaving NeverNote.printNote"); + + } + // Listener triggered when the email button is pressed + @SuppressWarnings("unused") + private void emailNote() { + logger.log(logger.HIGH, "Entering NeverNote.emailNote"); + + if (Desktop.isDesktopSupported()) { + Desktop desktop = Desktop.getDesktop(); + + String text2 = browserWindow.getContentsToEmail(); + QUrl url = new QUrl("mailto:"); + url.addQueryItem("subject", currentNote.getTitle()); + url.addQueryItem("body", QUrl.toPercentEncoding(text2).toString()); + QDesktopServices.openUrl(url); + } +/* + + if (desktop.isSupported(Desktop.Action.MAIL)) { + URI uriMailTo = null; + try { + //String text = browserWindow.getBrowser().page().currentFrame().toPlainText(); + String text = browserWindow.getContentsToEmail(); + //text = "" +text +""; + uriMailTo = new URI("mailto", "&SUBJECT="+currentNote.getTitle() + +"&BODY=" +text, null); + uriMailTo = new URI("mailto", "&SUBJECT="+currentNote.getTitle() + +"&ATTACHMENT=d:/test.pdf", null); + desktop.mail(uriMailTo); + } catch (URISyntaxException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + } + */ + logger.log(logger.HIGH, "Leaving NeverNote.emailNote"); + } + // Reindex all notes + @SuppressWarnings("unused") + private void fullReindex() { + logger.log(logger.HIGH, "Entering NeverNote.fullReindex"); + // If we are deleting non-trash notes + if (currentNote.getDeleted() == 0) { + if (QMessageBox.question(this, "Confirmation", "This will cause all notes & attachments to be reindexed, "+ + "but please be aware that depending upon the size of your database updating all these records " + + "can be time consuming and NeverNote will be unresponsive until it is complete. Do you wish to continue?", + QMessageBox.StandardButton.Yes, + QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) { + return; + } + } + waitCursor(true); + setMessage("Marking notes for reindex."); + conn.getNoteTable().reindexAllNotes(); + conn.getNoteTable().noteResourceTable.reindexAll(); + setMessage("Database will be reindexed."); + waitCursor(false); + logger.log(logger.HIGH, "Leaving NeverNote.fullRefresh"); + } + // Listener when a user wants to reindex a specific note + @SuppressWarnings("unused") + private void reindexNote() { + logger.log(logger.HIGH, "Entering NeverNote.reindexNote"); + for (int i=0; i 1) + setMessage("Notes will be reindexed."); + else + setMessage("Note will be reindexed."); + logger.log(logger.HIGH, "Leaving NeverNote.reindexNote"); + } + // Delete the note + @SuppressWarnings("unused") + private void deleteNote() { + logger.log(logger.HIGH, "Entering NeverNote.deleteNote"); + if (currentNote == null) + return; + if (currentNoteGuid.equals("")) + return; + + // If we are deleting non-trash notes + if (currentNote.isActive()) { + if (Global.verifyDelete()) { + if (QMessageBox.question(this, "Confirmation", "Delete selected note(s)?", + QMessageBox.StandardButton.Yes, + QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) { + return; + } + } + if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals("")) + selectedNoteGUIDs.add(currentNoteGuid); + for (int i=0; i=0; i--) { + for (int j=noteTableView.model.rowCount()-1; j>=0; j--) { + QModelIndex modelIndex = noteTableView.model.index(j, Global.noteTableGuidPosition); + if (modelIndex != null) { + SortedMap ix = noteTableView.model.itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + if (tableGuid.equals(selectedNoteGUIDs.get(i))) { + noteTableView.model.removeRow(j); + j=-1; + } + } + } + listManager.expungeNote(selectedNoteGUIDs.get(i)); + } + } + currentNoteGuid = ""; + listManager.loadNotesIndex(); + noteIndexUpdated(false); + refreshEvernoteNote(true); + scrollToGuid(currentNoteGuid); + logger.log(logger.HIGH, "Leaving NeverNote.deleteNote"); + } + // Add a new note + @SuppressWarnings("unused") + private void addNote() { + logger.log(logger.HIGH, "Inside NeverNote.addNote"); +// browserWindow.setEnabled(true); + browserWindow.setReadOnly(false); + saveNote(); + Calendar currentTime = new GregorianCalendar(); + String noteString = new String("\n" + + "\n" + + "\n
"); + + Long l = new Long(currentTime.getTimeInMillis()); + String randint = new String(Long.toString(l)); + + // Find a notebook. We first look for a selected notebook (the "All Notebooks" one doesn't count). + // Then we look + // for the first non-archived notebook. Finally, if nothing else we + // pick the first notebook in the list. + String notebook = null; + listManager.getNotebookIndex().get(0).getGuid(); + List selectedNotebook = notebookTree.selectedItems(); + if (selectedNotebook.size() > 0 && !selectedNotebook.get(0).text(0).equalsIgnoreCase("All Notebooks")) { + QTreeWidgetItem currentSelectedNotebook = selectedNotebook.get(0); + notebook = currentSelectedNotebook.text(2); + } else { + boolean found = false; + List goodNotebooks = new ArrayList(); + for (int i=0; i 0 && !found) + notebook = goodNotebooks.get(0).getGuid(); + + if (notebook==null) + notebook = listManager.getNotebookIndex().get(0).getGuid(); + } + + Note newNote = new Note(); + newNote.setUpdateSequenceNum(0); + newNote.setGuid(randint); + newNote.setNotebookGuid(notebook); + newNote.setTitle(""); + newNote.setContent(noteString); + newNote.setDeleted(0); + newNote.setCreated(System.currentTimeMillis()); + newNote.setUpdated(System.currentTimeMillis()); + newNote.setActive(true); + NoteAttributes na = new NoteAttributes(); + na.setLatitude(0.0); + na.setLongitude(0.0); + na.setAltitude(0.0); + newNote.setAttributes(new NoteAttributes()); + conn.getNoteTable().addNote(newNote, true); + listManager.getUnsynchronizedNotes().add(newNote.getGuid()); + noteTableView.insertRow(listManager, newNote, true, -1); + + currentNote = newNote; + currentNoteGuid = currentNote.getGuid(); + listManager.addNote(newNote); + refreshEvernoteNote(true); + listManager.countNotebookResults(listManager.getNoteIndex()); + browserWindow.titleLabel.setFocus(); + browserWindow.titleLabel.selectAll(); +// notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter()); + logger.log(logger.HIGH, "Leaving NeverNote.addNote"); + } + // Restore a note from the trash; + @SuppressWarnings("unused") + private void restoreNote() { + waitCursor(true); + if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals("")) + selectedNoteGUIDs.add(currentNoteGuid); + for (int i=0; i resList = conn.getNoteTable().noteResourceTable.getNoteResources(guid, true); + oldNote.setResources(resList); + duplicateNote(oldNote); + } + private void duplicateNote(Note oldNote) { + waitCursor(true); + // Now that we have a good notebook guid, we need to move the conflicting note + // to the local notebook + Calendar currentTime = new GregorianCalendar(); + Long l = new Long(currentTime.getTimeInMillis()); + String newGuid = new String(Long.toString(l)); + + Note newNote = oldNote.deepCopy(); + newNote.setUpdateSequenceNum(0); + newNote.setGuid(newGuid); + newNote.setDeleted(0); + newNote.setActive(true); + List resList = oldNote.getResources(); + if (resList == null) + resList = new ArrayList(); + long prevGuid = 0; + for (int i=0; i sources = new ArrayList(); + QModelIndex index; + for (int i=0; i ix = noteTableView.proxyModel.itemData(index); + if (i == 0) + masterGuid = (String)ix.values().toArray()[0]; + else + sources.add((String)ix.values().toArray()[0]); + } + + logger.log(logger.EXTREME, "Master guid=" +masterGuid); + logger.log(logger.EXTREME, "Children count: "+sources.size()); + mergeNoteContents(masterGuid, sources); + currentNoteGuid = masterGuid; + noteIndexUpdated(false); + refreshEvernoteNote(true); + waitCursor(false); + } + private void mergeNoteContents(String targetGuid, List sources) { + Note target = conn.getNoteTable().getNote(targetGuid, true, false, false, false, false); + String newContent = target.getContent(); + newContent = newContent.replace("", "

"); + + for (int i=0; i" +source.getTitle() +""); + } + String sourceContent = source.getContent(); + logger.log(logger.EXTREME, "Merging contents into note"); + logger.log(logger.EXTREME, sourceContent); + logger.log(logger.EXTREME, "End of content"); + int startOfNote = sourceContent.indexOf(""); + sourceContent = sourceContent.substring(startOfNote+9); + int endOfNote = sourceContent.indexOf(""); + sourceContent = sourceContent.substring(0,endOfNote); + newContent = newContent + sourceContent; + logger.log(logger.EXTREME, "New note content"); + logger.log(logger.EXTREME, newContent); + logger.log(logger.EXTREME, "End of content"); + for (int j=0; j"); + for (int i=0; i(); + currentOnlineNote = syncRunner.noteStore.getNote(syncRunner.authToken, currentNoteGuid, true, true, false, false); + } catch (EDAMUserException e) { + setMessage("EDAMUserException: " +e.getMessage()); + return; + } catch (EDAMSystemException e) { + setMessage("EDAMSystemException: " +e.getMessage()); + return; + } catch (EDAMNotFoundException e) { + setMessage("Note not found on server."); + QMessageBox.information(this, "Error", "This note could not be found on Evernote's servers."); + return; + } catch (TException e) { + setMessage("EDAMTransactionException: " +e.getMessage()); + return; + } + + // If we've gotten this far, we have a good note. + if (historyWindow == null) { + historyWindow = new OnlineNoteHistory(conn); + historyWindow.historyCombo.activated.connect(this, "reloadHistoryWindow(String)"); + historyWindow.restoreAsNew.clicked.connect(this, "restoreHistoryNoteAsNew()"); + historyWindow.restore.clicked.connect(this, "restoreHistoryNote()"); + } else { + historyWindow.historyCombo.clear(); + } + boolean isDirty = conn.getNoteTable().isNoteDirty(currentNoteGuid); + if (currentNote.getUpdateSequenceNum() != currentOnlineNote.getUpdateSequenceNum()) + isDirty = true; + historyWindow.setCurrent(isDirty); + + loadHistoryWindowContent(currentOnlineNote); + historyWindow.load(versions); + setMessage("History retrieved"); + waitCursor(false); + historyWindow.exec(); + } + private Note reloadHistoryWindow(String selection) { + waitCursor(true); + String fmt = Global.getDateFormat() + " " + Global.getTimeFormat(); + String dateTimeFormat = new String(fmt); + SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat); + int index = -1; + int usn = 0; + + for (int i=0; i -1 || selection.indexOf("Current") > -1) { + Note historyNote = null; + try { + if (index > -1) { + usn = versions.get(index).getUpdateSequenceNum(); + historyNote = syncRunner.noteStore.getNoteVersion(syncRunner.authToken, currentNoteGuid, usn, true, true, true); + } else + historyNote = syncRunner.noteStore.getNote(syncRunner.authToken, currentNoteGuid, true,true,true,true); + } catch (EDAMUserException e) { + setMessage("EDAMUserException: " +e.getMessage()); + waitCursor(false); + return null; + } catch (EDAMSystemException e) { + setMessage("EDAMSystemException: " +e.getMessage()); + waitCursor(false); + return null; + } catch (EDAMNotFoundException e) { + setMessage("EDAMNotFoundException: " +e.getMessage()); + waitCursor(false); + return null; + } catch (TException e) { + setMessage("EDAMTransactionException: " +e.getMessage()); + waitCursor(false); + return null; + } + + waitCursor(false); + if (historyNote != null) + historyWindow.setContent(historyNote); + return historyNote; + } + waitCursor(false); + return null; + } + private void loadHistoryWindowContent(Note note) { + note.setUpdateSequenceNum(0); + historyWindow.setContent(note); + } + @SuppressWarnings("unused") + private void restoreHistoryNoteAsNew() { + setMessage("Restoring as new note."); + duplicateNote(reloadHistoryWindow(historyWindow.historyCombo.currentText())); + setMessage("Note has been restored as a new note."); + } + @SuppressWarnings("unused") + private void restoreHistoryNote() { + setMessage("Restoring note."); + Note n = reloadHistoryWindow(historyWindow.historyCombo.currentText()); + conn.getNoteTable().expungeNote(n.getGuid(), true, false); + n.setActive(true); + n.setDeleted(0); + for (int i=0; i -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; + String pathPrefix = Global.currentDir; + pathPrefix = Global.getDirectoryPath()+"res/"; + if (fileDetails != null && !fileDetails.equals("")) { + enmedia.setAttribute("href", "nnres://" +r.getGuid() +Global.attachmentNameDelimeter +fileDetails); + contextFileName = Global.currentDir +"res/" +r.getGuid() +Global.attachmentNameDelimeter +fileDetails; + } else { + enmedia.setAttribute("href", "nnres://" +r.getGuid() +Global.attachmentNameDelimeter +appl); + contextFileName = pathPrefix+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(Global.getDirectoryPath() +"res/"+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() +"')"); + left.setAttribute("src", Global.currentDir+"images/small_left.png"); + right.setAttribute("src", Global.currentDir+"images/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)); + newText.setAttribute("src", Global.getDirectoryPath()+"images"+File.separator +icon); + if (goodPreview) { + newText.setAttribute("src", Global.getDirectoryPath()+"res/"+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("-1; i=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.getDirectoryPath()+"res"+File.separator +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(); + 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.getDirectoryPath()+"images/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 + } + + 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, tr("Parse error when rebuilding HTML")); + logger.log(logger.MEDIUM, tr("Note guid: " +noteGuid)); + logger.log(logger.EXTREME, tr("Start of unmodified note HTML")); + logger.log(logger.EXTREME, note); + logger.log(logger.EXTREME, tr("End of unmodified note HTML")); + return note; + } + + if (tempFiles == null) + tempFiles = new ArrayList(); + 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 tag after an tag (which is done + // to get the application tag to work properly) causes spaces to be inserted + // between the & . This messes things up later. This is an ugly hack. + StringBuffer html = new StringBuffer(doc.toString()); + for (int i=html.indexOf("-1; i=html.indexOf("\n",i+1); + int z = html.indexOf("i; j--) + html.deleteCharAt(j); + i=html.indexOf("/>", z+1); + z = html.indexOf("",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) + return; + QMessageBox.information(this, tr("DOUGH!!!"), tr("Well, this is embarrassing."+ + "\n\nSome attachments or images for this note appear to be missing from my database.\n"+ + "In a perfect world this wouldn't happen, but it has.\n" + + "It is embarasing when a program like me, designed to save all your\n"+ + "precious data, has a problem finding data.\n\n" + + "I guess life isn't fair, but I'll survive. Somehow...\n\n" + + "In the mean time, I'm not going to let you make changes to this note.\n" + + "Don't get angry. I'm doing it to prevent you from messing up\n"+ + "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); + } + + + + + //********************************************************** + //********************************************************** + //* Timer functions + //********************************************************** + //********************************************************** + // We should now do a sync with Evernote + private void syncTimer() { + logger.log(logger.EXTREME, "Entering NeverNote.syncTimer()"); + syncRunner.syncNeeded = true; + syncRunner.disableUploads = Global.disableUploads; + syncStart(); + logger.log(logger.EXTREME, "Leaving NeverNote.syncTimer()"); + } + private void syncStart() { + logger.log(logger.EXTREME, "Entering NeverNote.syncStart()"); + saveNote(); + if (!syncRunning && Global.isConnected) { + syncRunner.setConnected(true); + syncRunner.setKeepRunning(Global.keepRunning); + syncRunner.syncDeletedContent = Global.synchronizeDeletedContent(); + + if (syncThreadsReady > 0) { + saveNoteIndexWidth(); + if (syncRunner.addWork("SYNC")) { + syncRunning = true; + syncRunner.syncNeeded = true; + syncThreadsReady--; + } + } + } + logger.log(logger.EXTREME, "Leaving NeverNote.syncStart"); + } + @SuppressWarnings("unused") + private void syncThreadComplete(Boolean refreshNeeded) { + setMessage("Finalizing Synchronization"); + syncThreadsReady++; + syncRunning = false; + syncRunner.syncNeeded = false; + synchronizeAnimationTimer.stop(); + noteIndexUpdated(true); + synchronizeButton.setIcon(synchronizeAnimation.get(0)); + saveNote(); +// noteTableView.selectionModel().selectionChanged.disconnect(this, "noteTableSelection()"); + noteTableView.selectionModel().blockSignals(true); + scrollToGuid(currentNoteGuid); + noteTableView.selectionModel().blockSignals(false); +// noteTableView.selectionModel().selectionChanged.connect(this, "noteTableSelection()"); +// indexRunner.setKeepRunning(Global.keepRunning); + + // Reload the unindexed table If the dbthread is dead, we are probably shutting down. + if (!dbThread.isAlive()) + return; + listManager.setUnsynchronizedNotes(conn.getNoteTable().getUnsynchronizedGUIDs()); + for (int i=0; i ix = noteTableView.model.itemData(modelIndex); + String tableGuid = (String)ix.values().toArray()[0]; + String synch = "true"; + for (int j=0; j syncRunner.authRefreshTime) +// syncRunner.authRefreshTime = cal.getTimeInMillis(); + +// long now = new Date().getTime(); +// if (now > Global.authRefreshTime && Global.isConnected) { + syncRunner.authRefreshNeeded = true; + syncStart(); +// } + } + @SuppressWarnings("unused") + private void authRefreshComplete(boolean goodSync) { + logger.log(logger.EXTREME, "Entering NeverNote.authRefreshComplete"); + Global.isConnected = syncRunner.isConnected; + if (goodSync) { +// authTimer.start((int)syncRunner.authTimeRemaining/4); + authTimer.start(1000*60*15); + logger.log(logger.LOW, "Authentication token has been renewed"); +// setMessage("Authentication token has been renewed."); + } else { + authTimer.start(1000*60*5); + logger.log(logger.LOW, "Authentication token renew has failed - retry in 5 minutes."); +// setMessage("Authentication token renew has failed - retry in 5 minutes."); + } + logger.log(logger.EXTREME, "Leaving NeverNote.authRefreshComplete"); + } + + + @SuppressWarnings("unused") + private synchronized void indexTimer() { + logger.log(logger.EXTREME, "Index timer activated. Sync running="+syncRunning); + if (syncRunning) + return; + // Look for any unindexed notes. We only refresh occasionally + // and do one at a time to keep overhead down. + if (!indexDisabled && indexRunner.getWorkQueueSize() == 0) { + List notes = conn.getNoteTable().getNextUnindexed(1); + String unindexedNote = null; + if (notes.size() > 0) + unindexedNote = notes.get(0); + if (unindexedNote != null && Global.keepRunning) { + indexNoteContent(unindexedNote); + } + if (notes.size()>0) { + indexTimer.setInterval(100); + return; + } + List unindexedResources = conn.getNoteTable().noteResourceTable.getNextUnindexed(1); + if (unindexedResources.size() > 0 && indexRunner.getWorkQueueSize() == 0) { + String unindexedResource = unindexedResources.get(0); + if (unindexedResource != null && Global.keepRunning) { + indexNoteResource(unindexedResource); + } + } + if (unindexedResources.size() > 0) { + indexTimer.setInterval(100); + return; + } else { + indexTimer.setInterval(indexTime); + } + if (indexRunning) { + setMessage("Index completed."); + logger.log(logger.LOW, "Indexing has completed."); + indexRunning = false; + indexTimer.setInterval(indexTime); + } + } + logger.log(logger.EXTREME, "Leaving neverNote index timer"); + } + private synchronized void indexNoteContent(String unindexedNote) { + logger.log(logger.EXTREME, "Entering NeverNote.indexNoteContent()"); + logger.log(logger.MEDIUM, "Unindexed Note found: "+unindexedNote); + indexRunner.setIndexType(indexRunner.CONTENT); + indexRunner.addWork("CONTENT "+unindexedNote); + if (!indexRunning) { + setMessage("Indexing notes."); + logger.log(logger.LOW, "Beginning to index note contents."); + indexRunning = true; + } + logger.log(logger.EXTREME, "Leaving NeverNote.indexNoteContent()"); + } + private synchronized void indexNoteResource(String unindexedResource) { + logger.log(logger.EXTREME, "Leaving NeverNote.indexNoteResource()"); + indexRunner.addWork(new String("RESOURCE "+unindexedResource)); + if (!indexRunning) { + setMessage("Indexing notes."); + indexRunning = true; + } + logger.log(logger.EXTREME, "Leaving NeverNote.indexNoteResource()"); + } + @SuppressWarnings("unused") + private void indexThreadComplete(String guid) { + logger.log(logger.MEDIUM, "Index complete for "+guid); + } + @SuppressWarnings("unused") + private synchronized void toggleNoteIndexing() { + logger.log(logger.HIGH, "Entering NeverNote.toggleIndexing"); + indexDisabled = !indexDisabled; + if (!indexDisabled) + setMessage("Indexing is now enabled."); + else + setMessage("Indexing is now disabled."); + menuBar.disableIndexing.setChecked(indexDisabled); + logger.log(logger.HIGH, "Leaving NeverNote.toggleIndexing"); + } + + @SuppressWarnings("unused") + private void threadMonitorCheck() { + int MAX=3; + + + boolean alive; + alive = listManager.threadCheck(Global.tagCounterThreadId); + if (!alive) { + tagDeadCount++; + if (tagDeadCount > MAX) + QMessageBox.information(this, "A thread his died.", "It appears as the tag counter thread has died. I recommend "+ + "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry."); + } else + tagDeadCount=0; + + alive = listManager.threadCheck(Global.notebookCounterThreadId); + if (!alive) { + notebookThreadDeadCount++; + QMessageBox.information(this, "A thread his died.", "It appears as the notebook counter thread has died. I recommend "+ + "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry."); + } else + notebookThreadDeadCount=0; + + alive = listManager.threadCheck(Global.trashCounterThreadId); + if (!alive) { + trashDeadCount++; + QMessageBox.information(this, "A thread his died.", "It appears as the trash counter thread has died. I recommend "+ + "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry."); + } else + trashDeadCount = 0; + + alive = listManager.threadCheck(Global.saveThreadId); + if (!alive) { + saveThreadDeadCount++; + QMessageBox.information(this, "A thread his died.", "It appears as the note saver thread has died. I recommend "+ + "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry."); + } else + saveThreadDeadCount=0; + + if (!dbThread.isAlive()) { + dbThreadDeadCount++; + QMessageBox.information(this, "A thread his died.", "It appears as the database thread has died. I recommend "+ + "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry."); + } else + dbThreadDeadCount=0; + + if (!syncThread.isAlive()) { + syncThreadDeadCount++; + QMessageBox.information(this, "A thread his died.", "It appears as the synchronization thread has died. I recommend "+ + "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry."); + } else + syncThreadDeadCount=0; + + if (!indexThread.isAlive()) { + indexThreadDeadCount++; + QMessageBox.information(this, "A thread his died.", "It appears as the index thread has died. I recommend "+ + "checking stopping NeverNote, saving the logs for later viewing, and restarting. Sorry."); + } else + indexThreadDeadCount=0; + + + } + + + + //************************************************** + //* Backup & Restore + //************************************************** + @SuppressWarnings("unused") + private void databaseBackup() { + QFileDialog fd = new QFileDialog(this); + fd.setFileMode(FileMode.AnyFile); + fd.setConfirmOverwrite(true); + fd.setWindowTitle("Backup Database"); + fd.setFilter(tr("NeverNote Export (*.nnex);;All Files (*.*)")); + fd.setAcceptMode(AcceptMode.AcceptSave); + fd.setDirectory(System.getProperty("user.home")); + if (fd.exec() == 0 || fd.selectedFiles().size() == 0) { + return; + } + + + waitCursor(true); + setMessage("Backing up database"); + saveNote(); +// conn.backupDatabase(Global.getUpdateSequenceNumber(), Global.getSequenceDate()); + + ExportData noteWriter = new ExportData(conn, true); + String fileName = fd.selectedFiles().get(0); + + if (!fileName.endsWith(".nnex")) + fileName = fileName +".nnex"; + noteWriter.exportData(fileName); + setMessage("Database backup completed."); + + + waitCursor(false); + } + @SuppressWarnings("unused") + private void databaseRestore() { + if (QMessageBox.question(this, "Confirmation", + "This is used to restore a database from backups.\n" + + "It is HIGHLY recommened that this only be used to populate\n" + + "an empty database. Restoring into a database that\n already has data" + + " can cause problems.\n\nAre you sure you want to continue?", + QMessageBox.StandardButton.Yes, + QMessageBox.StandardButton.No)==StandardButton.No.value()) { + return; + } + + + QFileDialog fd = new QFileDialog(this); + fd.setFileMode(FileMode.ExistingFile); + fd.setConfirmOverwrite(true); + fd.setWindowTitle("Restore Database"); + fd.setFilter(tr("NeverNote Export (*.nnex);;All Files (*.*)")); + fd.setAcceptMode(AcceptMode.AcceptOpen); + fd.setDirectory(System.getProperty("user.home")); + if (fd.exec() == 0 || fd.selectedFiles().size() == 0) { + return; + } + + + waitCursor(true); + setMessage("Restoring database"); + ImportData noteReader = new ImportData(conn, true); + noteReader.importData(fd.selectedFiles().get(0)); + + if (noteReader.lastError != 0) { + setMessage(noteReader.getErrorMessage()); + logger.log(logger.LOW, "Restore problem: " +noteReader.lastError); + waitCursor(false); + return; + } + + listManager.loadNoteTitleColors(); + refreshLists(); + refreshEvernoteNote(true); + setMessage("Database has been restored."); + waitCursor(false); + } + @SuppressWarnings("unused") + private void exportNotes() { + QFileDialog fd = new QFileDialog(this); + fd.setFileMode(FileMode.AnyFile); + fd.setConfirmOverwrite(true); + fd.setWindowTitle("Backup Database"); + fd.setFilter(tr("NeverNote Export (*.nnex);;All Files (*.*)")); + fd.setAcceptMode(AcceptMode.AcceptSave); + fd.setDirectory(System.getProperty("user.home")); + if (fd.exec() == 0 || fd.selectedFiles().size() == 0) { + return; + } + + + waitCursor(true); + setMessage("Exporting Notes"); + saveNote(); + + if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals("")) + selectedNoteGUIDs.add(currentNoteGuid); + + ExportData noteWriter = new ExportData(conn, false, selectedNoteGUIDs); + String fileName = fd.selectedFiles().get(0); + + if (!fileName.endsWith(".nnex")) + fileName = fileName +".nnex"; + noteWriter.exportData(fileName); + setMessage("Export completed."); + + + waitCursor(false); + + } + @SuppressWarnings("unused") + private void importNotes() { + QFileDialog fd = new QFileDialog(this); + fd.setFileMode(FileMode.ExistingFile); + fd.setConfirmOverwrite(true); + fd.setWindowTitle("Import Notes"); + fd.setFilter(tr("NeverNote Export (*.nnex);;All Files (*.*)")); + fd.setAcceptMode(AcceptMode.AcceptOpen); + fd.setDirectory(System.getProperty("user.home")); + if (fd.exec() == 0 || fd.selectedFiles().size() == 0) { + return; + } + + + waitCursor(true); + setMessage("Importing Notes"); + saveNote(); + + if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals("")) + selectedNoteGUIDs.add(currentNoteGuid); + + ImportData noteReader = new ImportData(conn, false); + String fileName = fd.selectedFiles().get(0); + + if (!fileName.endsWith(".nnex")) + fileName = fileName +".nnex"; + if (selectedNotebookGUIDs != null && selectedNotebookGUIDs.size() > 0) + noteReader.setNotebookGuid(selectedNotebookGUIDs.get(0)); + else + noteReader.setNotebookGuid(listManager.getNotebookIndex().get(0).getGuid()); + + noteReader.importData(fileName); + + if (noteReader.lastError != 0) { + setMessage(noteReader.getErrorMessage()); + logger.log(logger.LOW, "Import problem: " +noteReader.lastError); + waitCursor(false); + return; + } + + listManager.loadNoteTitleColors(); + refreshLists(); + refreshEvernoteNote(false); + setMessage("Notes have been imported."); + waitCursor(false); + + setMessage("Import completed."); + + + waitCursor(false); + + } + + //************************************************** + //* Duplicate a note + //************************************************** + @SuppressWarnings("unused") + private void duplicateNote() { + saveNote(); + duplicateNote(currentNoteGuid); + } + + + + //************************************************** + //* Folder Imports + //************************************************** + public void setupFolderImports() { + List records = conn.getWatchFolderTable().getAll(); + + if (importKeepWatcher == null) + importKeepWatcher = new QFileSystemWatcher(); + if (importDeleteWatcher == null) { + importDeleteWatcher = new QFileSystemWatcher(); + for (int i=0; i(); + for (int j=0; j list = dir.entryInfoList(); + for (int k=0; k recs = conn.getWatchFolderTable().getAll(); + WatchFolder dialog = new WatchFolder(recs, listManager.getNotebookIndex()); + dialog.exec(); + if (!dialog.okClicked()) + return; + + // We have some sort of update. + if (importKeepWatcher.directories().size() > 0) + importKeepWatcher.removePaths(importKeepWatcher.directories()); + if (importDeleteWatcher.directories().size() > 0) + importDeleteWatcher.removePaths(importDeleteWatcher.directories()); + + conn.getWatchFolderTable().expungeAll(); + // Start building from the table + for (int i=0; i list = dir.entryInfoList(); + String notebook = conn.getWatchFolderTable().getNotebook(dirName); + + for (int i=0; i list = dir.entryInfoList(); + String notebook = conn.getWatchFolderTable().getNotebook(dirName); + + for (int i=0; i -1) { + guid = guid.substring(0,pos); + } + pos = name.lastIndexOf(Global.attachmentNameDelimeter); + if (pos > -1) { + guid = name.substring(0, pos); + } + + QFile file = new QFile(fileName); + if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly))) { + // If we can't get to the file, it is probably locked. We'll try again later. + logger.log(logger.LOW, "Unable to save externally edited file. Saving for later."); + externalFiles.add(fileName); + return; + } + QByteArray binData = file.readAll(); + file.close(); + if (binData.size() == 0) { + // If we can't get to the file, it is probably locked. We'll try again later. + logger.log(logger.LOW, "Unable to save externally edited file. Saving for later."); + externalFiles.add(fileName); + return; + } + + Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true); + if (r==null) + r = conn.getNoteTable().noteResourceTable.getNoteResource(Global.resourceMap.get(guid), true); + if (r == null || r.getData() == null || r.getData().getBody() == null) + return; + String oldHash = Global.byteArrayToHexString(r.getData().getBodyHash()); + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(binData.toByteArray()); + byte[] hash = md.digest(); + String newHash = Global.byteArrayToHexString(hash); + if (r.getNoteGuid().equalsIgnoreCase(currentNoteGuid)) { + updateResourceContentHash(r.getGuid(), oldHash, newHash); + } + conn.getNoteTable().updateResourceContentHash(r.getNoteGuid(), oldHash, newHash); + Data data = r.getData(); + data.setBody(binData.toByteArray()); + data.setBodyHash(hash); + logger.log(logger.LOW, "externalFileEdited: " +data.getSize() +" bytes"); + r.setData(data); + conn.getNoteTable().noteResourceTable.updateNoteResource(r,true); + + if (r.getNoteGuid().equals(currentNoteGuid)) { + QWebSettings.setMaximumPagesInCache(0); + QWebSettings.setObjectCacheCapacities(0, 0, 0); + refreshEvernoteNote(true); + browserWindow.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 + // is only needed if we couldn't save a file earlier. + public void externalFileEditedSaver() { + for (int i=externalFiles.size()-1; i>=0; i--) { + try { + logger.log(logger.MEDIUM, "Trying to save " +externalFiles.get(i)); + externalFileEdited(externalFiles.get(i)); + externalFiles.remove(i); + } catch (NoSuchAlgorithmException e) {e.printStackTrace();} + } + for (int i=0; i", position+1); + String oldSegment = browserWindow.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) + + newSegment + + browserWindow.getContent().substring(endPos); + browserWindow.getBrowser().setContent(new QByteArray(content));; + } + + position = browserWindow.getContent().indexOf("en-tag=\"en-media\" guid=\""+guid+"\" type=", position+1); + } + } + + + + + //************************************************* + //* Check database userid & passwords + //************************************************* + public boolean databaseCheck(String url,String userid, String userPassword, String cypherPassword) { + Connection connection; + + try { + Class.forName("org.h2.Driver"); + } catch (ClassNotFoundException e1) { + e1.printStackTrace(); + System.exit(16); + } + + try { + String passwordString = null; + if (cypherPassword==null || cypherPassword.trim().equals("")) + passwordString = userPassword; + else + passwordString = cypherPassword+" "+userPassword; + connection = DriverManager.getConnection(url,userid,passwordString); + } catch (SQLException e) { + return false; + } + try { + connection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + return true; + } + +} diff --git a/src/cx/fbn/nevernote/dialog/AccountDialog.class b/src/cx/fbn/nevernote/dialog/AccountDialog.class new file mode 100644 index 0000000000000000000000000000000000000000..9611f708549ccb9df5e96228405d440236532640 GIT binary patch literal 4104 zcma)9X>=3U8NE-)nvpyJ?JwlPFl1``__Lqa;1#%5roF{2TN z(lw-8x;LaPg{EoKHcivg&=T2+({xE!=t9#rZMyu(zy8hNoSf48W+W_weHtGh>22Tl zzI)%d>EeH1cnQGm__u<9z{39M+D z2aqyxQKWRHZ zrXhiMQ2SBcDjK^+NqNhT)+!F=nRcoFb`9^8`s=UiPn$WDq&49V4eyd$jkCA9^I3WA zT^jC|yJ3r}2IVy>phEB-8AXMB#Q{z3IDmvt#w^KnExtuZAf6mULX=M#Z z-rKEV8@3D7@!qYvYi#peL|}1CHG;AiM36#{f*k@4*Q%5pqy<)0`_8VBLq^7JpHopM znpNx)5b+2)v0KA^=qDh3eB8)q1=dyTsrXW^UXvW+;eYKbqyogBso=p@sbDQ7|HK%iNx}-LZ?~o%S&m zgrJt=E-AxdRKpk!GO}Ig8j|J(M^w5biK(Ej62b$=#|`R>BBvn_n+~C8vqNTny9MjGwRUDK6(7}8oq!> zsjg5QDR`Mvo=(jf0gvHJ3ce`I#@hj=;mgv_rL@z-K^Pv2j%?O33I!EkVJvM?aCY7# zJySPSJkB@S)f2%PG>7S(U)NBBP?*yvHGC7_VlK;AX6CR#H};92RjYRQn`3$1>SpS4 z4X4?kZ6NhektqAHyvWG5v_|kWo>A~!fz{WA%iJn7d=KB3m)rR~GY18$(?HqRuFC>m z-H74`8lJ^@KO`y@XWoz~R~#7cj^wf?pj;;b}P zGlmG^QH% zR29#u>v#3c;a+{b{P=3cuVps>vxdLOE~F-7*##o4WmN7u>^Efs&E;e@D`vd@ZYBh! zQT=w&$r#&A&*5hEi0kFE(4-W@!0EE|Lcu5~_@}_~{}V{0zZ{KNK|2?)E8r{3;O1xn z$7~Au8D_I^o@0<=%I}(WCEOVc@*^jwp=dIx$ffY9$FWEb7Gsm#*%{sJZ*YF< z%r#qEl8UE73N7(QQmQPO3{InScnVvmaPK5~qdQCJo5BD;OBhP3(?|`+)Jg11hNrQA zI2NA71IdUKiA7>HB^;nkvbGE}sZB#4Zi{A0FeYIp>tb9W+Cu~wBnT^}tqoF$-`@H- z*K7QBIrp@3>Xc2{;u|3kRS6Y156u=L5oMW}LYZihAF)sg6VdlxRS~LE@jj|hW>my# z2~{q6M`&~jA6OHs^DLgi2a}aoOfK}{oh-v^h;d;#@qWZx@F7m&W68!?WAu>{K6M(k zu|`_-Ij(p|J%sfooGK$cP4g&l)kvQl>h&yW@VKdP8*Q7$nc?VHC-JrC@I>1MJaGZv zXp4TkgzvMA(c+(Z=5qYuWU#<0!%14QS^t zt}ZsxJ)G^s9XNnH*<9U)0(;~M?mmP~EZXm8CB6q|u?6RN`VzL{RdnNZcDrxjUc8Bv z2(yump+~G>ceeq(Vh}sUD0|Y==o3$4w|EiviI*`TE@4ny#*laod&Pe+EZ)LC{@U9g zsKxz(MR*{v83zL0creh5Okfb%Kn6x&9HW5~7z>=lLHvk_E@H8aHC(`RoJ9i;N|IY|RKvU5@DfKM-nt4u!A}{}m&Eh< z8AmE!73c7Cj>33dJc*a_3$plzcoe_HuTYCO#UuDN@6|+DoWO7JTmC-0Oq(u}pL*hZ z2EXI(LZUp2-*dNtI8Wja)YnL4>+whKMsb-43J6`{g9H=^g-dt~VFk;tuuW9`CC(JA zt@=*^P0Ox`ETZ!rP>}Ne_bcG<79P_TJXRS{oFx6JlD_!#?02{pYAfNDA?ZK?NC%4W z8?Z=J&Ldv)PnC%m_$%GOOMrAHUqg*_$7io92zdfWs)TFG!U6ovJN0+G=3OM%-~0pr HLgW7cCGb1D literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/dialog/AccountDialog.java b/src/cx/fbn/nevernote/dialog/AccountDialog.java new file mode 100644 index 0000000..50ed80e --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/AccountDialog.java @@ -0,0 +1,121 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.dialog; + + +import java.text.SimpleDateFormat; + +import com.evernote.edam.type.UserAttributes; +import com.trolltech.qt.gui.QDialog; +import com.trolltech.qt.gui.QGridLayout; +import com.trolltech.qt.gui.QGroupBox; +import com.trolltech.qt.gui.QHBoxLayout; +import com.trolltech.qt.gui.QLabel; +import com.trolltech.qt.gui.QPushButton; + +import cx.fbn.nevernote.Global; + +public class AccountDialog extends QDialog { + + private final QPushButton ok; + + // Constructor + public AccountDialog() { + setWindowTitle("Account Information"); + QGridLayout grid = new QGridLayout(); + setLayout(grid); + QLabel premium; + if (Global.isPremium()) + premium = new QLabel("Premium"); + else + premium = new QLabel("Free"); + + Long uploadAmt = Global.getUploadAmount(); + Long uploadLimit = Global.getUploadLimit(); + Long uploadLimitEnd = Global.getUploadLimitEnd(); + Long pct; + if (uploadLimit > 0) + pct = uploadAmt*100 / uploadLimit; + else + pct = new Long(0); + String unit = " Bytes"; + + if (uploadAmt > 0) { + uploadAmt = uploadAmt/1024; + unit = " KB"; + } + if (uploadAmt >= 1024) { + uploadAmt = uploadAmt / 1024; + unit = " MB"; + } + if (uploadLimit > 0) + uploadLimit = uploadLimit/1024/1024; + + + String fmt = Global.getDateFormat() + " " + Global.getTimeFormat(); + String dateTimeFormat = new String(fmt); + SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat); + StringBuilder endDate = new StringBuilder(simple.format(uploadLimitEnd)); + + QGridLayout textGrid = new QGridLayout(); + QGroupBox limitGroup = new QGroupBox(tr("Account:")); + textGrid.addWidget(new QLabel("Account Type:"), 1,1); + textGrid.addWidget(premium, 1, 2); + textGrid.addWidget(new QLabel("Limit:"), 2,1); + textGrid.addWidget(new QLabel(uploadLimit.toString() +" MB"),2,2); + textGrid.addWidget(new QLabel("Uploaded In This Period:"), 3,1); + textGrid.addWidget(new QLabel(uploadAmt.toString()+unit +" ("+pct+"%)"),3,2); + textGrid.addWidget(new QLabel("Current Cycle Ends:"), 4,1); + textGrid.addWidget(new QLabel(endDate.toString()),4,2); + limitGroup.setLayout(textGrid); + + grid.addWidget(limitGroup, 1, 1); + + UserAttributes attrib = Global.getUserAttributes(); + QGridLayout attribGrid = new QGridLayout(); + QGroupBox attribGroup = new QGroupBox(tr("User Attributes")); + attribGrid.addWidget(new QLabel(tr("Incoming Email:")), 1,1); + String server = Global.getServer(); + if (server.startsWith("www.")) + server = server.substring(4); + attribGrid.addWidget(new QLabel(attrib.getIncomingEmailAddress()+"@"+Global.getServer()), 1,2); + attribGroup.setLayout(attribGrid); + grid.addWidget(attribGroup, 2,1); + + + QHBoxLayout buttonLayout = new QHBoxLayout(); + ok = new QPushButton("OK"); + ok.clicked.connect(this, "okPushed()"); + buttonLayout.addStretch(); + buttonLayout.addWidget(ok); + buttonLayout.addStretch(); + grid.addLayout(buttonLayout,3,1); + } + + @SuppressWarnings("unused") + private void okPushed() { + this.close(); + } + + + public QPushButton getOkButton() { + return ok; + } +} diff --git a/src/cx/fbn/nevernote/dialog/AssignTag.class b/src/cx/fbn/nevernote/dialog/AssignTag.class new file mode 100644 index 0000000000000000000000000000000000000000..4168a9f08306972bd8b5b144113e811a1b0f672e GIT binary patch literal 3555 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 literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/dialog/ConfigAppearancePage.java b/src/cx/fbn/nevernote/dialog/ConfigAppearancePage.java new file mode 100644 index 0000000..93c35f6 --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/ConfigAppearancePage.java @@ -0,0 +1,336 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.dialog; + +import java.util.ArrayList; +import java.util.List; + +import com.trolltech.qt.gui.QApplication; +import com.trolltech.qt.gui.QCheckBox; +import com.trolltech.qt.gui.QComboBox; +import com.trolltech.qt.gui.QFormLayout; +import com.trolltech.qt.gui.QGroupBox; +import com.trolltech.qt.gui.QHBoxLayout; +import com.trolltech.qt.gui.QLabel; +import com.trolltech.qt.gui.QSpinBox; +import com.trolltech.qt.gui.QStyleFactory; +import com.trolltech.qt.gui.QVBoxLayout; +import com.trolltech.qt.gui.QWidget; + +import cx.fbn.nevernote.Global; + +public class ConfigAppearancePage extends QWidget { + private final QComboBox dateFormat; + private final QComboBox timeFormat; + private final QComboBox styleFormat; + private final QComboBox tagBehavior; + private final QCheckBox standardPalette; + private final QCheckBox showSplashScreen; + private final QCheckBox showTrayIcon; + private final QCheckBox verifyDelete; + private final QCheckBox pdfPreview; + private final QCheckBox mimicEvernote; + private final QSpinBox autoSaveInterval; + + private final List tformats; + private final List dformats; + + public ConfigAppearancePage(QWidget parent) { +// super(parent); + + dformats = new ArrayList(); + tformats = new ArrayList(); + + dformats.add("MM/dd/yy - 12/31/09"); + dformats.add("MM/dd/yyyy - 12/31/2009"); + dformats.add("dd/MM/yy - 31/12/09"); + dformats.add("dd/MM/yyyy - 31/12/2009"); + dformats.add("yyyy/MM/dd - 2009/12/31"); + dformats.add("yy/MM/dd - 9/12/31"); + + tformats.add("HH:mm:ss - 2:13:01"); + tformats.add("HH:mm:ss a - 2:13:01 am"); + tformats.add("HH:mm - 2:13"); + tformats.add("HH:mm a - 2:13 am"); + + + // Style sheet formats + List styles = QStyleFactory.keys(); + QGroupBox styleGroup = new QGroupBox(tr("GUI Style")); + styleFormat = new QComboBox(); + styleFormat.addItems(styles); + styleFormat.activated.connect(this, "styleSelected(String)"); + + standardPalette = new QCheckBox(); + standardPalette.setText("Use standard palette"); + standardPalette.clicked.connect(this, "standardPaletteChanged()"); + + QFormLayout styleLayout = new QFormLayout(); + styleLayout.addWidget(styleFormat); + styleLayout.addWidget(standardPalette); + + styleGroup.setLayout(styleLayout); + + QGroupBox tagBehaviorGroup = new QGroupBox(tr("Tag Behavior")); + tagBehavior = new QComboBox(); + tagBehavior.addItem(tr("Do nothing")); + tagBehavior.addItem(tr("Count tags & do not hide inactive")); + tagBehavior.addItem(tr("Count tags & hide inactive")); + tagBehavior.addItem(tr("Color active tags")); + + QFormLayout tagLayout = new QFormLayout(); + tagLayout.addWidget(tagBehavior); + tagBehaviorGroup.setLayout(tagLayout); + + + + // Date/Time settings + QGroupBox datetimeGroup = new QGroupBox(tr("Date/Time Format")); + dateFormat = new QComboBox(); + for (int i=0; iG=ul8c^efq6Wzx6ltTWjBaE|ZWsL!LZy&ffd1wf4LA zTI*dq@BHu0w*c(G-@~XA=*mndPmGyKQ=X9p)3RkUYv?&^JlSWNCya4EO_{L`%RHoy z%P>L$@5xyCq+PIbIa_8XlBezDc*#f}e$>d0OIsjXD$0V9?avyV#M8mTX~UFCqE|qh z)QiO_tKey@D#*OdkIBLzZ@IRSz6qH*wbz=aktV%lTWM?DFln$jV`fsOEemJ#+zqs? z{FvowD~%&YUKRzmrmGI5WE(ldHe@k5?8|Y>m{OW3Sf+7S4w-#9t0)E5En3_sbJCVs zo}evFo2DCg8Kz`jaag!-(kjG`W`8d|VMpuQt962>h88-kDYK*1_a z(w_*{F$fEBi-IB3(2flPb#{RscBD`0XY^!FH^-C1cEK>mdlS`5QLIH=?Y&8$HAsbM zZWUM`j3%v*$y@}t(d$Q?e28K*;t_NRMEuBx(OJ_QKS82MptXrE+@YZXjZH}6&M@99 zu(m2p2XfY!p3|7wJGqIrK>2UT!m%Iya=G(!s`EwH8PSOc;@iig~w3~5+_o7D8MhKDh%iqA=? z5j|H@)fDUSGD}%Wrj4RaFZ=O`h7mll0|V8apmL(G(^x8!G{D|_K+>|x@~0QUY#g`F%3~AkQLad3SHIqSsC}r zI6g>jRN|_bmG}t_tCaYJz&2l;R1hCB+(bdtmd_9Z-<5Gk7dSv;#1{oYbfCi zRhUe!wHt7cD?siEW4b1;5fY4#Yf9mof~6iG*6HWg zbeA+-#uXBsL6%cpM)lHEK(`eT27f75inqJJOEczhHH@DK+~laMyemb((r3la4dh&I`^*oeyKo z)r1In$H5xJb2!JRGPlE-Gr!%?ed!X{+@n<60@AUhIpc_DN#HAiaJqxw z`5Ml9?kql?Yokl}6s|Z=e3s5*yg5*yWsWf8@76aitmc|HX vals = syncTimes.stringValues(); + for (int i=0; iw6Se9ez)4d&z{51keo>hH}e|q=AYwp&*0=qDiNl2r2~jBUFp2lb>^IvN}IlbmNPw%w0%x)(h<;y%9E?t$DFxdfm+XWsW)U; zm$E!#GHX6Eopp?qcMk~}GkGbH(2z7-*P_z1rk{810c%d6=8$Du{$YXbEo(ps5cjr@ z3sm(vDKm~r)N81P7D0o+*7CqlxK4hWYNKcp*f6S~>w%y0uHjpb9f!b14V&-*fePOh z*xfR8(U>v1vWA`R8ueYvPWQI1-il*A5>kIN`OC44N3ca;b9r1t#-y2zVk<2VK*g~c zi3ql@X-P2zap>3~_3jj?Y-t^j5&v!t5!6J{BCvjTcDA#a7@bru>Dx54OPmoSl^XQT zToilh4bQMslg`{-)Dd*8jUWtR9G%!9)$Y>}MJ$R31ro=DJkaw&BIv%O2Z1Y(3Aq=9t)5e*-~QSMS`z;KW3 z2?&@yQS=F{Q#GOw2f6P>(JxRJuJj>#FDuPEp`luOb&!r8a%Q9W7^5|8rmQ?2ILtIW zX{9q!oT6X*=X}@9F((h=jE1uq6^IiSv&Zz48G-7S!NFE0#3O5(Jziq=m^6C~hoU$y z(9{=JiyoAV&U%U9F-Cf2mPYXjQ4t?uL+H`RGNxWEGo2tefqTN<_udZ%G+6HN#Ljy z{bMNmmG_kMmiIaWq0}g)obEq6d~~FLWK4NRVVE>o5)?^4E}7=o%40T*LigtFq!g@Y zj2YA3LtmuGJWpv}o*q|rO57d#WS$VSrs0`7g&MPlYwFHapg-x@#Kgwd8OH&HX{h%Vw6zDk@)@vT~2P41(##kwU$^9FU1>X}E|>OnKJlQp#7gFym!& zJrZLFvNbrEmL;6@tr^2NQv$84JN=naD{ULu{+#9ern@s(b@xWWzPvH$C#R;RaeWzf zXEW8(8i$XW2=ek+TzS%!m!@GBJaHm)l+9!$V`=w3HF=Sny{r4ZJb3DdEZZE(=O#^e zOcsqm(B?tEM`Kt~#c9S*8i|5`l zgF0~p?puRFy(YC5c)8e6?_Yy_xl2o)aEJ&oHH1smNJF)C#XZ&8nJPKMvfoe1a!;g^ zSklc-g&Jz*bJ(wC3|4kRlE)=UQ9)C&BLyuq#8jE{(gHiyu&^ZCDXxy)Tpb$9D0!xS zRm0ctb%E#eteB^EOW9dO$9FV*7vEzrl6T4Hh@cSsK*JC5Bf_+MXW#H z*4S9Uh6Q|ZcoCbqx=*dPjkGO7Kfi$c?_gKkZT=hg@I?Ww!J;EvETWS{58OdF_q!YS z7x1A)9OPC{PgSC7ZvnlDD#=lN=;lL5qN;$yf$n30?w;yE`SCz`PtCIS0kRLYHJ)73 z&c#Pd7el3skzi585J^N5HBxs(N>LA0>r(}sPE;o%3d9((j`u_pQCf5^5lvL{7C?KH zqUe^M*diwAmyfIE<2`Xg>pb7KfKT4Rg`%EX3BPf20o!`CL~TNonrf-?f_#W2YL%*# zF_n?dYxPk|96$fygBlb&y8Qh?}Ok%O&DsOW0$013y*beug(gar@L7h)QtUf|dhSX3_o+4fd;6aLy;Ih|Y(L7syUO|Z83Mmr;*f?_{;fa(J41(L zLjN|?Ar!kX)Giz2yRWFE>1GWphnFVJvy}fF8ko2VrmRewAdbyTdK&SbGD@aORHh0) z^(UzBH)W&RT`sCGknzP5;pL+G+pq^qyQLVu52(JRaXAK6Yiq9_cXEgi| DW*@s+ literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/dialog/ConfigDebugPage.java b/src/cx/fbn/nevernote/dialog/ConfigDebugPage.java new file mode 100644 index 0000000..cffa7a6 --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/ConfigDebugPage.java @@ -0,0 +1,150 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.dialog; + +import com.trolltech.qt.gui.QCheckBox; +import com.trolltech.qt.gui.QComboBox; +import com.trolltech.qt.gui.QGroupBox; +import com.trolltech.qt.gui.QHBoxLayout; +import com.trolltech.qt.gui.QLabel; +import com.trolltech.qt.gui.QTextBrowser; +import com.trolltech.qt.gui.QVBoxLayout; +import com.trolltech.qt.gui.QWidget; + +public class ConfigDebugPage extends QWidget { + + QComboBox messageCombo; + QComboBox serverCombo; + QCheckBox disableUploads; + QCheckBox carriageReturnFix; + public ConfigDebugPage(QWidget parent) { + super(parent); + // Server settings + QGroupBox serverGroup = new QGroupBox(tr("Server Configuration")); + QLabel serverLabel = new QLabel(tr("Server")); + serverCombo = new QComboBox(); + serverCombo.addItem(tr("www.evernote.com")); + serverCombo.addItem(tr("sandbox.evernote.com")); + disableUploads = new QCheckBox(); + disableUploads.setText("Disable uploads to server"); + + QHBoxLayout serverLayout = new QHBoxLayout(); + serverLayout.addWidget(serverLabel); + serverLayout.addWidget(serverCombo); + serverLayout.addWidget(disableUploads); + serverGroup.setLayout(serverLayout); + + QGroupBox messageGroup = new QGroupBox(tr("Debug Messages")); + QLabel messageLevelLabel = new QLabel(tr("Message Level")); + messageCombo = new QComboBox(); + messageCombo.addItem(tr("Low")); + messageCombo.addItem(tr("Medium")); + messageCombo.addItem(tr("High")); + messageCombo.addItem(tr("Extreme")); + + QHBoxLayout messageLayout = new QHBoxLayout(); + messageLayout.addWidget(messageLevelLabel); + messageLayout.addWidget(messageCombo); + messageLayout.setStretch(1, 100); + messageGroup.setLayout(messageLayout); + + QVBoxLayout mainLayout = new QVBoxLayout(); + mainLayout.addWidget(serverGroup); + mainLayout.addWidget(messageGroup); + + QGroupBox crlfGroup = new QGroupBox(tr("Carriage Return Fix")); + String crlfMessage = new String(tr("Note: The carriage return is a test fix. If you " + + "enable it, it will do some modifications to the notes you view to try and" + + " get the carriage returns to look correct. This is due to the way that " + + "the way Evernote 3.1 Windows client is dealing with carriage returns. This fix"+ + "will try and correct this problem. This fix is not permanent unless you edit a note. If" + + "you edit a note, this fix is PERMANENT and will be sent to Evernote on the next sync. I haven't" + + "had any issues with this, but please be aware of this condition.")); + carriageReturnFix = new QCheckBox(this); + QHBoxLayout crlfLayout = new QHBoxLayout(); + QLabel carriageReturnLabel = new QLabel("Enable Carriage Return Fix"); + crlfLayout.addWidget(carriageReturnLabel); + crlfLayout.addWidget(carriageReturnFix); + crlfGroup.setLayout(crlfLayout); + + QTextBrowser msg = new QTextBrowser(this); + msg.setText(crlfMessage); + mainLayout.addWidget(crlfGroup); + + mainLayout.addWidget(msg); + + mainLayout.addStretch(1); + setLayout(mainLayout); + + serverCombo.activated.connect(this, "serverOptionChanged()"); + } + + //****************************************** + //* Message set/get + //****************************************** + public void setDebugLevel(String level) { + int i = messageCombo.findText(level); + if (i>0) + messageCombo.setCurrentIndex(i); + } + public String getDebugLevel() { + int i = messageCombo.currentIndex(); + return messageCombo.itemText(i); + } + public void setCarriageReturnFix(boolean val) { + carriageReturnFix.setChecked(val); + } + public boolean getCarriageReturnFix() { + return carriageReturnFix.isChecked(); + } + + + //****************************************** + //* Server set/get + //****************************************** + public void setServer(String server) { + int i = serverCombo.findText(server); + if (i>0) + serverCombo.setCurrentIndex(i); + } + public String getServer() { + int i = serverCombo.currentIndex(); + return serverCombo.itemText(i); + } + @SuppressWarnings("unused") + private void serverOptionChanged() { + String text = serverCombo.currentText(); + if (text.equalsIgnoreCase("www.evernote.com")) + disableUploads.setChecked(true); + } + //***************************************** + //* Disable uploads + //***************************************** + public void setDisableUploads(boolean val) { + disableUploads.setChecked(val); + } + public boolean getDisableUploads() { + return disableUploads.isChecked(); + } + + + + +} \ No newline at end of file diff --git a/src/cx/fbn/nevernote/dialog/ConfigDialog.class b/src/cx/fbn/nevernote/dialog/ConfigDialog.class new file mode 100644 index 0000000000000000000000000000000000000000..d7c5236249c80d98d8251289c9481aa023841d78 GIT binary patch literal 14154 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 B12X^s literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/dialog/ConfigDialog.java b/src/cx/fbn/nevernote/dialog/ConfigDialog.java new file mode 100644 index 0000000..a4b8eea --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/ConfigDialog.java @@ -0,0 +1,352 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.dialog; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; + +import com.trolltech.qt.core.QSize; +import com.trolltech.qt.core.Qt.AlignmentFlag; +import com.trolltech.qt.core.Qt.ItemFlag; +import com.trolltech.qt.gui.QApplication; +import com.trolltech.qt.gui.QDialog; +import com.trolltech.qt.gui.QHBoxLayout; +import com.trolltech.qt.gui.QIcon; +import com.trolltech.qt.gui.QListView; +import com.trolltech.qt.gui.QListWidget; +import com.trolltech.qt.gui.QListWidgetItem; +import com.trolltech.qt.gui.QPushButton; +import com.trolltech.qt.gui.QStackedWidget; +import com.trolltech.qt.gui.QVBoxLayout; +import com.trolltech.qt.gui.QWidget; + +import cx.fbn.nevernote.Global; +import cx.fbn.nevernote.utilities.AESEncrypter; +public class ConfigDialog extends QDialog { + private final QListWidget contentsWidget; + private final QStackedWidget pagesWidget; + private final ConfigConnectionPage connectionPage; + private final ConfigDebugPage debugPage; + private final ConfigAppearancePage appearancePage; + private final ConfigShowColumnsPage columnsPage; + private final ConfigIndexPage indexPage; + private final ConfigShowEditorButtonsPage editorButtonsPage; + + public ConfigDialog(QWidget parent) { + + contentsWidget = new QListWidget(this); + contentsWidget.setViewMode(QListView.ViewMode.IconMode); + contentsWidget.setIconSize(new QSize(96, 84)); + contentsWidget.setMovement(QListView.Movement.Static); + contentsWidget.setMaximumWidth(128); + contentsWidget.setSpacing(12); + + pagesWidget = new QStackedWidget(this); + connectionPage = new ConfigConnectionPage(this); + appearancePage = new ConfigAppearancePage(this); + indexPage = new ConfigIndexPage(this); + debugPage = new ConfigDebugPage(this); + columnsPage = new ConfigShowColumnsPage(this); + editorButtonsPage = new ConfigShowEditorButtonsPage(this); + pagesWidget.addWidget(appearancePage); + pagesWidget.addWidget(indexPage); + pagesWidget.addWidget(connectionPage); + pagesWidget.addWidget(columnsPage); + pagesWidget.addWidget(editorButtonsPage); + pagesWidget.addWidget(debugPage); + + QPushButton cancelButton = new QPushButton(tr("Cancel")); + QPushButton okButton = new QPushButton(tr("OK")); + okButton.clicked.connect(this, "okPushed()"); + cancelButton.clicked.connect(this, "close()"); + + createIcons(); + contentsWidget.setCurrentRow(0); + + QHBoxLayout horizontalLayout = new QHBoxLayout(); + horizontalLayout.addWidget(contentsWidget); + horizontalLayout.addWidget(pagesWidget,1); + + QHBoxLayout buttonLayout = new QHBoxLayout(); + buttonLayout.addStretch(1); + buttonLayout.addWidget(okButton); + buttonLayout.addWidget(cancelButton); + setWindowTitle(tr("Settings")); + + QVBoxLayout mainLayout = new QVBoxLayout(); + mainLayout.addLayout(horizontalLayout); + mainLayout.addSpacing(1); + mainLayout.addLayout(buttonLayout); + setLayout(mainLayout); + + loadSettings(); + } + public void okPushed() { + Global.setServer(debugPage.getServer()); + AESEncrypter aes = new AESEncrypter(); + aes.setUserid(connectionPage.getUserid().trim()); + + if (debugPage.getDisableUploads()) + Global.disableUploads = true; + else + Global.disableUploads = false; + Global.setDisableUploads(Global.disableUploads); + Global.setMimicEvernoteInterface(appearancePage.getMimicEvernote()); + + if (appearancePage.getShowSplashScreen()) + Global.saveWindowVisible("SplashScreen", true); + else + Global.saveWindowVisible("SplashScreen", false); + + + if (appearancePage.getPdfPreview()) + Global.setPdfPreview(true); + else + Global.setPdfPreview(false); + + Global.setAutoSaveInterval(appearancePage.getAutoSaveInterval()); + + Global.setAutomaticLogin(connectionPage.getAutomaticLogin()); + Global.setRememberPassword(connectionPage.getRememberPassword()); + if (connectionPage.getRememberPassword()) { + aes.setPassword(connectionPage.getPassword()); + } + Global.setShowTrayIcon(appearancePage.getShowTrayIcon()); + Global.setVerifyDelete(appearancePage.getVerifyDelete()); + Global.setSynchronizeOnClose(connectionPage.getSynchronizeOnClose()); + Global.setSynchronizeDeletedContent(connectionPage.getSynchronizeDeletedContent()); + Global.setTagBehavior(appearancePage.getTagBehavior()); + FileOutputStream out = null; + try { + out = new FileOutputStream(Global.getDirectoryPath()+"secure.txt"); + } catch (FileNotFoundException e) { + // if it isn't found we'll write it. + } + if (out != null) + aes.encrypt(out); + Global.userStoreUrl = "https://"+debugPage.getServer()+"/edam/user"; + Global.setWordRegex(indexPage.getRegex()); + Global.setRecognitionWeight(indexPage.getRecognitionWeight()); + Global.setMinimumWordLength(indexPage.getWordLength()); + Global.minimumWordCount = indexPage.getWordLength(); + Global.setIndexThreads(indexPage.getIndexThreads()); + Global.setMessageLevel( debugPage.getDebugLevel()); + Global.saveCarriageReturnFix(debugPage.getCarriageReturnFix()); + Global.enableCarriageReturnFix = debugPage.getCarriageReturnFix(); + + String guiFormat = appearancePage.getStyle(); + QApplication.setStyle(guiFormat); + QApplication.style().standardPalette(); + Global.setStyle(guiFormat); + Global.setStandardPalette(appearancePage.getStandardPalette()); + if (Global.useStandardPalette()) + QApplication.setPalette(QApplication.style().standardPalette()); + else + QApplication.setPalette(Global.originalPalette); + + String dateFmt = appearancePage.getDateFormat(); + String timeFmt = appearancePage.getTimeFormat(); + int dash = dateFmt.indexOf("-"); + dateFmt = dateFmt.substring(0,dash-1); + dash = timeFmt.indexOf("-"); + timeFmt = timeFmt.substring(0,dash-1); + + Global.setDateFormat(dateFmt); + Global.setTimeFormat(timeFmt); + + Global.setSyncInterval(connectionPage.getSyncInterval()); + + Global.saveColumnVisible("dateCreated", columnsPage.showDateCreated()); + Global.saveColumnVisible("dateChanged", columnsPage.showDateChanged()); + Global.saveColumnVisible("dateSubject", columnsPage.showDateSubject()); + Global.saveColumnVisible("author", columnsPage.showAuthor()); + Global.saveColumnVisible("sourceUrl", columnsPage.showSourceUrl()); + Global.saveColumnVisible("synchronized", columnsPage.showSynchronized()); + Global.saveColumnVisible("notebook", columnsPage.showNotebook()); + Global.saveColumnVisible("tags", columnsPage.showTags()); + + Global.saveEditorButtonsVisible("undo", editorButtonsPage.showUndo()); + Global.saveEditorButtonsVisible("redo", editorButtonsPage.showRedo()); + Global.saveEditorButtonsVisible("cut", editorButtonsPage.showCut()); + Global.saveEditorButtonsVisible("copy", editorButtonsPage.showCopy()); + Global.saveEditorButtonsVisible("paste", editorButtonsPage.showPaste()); + Global.saveEditorButtonsVisible("underline", editorButtonsPage.showUnderline()); + Global.saveEditorButtonsVisible("strikethrough", editorButtonsPage.showStrikethrough()); + Global.saveEditorButtonsVisible("italic", editorButtonsPage.showItalic()); + Global.saveEditorButtonsVisible("bold", editorButtonsPage.showBold()); + Global.saveEditorButtonsVisible("font", editorButtonsPage.showFont()); + Global.saveEditorButtonsVisible("fontSize", editorButtonsPage.showFontSize()); + Global.saveEditorButtonsVisible("fontColor", editorButtonsPage.showFontColor()); + Global.saveEditorButtonsVisible("fontHilight", editorButtonsPage.showFontHilight()); + Global.saveEditorButtonsVisible("indent", editorButtonsPage.showIndent()); + Global.saveEditorButtonsVisible("outdent", editorButtonsPage.showOutdent()); + Global.saveEditorButtonsVisible("numberList", editorButtonsPage.showNumberList()); + Global.saveEditorButtonsVisible("bulletList", editorButtonsPage.showBulletList()); + Global.saveEditorButtonsVisible("alignCenter", editorButtonsPage.showAlignCenter()); + Global.saveEditorButtonsVisible("alignLeft", editorButtonsPage.showAlignLeft()); + Global.saveEditorButtonsVisible("alignRight", editorButtonsPage.showAlignRight()); + close(); + } + @Override + public void reject() { + QApplication.setStyle(Global.getStyle()); + super.reject(); + } + + public ConfigDebugPage getDebugPage() { + return debugPage; + } + + + public ConfigConnectionPage getConfigPage() { + return connectionPage; + } + + public void createIcons() { + String iconPath = new String("classpath:cx/fbn/nevernote/icons/"); + + + QListWidgetItem formatsButton = new QListWidgetItem(contentsWidget); + formatsButton.setText(tr("Appearance")); + formatsButton.setTextAlignment(AlignmentFlag.AlignHCenter.value()); + formatsButton.setFlags(ItemFlag.ItemIsSelectable, ItemFlag.ItemIsEnabled); + formatsButton.setIcon(new QIcon(iconPath+"appearance.jpg")); + + QListWidgetItem indexButton = new QListWidgetItem(contentsWidget); + indexButton.setText(tr("Indexing")); + indexButton.setTextAlignment(AlignmentFlag.AlignHCenter.value()); + indexButton.setFlags(ItemFlag.ItemIsSelectable, ItemFlag.ItemIsEnabled); + indexButton.setIcon(new QIcon(iconPath+"search_config.jpg")); + + QListWidgetItem configButton = new QListWidgetItem(contentsWidget); + configButton.setText(tr("Connection")); + configButton.setTextAlignment(AlignmentFlag.AlignHCenter.value()); + configButton.setFlags(ItemFlag.ItemIsSelectable, ItemFlag.ItemIsEnabled); + configButton.setIcon(new QIcon(iconPath+"synchronize.png")); + + QListWidgetItem columnsButton = new QListWidgetItem(contentsWidget); + columnsButton.setText(tr("Hide Columns")); + columnsButton.setTextAlignment(AlignmentFlag.AlignHCenter.value()); + columnsButton.setFlags(ItemFlag.ItemIsSelectable, ItemFlag.ItemIsEnabled); + columnsButton.setIcon(new QIcon(iconPath+"show-columns.png")); + + QListWidgetItem editorButton = new QListWidgetItem(contentsWidget); + editorButton.setText(tr("Hide Edit Buttons")); + editorButton.setTextAlignment(AlignmentFlag.AlignHCenter.value()); + editorButton.setFlags(ItemFlag.ItemIsSelectable, ItemFlag.ItemIsEnabled); + editorButton.setIcon(new QIcon(iconPath+"scissors.jpg")); + + QListWidgetItem debugButton = new QListWidgetItem(contentsWidget); + debugButton.setText(tr("Debugging")); + debugButton.setTextAlignment(AlignmentFlag.AlignHCenter.value()); + debugButton.setFlags(ItemFlag.ItemIsSelectable, ItemFlag.ItemIsEnabled); + debugButton.setIcon(new QIcon(iconPath+"debug.jpg")); + + contentsWidget.currentItemChanged.connect(this, "changePage(QListWidgetItem, QListWidgetItem)"); + } + + protected void changePage(QListWidgetItem current, QListWidgetItem previous) { + pagesWidget.setCurrentIndex(contentsWidget.row(current)); + } + + private void loadSettings() { + Global.originalPalette = QApplication.palette(); + + debugPage.setServer(Global.getServer()); + debugPage.setDisableUploads(Global.disableUploads); +// if (Global.getUpdateSequenceNumber() > 0) + debugPage.serverCombo.setEnabled(false); + + if (Global.username.equalsIgnoreCase("") || Global.password.equalsIgnoreCase("")) { + AESEncrypter aes = new AESEncrypter(); + try { + aes.decrypt(new FileInputStream(Global.getDirectoryPath()+"secure.txt")); + } catch (FileNotFoundException e) { + // File not found, so we'll just get empty strings anyway. + } + String userid = aes.getUserid(); + String password = aes.getPassword(); + if (!userid.equals("") && !password.equals("")) { + Global.username = userid; + Global.password = password; + } + } + appearancePage.setAutoSaveInterval(Global.getAutoSaveInterval()); + connectionPage.setUserid(Global.username); + connectionPage.setPassword(Global.password); + connectionPage.setAutomaticLogin(Global.automaticLogin()); + connectionPage.setRememberPassword(Global.rememberPassword()); + appearancePage.setMimicEvernote(Global.getMimicEvernoteInterface()); + appearancePage.setShowTrayIcon(Global.showTrayIcon()); + connectionPage.setSynchronizeOnClose(Global.synchronizeOnClose()); + connectionPage.setSyncronizeDeletedContent(Global.synchronizeDeletedContent()); + appearancePage.setVerifyDelete(Global.verifyDelete()); + appearancePage.setPdfPreview(Global.pdfPreview()); + appearancePage.setShowSplashScreen(Global.isWindowVisible("SplashScreen")); + appearancePage.setTagBehavior(Global.tagBehavior()); + + indexPage.setRegex(Global.getWordRegex()); + indexPage.setWordLength(Global.getMinimumWordLength()); + indexPage.setIndexThreads(Global.getIndexThreads()); + connectionPage.setSyncInterval(Global.getSyncInterval()); + + appearancePage.setDateFormat(Global.getDateFormat()); + appearancePage.setTimeFormat(Global.getTimeFormat()); + appearancePage.setStyle(Global.getStyle()); + appearancePage.setStandardPalette(Global.useStandardPalette()); + + columnsPage.setDateCreated(Global.isColumnVisible("dateCreated")); + columnsPage.setDateSubject(Global.isColumnVisible("dateSubject")); + columnsPage.setDateChanged(Global.isColumnVisible("dateChanged")); + columnsPage.setAuthor(Global.isColumnVisible("author")); + columnsPage.setSourceUrl(Global.isColumnVisible("sourceUrl")); + columnsPage.setTags(Global.isColumnVisible("tags")); + columnsPage.setSynchronized(Global.isColumnVisible("synchronized")); + columnsPage.setNotebook(Global.isColumnVisible("notebook")); + + editorButtonsPage.setUndo(Global.isEditorButtonVisible("undo")); + editorButtonsPage.setRedo(Global.isEditorButtonVisible("redo")); + editorButtonsPage.setCut(Global.isEditorButtonVisible("cut")); + editorButtonsPage.setCopy(Global.isEditorButtonVisible("copy")); + editorButtonsPage.setPaste(Global.isEditorButtonVisible("paste")); + editorButtonsPage.setBold(Global.isEditorButtonVisible("bold")); + editorButtonsPage.setItalic(Global.isEditorButtonVisible("italic")); + editorButtonsPage.setUnderline(Global.isEditorButtonVisible("underline")); + editorButtonsPage.setStrikethrough(Global.isEditorButtonVisible("strikethrough")); + editorButtonsPage.setIndent(Global.isEditorButtonVisible("indent")); + editorButtonsPage.setHline(Global.isEditorButtonVisible("hline")); + editorButtonsPage.setOutdent(Global.isEditorButtonVisible("outdent")); + editorButtonsPage.setBulletList(Global.isEditorButtonVisible("bulletList")); + editorButtonsPage.setNumberList(Global.isEditorButtonVisible("numberList")); + editorButtonsPage.setFont(Global.isEditorButtonVisible("font")); + editorButtonsPage.setFontSize(Global.isEditorButtonVisible("fontSize")); + editorButtonsPage.setFontColor(Global.isEditorButtonVisible("fontColor")); + editorButtonsPage.setFontHighlight(Global.isEditorButtonVisible("fontHilight")); + editorButtonsPage.setAlignLeft(Global.isEditorButtonVisible("alignLeft")); + editorButtonsPage.setAlignCenter(Global.isEditorButtonVisible("alignCenter")); + editorButtonsPage.setAlignRight(Global.isEditorButtonVisible("alignRight")); + + debugPage.setDebugLevel(Global.getMessageLevel()); + debugPage.setCarriageReturnFix(Global.enableCarriageReturnFix()); + + } + +} diff --git a/src/cx/fbn/nevernote/dialog/ConfigFormatsPage.class b/src/cx/fbn/nevernote/dialog/ConfigFormatsPage.class new file mode 100644 index 0000000000000000000000000000000000000000..5abf0b2954f141a2d91dafccad9f6773a9cf753a GIT binary patch literal 3049 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 PYJgC>mk*2S8{+>D(T*6g literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/dialog/ConfigIndexPage.class b/src/cx/fbn/nevernote/dialog/ConfigIndexPage.class new file mode 100644 index 0000000000000000000000000000000000000000..41406c34a725450a9088e4b2636e94ba6fd2033d GIT binary patch literal 2878 zcmaJ@TW}Lq82(P1c9ZQEYN=r47C_siK*LQgZ3Ur1DWnzBHc(Jt+Z@t`BwIF{5>OQH z7aU(4AAR*nXVj6@v7>LkI6nI3yEDG|%8TQ7b~kOM3DcQ9m;d&i|Ns6!{q5hMegUu# zpK53l=$WY`uTK|~ML92>qV39L)-v;UE;(cuuUom1VpdkpnK`K;B(Q15E+k#Y&gWe@ zGn>5SCUa#gdH#Zx%}H0F(^A?KvyL>g<8xNAC>?>Vsrp7r;e=fo5NOZKV$PjivWPe` zCo3nj7G1^~Sf{L_R2npI9khy;dsJXsyn(WhZy=Eo2o2d;siPTd4Cq)Z&>T->G(07+ z`H3)fbYPt_X^TMMX#*{2Rd*WcO9#k8%V6a(y_(eF#LQ;>v}#BSY^m>H*s;rVbP~p1 zfgK)~2(Vrf}&O~*~>=tH;q95C<#4l)k&>O*)!eSHPiH;lsqZ5M1O z8%ued3Zq|O-Kd}X*b0HF&Kgz97Y%5BDUTU=3C9J(44GzHr9ex3B&g(&ftOV!+bJC9 z8}f48m2(lC!f6e|0vlGf(Qw|LHuDBXa7Lh`;6qRdhU{{Y%oZaGL(0IY@~eVo%zRmf z@e0}GAw6e0C7#c-vC=YE&YMo`WMz)&Dp__>!+68A*P25|+J9umKo}97XfGO=!X*KN z4Xc9Cv8)Jm#p{wMjaLo4rpTia--N8V8m=~^OJ)UKt|+=(!7lZgF_87TfSe&!r8_gL z_HhTK`JB#=n0N^<>KrG~Jm#E3fxB1sbS(Vl}IL?NW`C+Z*UFw+@Yrz{qQd#xt$fEwosBo3-&N92l**37~c? z>(tQb-sB7{{6nDJ=1G?H3Z_-89U47hxt!|VtiR%mkBMWGGn=;oiX+DS6UiSy%j5oCW|BcsnJ{tv#-MM<0u}f&>F;+4ABLg2RDu-P1l07qSmz^1T z%2G7ydhFM$PYp|KBkP*^+t-XvHNUy*RL$?L><_LQH8|t>HGrne2&q*J^e&*icM%;^ z+;l!fSMLw#3RkgSt)VKOUBu?8-p;L6Y+Jzdql<`7EueR7_pT~-?p8Wn7tu$RJ)X+G z{!lcuyNdn(<)PrR#dmYWchleMMO?tZLk!Z%U~7k7#Zk3m$P;S)9w)0f8-(lEqFS_- zk)oQCsZC2%TM9B31PS{=&ILgt43Z|=iHDe^+2oJ7P{rk%OFgPbBg&JmWNH(R5(IHy zq0P1awrE?FU`#G8{=%&A#JlOKXJ0`UW*ZKX7zg|E$Q<~u1>*depPQ*Cr`;f#z z?7;x`Vu=5iq_H0taR@ma#ypPTZS>;-rJrLEU*agf!ZCcqNnOQp{LG2=JBINmPUA05 z+JA5skB}0;sEA-pbZ~e^krpuy%N|UKK1_-O$cTOp!5q=t^~;M{SUj=NxPhB2exGPZ z9t9#lC|Xd2P0FP4H|B7Q_;dIJ4tFiY_bW=&YbB~L;8IT`9vfv!!$ftB8U+&T5l-MX z?{%WtjtcI06uXP4Pc*)yiGM&uRc<3|x|}xM6I`XcYaZnFzG4kBoxhGVbR+Nv?gj4l zd1oN(6XDIT>Dn(sD<#0R=gIK);lPt%qU*uwst4x=;oNKh=Y9a^ow{(?3aj80>cV*! xJ;8HUW@mCI>G^ne<_YI^132&DeJ>jy;8NgjWp>Ev55IjZJ9p~B`NY$D@E>pxsptRz literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/dialog/ConfigIndexPage.java b/src/cx/fbn/nevernote/dialog/ConfigIndexPage.java new file mode 100644 index 0000000..e2fce00 --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/ConfigIndexPage.java @@ -0,0 +1,151 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.dialog; + +import com.trolltech.qt.gui.QGroupBox; +import com.trolltech.qt.gui.QHBoxLayout; +import com.trolltech.qt.gui.QLabel; +import com.trolltech.qt.gui.QLineEdit; +import com.trolltech.qt.gui.QSpinBox; +import com.trolltech.qt.gui.QVBoxLayout; +import com.trolltech.qt.gui.QWidget; + +import cx.fbn.nevernote.Global; + +public class ConfigIndexPage extends QWidget { + + private final QSpinBox indexThreadSpinner; + private final QSpinBox lengthSpinner; + private final QSpinBox weightSpinner; + private final QLineEdit regexEdit; + + public ConfigIndexPage(QWidget parent) { +// super(parent); + + indexThreadSpinner = new QSpinBox(this); + indexThreadSpinner.setMaximum(5); + indexThreadSpinner.setMinimum(1); + + // Index threads layout + QLabel threadLabel = new QLabel(tr("Maximum Threads")); + QHBoxLayout threadsLayout = new QHBoxLayout(); + threadsLayout.addWidget(threadLabel); + threadsLayout.addWidget(indexThreadSpinner); + QGroupBox threadsGroup = new QGroupBox(tr("Indexing Threads (Requires Restart)")); + threadsGroup.setLayout(threadsLayout); + + threadsGroup.setVisible(false); + + + // Minimum word length + QGroupBox wordLengthGroup = new QGroupBox(tr("Word Length")); + QLabel wordLengthLabel = new QLabel(tr("Minimum Word Length")); + lengthSpinner = new QSpinBox(); + lengthSpinner.setRange(3,10); + lengthSpinner.setSingleStep(1); + lengthSpinner.setValue(Global.minimumWordCount); + + QHBoxLayout wordLengthLayout = new QHBoxLayout(); + wordLengthLayout.addWidget(wordLengthLabel); + wordLengthLayout.addWidget(lengthSpinner); + wordLengthGroup.setLayout(wordLengthLayout); + + + // Minimum word length + QGroupBox weightGroup = new QGroupBox(tr("Recognition")); + QLabel weightLabel = new QLabel(tr("Minimum Recognition Weight")); + weightSpinner = new QSpinBox(); + weightSpinner.setRange(1,100); + weightSpinner.setSingleStep(1); + weightSpinner.setValue(Global.getRecognitionWeight()); + + QHBoxLayout weightLayout = new QHBoxLayout(); + weightLayout.addWidget(weightLabel); + weightLayout.addWidget(weightSpinner); + weightGroup.setLayout(weightLayout); + + + // Regular Expressions for word parsing + QGroupBox regexGroup = new QGroupBox(tr("Word Parse")); + QLabel regexLabel = new QLabel(tr("Regular Expression")); + regexEdit = new QLineEdit(); + regexEdit.setText(Global.getWordRegex()); + + QHBoxLayout regexLayout = new QHBoxLayout(); + regexLayout.addWidget(regexLabel); + regexLayout.addWidget(regexEdit); + regexGroup.setLayout(regexLayout); + + + QVBoxLayout mainLayout = new QVBoxLayout(); + mainLayout.addWidget(threadsGroup); + mainLayout.addWidget(wordLengthGroup); + mainLayout.addWidget(weightGroup); + mainLayout.addWidget(regexGroup); + mainLayout.addStretch(1); + setLayout(mainLayout); + + + } + + //***************************************** + //* Word length get/set methods + //***************************************** + public void setWordLength(int len) { + lengthSpinner.setValue(len); + } + public int getWordLength() { + return lengthSpinner.value(); + } + + + //***************************************** + //* Recognition Weight + //***************************************** + public void setRecognitionWeight(int len) { + weightSpinner.setValue(len); + } + public int getRecognitionWeight() { + return weightSpinner.value(); + } + + //***************************************** + //* Index Threads get/set methods + //***************************************** + public void setIndexThreads(int value) { + indexThreadSpinner.setValue(value); + } + public int getIndexThreads() { + return indexThreadSpinner.value(); + } + + + + //***************************************** + //* Regex get/set methods + //***************************************** + public void setRegex(String s) { + regexEdit.setText(s); + } + public String getRegex() { + return regexEdit.text(); + } + +} diff --git a/src/cx/fbn/nevernote/dialog/ConfigShowColumnsPage.class b/src/cx/fbn/nevernote/dialog/ConfigShowColumnsPage.class new file mode 100644 index 0000000000000000000000000000000000000000..c5ab2065b97257ba5f403e8fefd169b5bb2db249 GIT binary patch literal 4917 zcmb7HZERat8Gg>S9XrlVY^Ph`u3br6Xp^*=Sz%q<6zH0Mg(c~lw8@e()*JiQc4GUc z_I28{?5o?@)_u1yR_NHqx=k7sY15jbMN~rtCQU;iF-=0E+An^A_6H;+gn;MV4=3}- z6#n=<_dW0XJolXQzR$US|3B|s0k9FT1)&IZCyvLDOyuKvW5y`tP0NTUGkVrc#e2>C zkxXhhZ6512v!z_Vc!!=cg76EhNSL{}RWP$z%Sfc-N3D3Ol!@;j%_LKXB@ihxXQyr% zy#<56Nr5%}wKInFWX9Z4vMe*-!@P7RX?!ZLj5J)Dm^2a++lyK7l-bgHJ|)@8F}5%=q!ES>D^z?QS`aG*R@Od+Jq5EgO^OiOxfXcy~}LMET;>8y5zaU<4B-gN@k*Gd@)qLXW`{XTp7F8%tfS+c_D zzD81WMd=1?0aM7^1R>Ml91p*y?eVrq6f!kHwh8;}ewDY>3aWYN-PbP$& z++??U+vR4$k#pikwpie!}>6C*dl)lDvDt9 zhj~2ZgYb9Q=OD119p9hH8-u0Xgi$!4Ph{D*t^H;~&yMJYjC^*Tek+|}BggyyFUgag zH?0?pJl|mDXEz=jJ-MKJc3;)+Y_IKzA6t~=mD1`uR14j~M4QenCYR2}a$O!)OIhXI zph(%_g*555Ji7C$^W;rBt8$8HF^wy*URbldKBOeNF)iM+7tm<2irmSt9D5V7;v%{9 z0;JCi2LjI0%*|^;}tKxf7Q38o4lQNCMb`+K*EDwV>!Pz0Lz=yjGrkWbF_5s_hw7Ho^#xO}yj zRr~}mQd2U;-n5aJl6Ob5eVr_zy0Wl4BkTNznz!^#Qlznp?dRi7A7ejL{5Wcrf@fQ* zjcutlwxuT6mWp6oDv52WBetdT*p|9uTWWx9sQ|X6V%U~?VO#dRZQ1d(KpQ^C-x%MB zml1z&00KAjt(F14HC^j3WBEL89P4WR!W>pz#+L@>(J^)zU4vco=%zbvyKlaPjjrRX zo?}yY*W1`Qht1M%lGYzh&Y@>R_Z+_AVD>tgTm3HR)<7ldu1eHBT7Yo72xkxW*aHVx z^J{@Jbe{{|;6Vo~p>MB*9?*h>zFi{9!GJw*p&PVd8G4@!9rBZ3u?&6Cg${erO_k82mC$2a6A?!xq8yCb0~b21HI<@y7Rjs)Ut-H`I9(1GEk?wQM3jRmd*DJxwU`Z^V+osETea2=bC}jzwXkFSj!_-c;+O`KB7`9k!9lT-Ul8jsDmLRz(T6cH zgmG~QheU$k43ju4W}%By{5m*`gt&mDxClec;fT0`l=uxM#fO*@*N_#TASeEdyb^+` z#4xRBII6V6QsO8nn=zyG;g~Xx<4OXvN){&+3n!J6xK}xi`;@b|U%7w>luJ0JT)~6N zdw59sJsws*!XwJZcvSfd9#j5?)5_oRxbiPN;S+e$7s6A%2%h$};ThiwJnLJHGdRXw zd)JX09LFr5C_FfUlN6(6z9_zfd$_~PnR_qpqim*?dE8H*pYQq>9-uFPtIA>SN0h-cvSNI)VwmOU@Avup96unR=SSE%dpFvgY;QNv#+c`b`2$A#p|mt`{Cr)u zU1c_kV-?$ZBD_Gh7s>Y0lG)DHWux%8Yoqd1vAsgJ3uJqZY_Bhw?T2;QsGu$zCA5m| z4YK`|Y!}J)^Ch$Ws4g3?0+)?2=wty;W?#B-<6Ty-T)VEt&1db=j!KE*s^zitQ@deoeODlI^`Evjteg z_U8&Um!F92jgZr8Fa3;TTa&2=(*M4VsX8%kSMfhf&3x8#RsQd4=7(zLv-_&@|4=hu zt(ngXugd>p&HPtt=Cfw2@;|DXAFY|sx~R(kQ_cMAYUcB#tMdO`GrzTFKD(eQ|KpnZ J7wl7h^?!;CGl~EJ literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/dialog/ConfigShowColumnsPage.java b/src/cx/fbn/nevernote/dialog/ConfigShowColumnsPage.java new file mode 100644 index 0000000..e338e93 --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/ConfigShowColumnsPage.java @@ -0,0 +1,231 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.dialog; + +import com.trolltech.qt.gui.QComboBox; +import com.trolltech.qt.gui.QGroupBox; +import com.trolltech.qt.gui.QHBoxLayout; +import com.trolltech.qt.gui.QRadioButton; +import com.trolltech.qt.gui.QVBoxLayout; +import com.trolltech.qt.gui.QWidget; + +public class ConfigShowColumnsPage extends QWidget { + private final QRadioButton showDateCreated; + private final QRadioButton hideDateCreated; + private final QRadioButton showDateSubject; + private final QRadioButton hideDateSubject; + private final QRadioButton showDateChanged; + private final QRadioButton hideDateChanged; + private final QRadioButton showAuthor; + private final QRadioButton hideAuthor; + private final QRadioButton sourceUrlShow; + private final QRadioButton sourceUrlHide; + private final QRadioButton showTags; + private final QRadioButton hideTags; + private final QRadioButton showNotebook; + private final QRadioButton hideNotebook; + private final QRadioButton showSynchronized; + private final QRadioButton hideSynchronized; + + + QComboBox messageCombo; + public ConfigShowColumnsPage(QWidget parent) { + super(parent); + + // Date Created Column + QGroupBox dateCreatedGroup = new QGroupBox(tr("Date Created")); + QHBoxLayout dateCreatedLayout = new QHBoxLayout(); + showDateCreated = new QRadioButton(tr("Show")); + hideDateCreated = new QRadioButton(tr("Hide")); + dateCreatedLayout.addWidget(showDateCreated); + dateCreatedLayout.addWidget(hideDateCreated); + dateCreatedLayout.setStretch(1, 100); + dateCreatedGroup.setLayout(dateCreatedLayout); + + + // Subject Date Column + QGroupBox dateSubjectGroup = new QGroupBox(tr("Subject Date")); + QHBoxLayout dateSubjectLayout = new QHBoxLayout(); + showDateSubject = new QRadioButton(tr("Show")); + hideDateSubject = new QRadioButton(tr("Hide")); + dateSubjectLayout.addWidget(showDateSubject); + dateSubjectLayout.addWidget(hideDateSubject); + dateSubjectLayout.setStretch(1, 100); + dateSubjectGroup.setLayout(dateSubjectLayout); + + + // Title Column + QGroupBox sourceUrlGroup = new QGroupBox(tr("Source URL")); + QHBoxLayout sourceUrlLayout = new QHBoxLayout(); + sourceUrlShow = new QRadioButton(tr("Show")); + sourceUrlHide = new QRadioButton(tr("Hide")); + sourceUrlLayout.addWidget(sourceUrlShow); + sourceUrlLayout.addWidget(sourceUrlHide); + sourceUrlLayout.setStretch(1, 100); + sourceUrlGroup.setLayout(sourceUrlLayout); + + // Author Column + QGroupBox authorGroup = new QGroupBox(tr("Author")); + QHBoxLayout authorLayout = new QHBoxLayout(); + showAuthor = new QRadioButton(tr("Show")); + hideAuthor = new QRadioButton(tr("Hide")); + authorLayout.addWidget(showAuthor); + authorLayout.addWidget(hideAuthor); + authorLayout.setStretch(1, 100); + authorGroup.setLayout(authorLayout); + + + // Date Changed Column + QGroupBox dateChangedGroup = new QGroupBox(tr("Date Changed")); + QHBoxLayout dateChangedLayout = new QHBoxLayout(); + showDateChanged = new QRadioButton(tr("Show")); + hideDateChanged = new QRadioButton(tr("Hide")); + dateChangedLayout.addWidget(showDateChanged); + dateChangedLayout.addWidget(hideDateChanged); + dateChangedLayout.setStretch(1, 100); + dateChangedGroup.setLayout(dateChangedLayout); + + // Notebook Column + QGroupBox notebookGroup = new QGroupBox(tr("Notebook")); + QHBoxLayout notebookLayout = new QHBoxLayout(); + showNotebook = new QRadioButton(tr("Show")); + hideNotebook = new QRadioButton(tr("Hide")); + notebookLayout.addWidget(showNotebook); + notebookLayout.addWidget(hideNotebook); + notebookLayout.setStretch(1, 100); + notebookGroup.setLayout(notebookLayout); + + // Tags Column + QGroupBox tagsGroup = new QGroupBox(tr("Tags")); + QHBoxLayout tagsLayout = new QHBoxLayout(); + showTags = new QRadioButton(tr("Show")); + hideTags = new QRadioButton(tr("Hide")); + tagsLayout.addWidget(showTags); + tagsLayout.addWidget(hideTags); + tagsLayout.setStretch(1, 100); + tagsGroup.setLayout(tagsLayout); + + // Synchronized Column + QGroupBox synchronizedGroup = new QGroupBox(tr("Synchronized Indicator")); + QHBoxLayout syncLayout = new QHBoxLayout(); + showSynchronized = new QRadioButton(tr("Show")); + hideSynchronized = new QRadioButton(tr("Hide")); + syncLayout.addWidget(showSynchronized); + syncLayout.addWidget(hideSynchronized); + syncLayout.setStretch(1, 100); + synchronizedGroup.setLayout(syncLayout); + + QVBoxLayout mainLayout = new QVBoxLayout(); + mainLayout.addWidget(dateCreatedGroup); + mainLayout.addWidget(dateChangedGroup); + mainLayout.addWidget(dateSubjectGroup); + mainLayout.addWidget(notebookGroup); + mainLayout.addWidget(tagsGroup); + mainLayout.addWidget(sourceUrlGroup); + mainLayout.addWidget(authorGroup); + mainLayout.addWidget(synchronizedGroup); + mainLayout.addStretch(1); + setLayout(mainLayout); + } + + public void setDateCreated(boolean value) { + if (value) + showDateCreated.click(); + else + hideDateCreated.click(); + } + + public void setDateSubject(boolean value) { + if (value) + showDateSubject.click(); + else + hideDateSubject.click(); + } + + public void setDateChanged(boolean value) { + if (value) + showDateChanged.click(); + else + hideDateChanged.click(); + } + + public void setAuthor(boolean value) { + if (value) + showAuthor.click(); + else + hideAuthor.click(); + } + + public void setSourceUrl(boolean value) { + if (value) + sourceUrlShow.click(); + else + sourceUrlHide.click(); + } + public void setNotebook(boolean value) { + if (value) + showNotebook.click(); + else + hideNotebook.click(); + } + public void setTags(boolean value) { + if (value) + showTags.click(); + else + hideTags.click(); + } + public void setSynchronized(boolean value) { + if (value) + showSynchronized.click(); + else + hideSynchronized.click(); + } + + public boolean showDateCreated() { + return showDateCreated.isChecked(); + } + public boolean showDateChanged() { + return showDateChanged.isChecked(); + } + public boolean showDateSubject() { + return showDateSubject.isChecked(); + } + public boolean showAuthor() { + return showAuthor.isChecked(); + } + public boolean showSourceUrl() { + return sourceUrlShow.isChecked(); + } + public boolean showTags() { + return showTags.isChecked(); + } + public boolean showSynchronized() { + return showSynchronized.isChecked(); + } + public boolean showNotebook() { + return showNotebook.isChecked(); + } + + + + + + +} \ No newline at end of file diff --git a/src/cx/fbn/nevernote/dialog/ConfigShowEditorButtonsPage.class b/src/cx/fbn/nevernote/dialog/ConfigShowEditorButtonsPage.class new file mode 100644 index 0000000000000000000000000000000000000000..f0fae18110bd99a8f2fa3825703af333fc4d6768 GIT binary patch literal 10863 zcmbVR33yf2wO;#-H#a9U1P((;!jyzS6jTtjRU!h`a6^Z6}Lqj53T~{$PQBm6(s~B@-tfn@aU=(UW=7gr2 zIHT@W!J%U#HLd9JWJs>u;6TY+uzP@##)%J_^qGSX4gc;x6v zOCriBjmJt|L=TNO)W~Q@4fE)ciAY1Nno*dCyNe8Y57Fj^SQD@^m(pMQfra+Jw7G=b7HhxvD0|iJ3g{3SV9Meba)w1b z17R8K5Q%4Sy1{CUwzOccR>m8rVILJH*@MD8G(H;}(6}Jh6ifVwQBg^fU}tX+DV@kj ztBlt~!=%!A7WJnACJka#5WLNYV`t0&MTiC?kMHm>F}lE_3khUO0yo&Jr0SZ;tVl&e zq^Y)oZ=R;wA*F3iVH!vmalVTgwGT>}Xi_EaHTXJ4;2NqTbKV=OYs;2h&D8czdo1|u~! z&a>mzi56W+|BIv65>4PxDFw#(1g^I-kZ?~wU z6L^P3HV?cL1yq(99&oosot%JsE$Ykz?&lXIiVgQaU{M#x|DZ)(x&L9*DyQ6lrA0iJ zM=dIFg4S5njR!rBt9B|*w8jg2!lFVa?3Wf5@v!xHFT6gqaH=OQDt6pYS=61opT@)G z?m}LXc*quudN?85Eb7Tap21EMA)+ktm>m}Na$=sds5g(Qn^@>G(dDQRmjGQP@ zpm@-07WH$2-ms{G43pkWdRB)w$7a zbA(6J+Snuy8wdN7MMt?a1J1Fchw)>`>(XRwBffW>cQ-yVtpS}Nw<=y8X_y#kj`6iL zYKgj73!`(Z{vQ(rFSj!y&7$uW{BX6!4roQq6jc<@D@m|hWC0xJ;cn$9P7;5r7$PIB z8FfPvgt_i!hiC91LVD80!gZxpqg=Q-Tz4Iz>ehs`r$KeinYb#aMo4FtXK+K(rlCf- zkX&~i=`k^#NSEcTTxV{}=>v$2$vea7hKA9Wo4nf*3)f|#E$~@G=4Z&I>rRh}df;7w zSh>!uY2Gj*1F}z9yr3p;9&v+CS=^ws={W1s9p<|0$lwcJ1Ee$4UAqCoAS!^2$l?*g z;D+RKi&p?-Sl$^%H#9TijwddfXK+KZg~cfWGAQRXlN**LY@!CpC?`=^+@Nq{B-Z3E zlI_@2B>_9u#JQayhHI^4GVhzinQgI7yrJvW7-Z`qXGI!XadsI_H2O!Ry8iOW40&{U zx-(Q8ygG=Pnk&vA4NVTr7F5u<^Da+wW@g@;-6@$Dm^1nlW=fdkj4L9=c5yns>^x5C zak_{zqw-SZ6dh;H$u7kkLm`!#oJ!?Nyj!Qd@i6bjqC6wwV)q52^1DlSoa9WxFK0)L zK$H0sJjY_^vi>Lsv6jlZXmx!QLxUJb9eg>`hR4NQo2#Rj#&}^Y{DEId{rE_SE{EX( zzqk6Jtz%SzmdnQ@Au*!}i3vqWOcp|7t`HJqh>#dUgv8JyBt{k?F-QoBF+xZT4nksV z5E5gEkQhRQ#Ka&Z<^>@!7zl~6KuF91LShOK5`AAtbbTSw;)O(m7ZSZ(NOW=`(Y%F3 z>lPB7T1fP1A<>nEL{AnH-B(ETULnzGg+!kf5^lh7d-I?WGV?}u)*(|}md5xLSR z6bT)&(>&<7gbusV>3-;$e&`lE9f&hIB3D|3BB8@}x(D4Vp)D6W!w-F}A9{|R0mN%L zB3I@JMM7J4h6jDUgwAxKv;5HW{Ll;REFjL~h+J796bYSaXL-;!Na$=AI>!%vqaS*a zodd)hIU-jU2}MF@+c_TeEfPA{h0gOsFZM&QV;K-|C) zxw26x61u?d=0R_g(1k8^kso@qA9|}@1jNl8ktwgrLXptLc6SeYmxS)&LihATKktX$WA_B&^Bj>YdxRpPd)Pfa=ock)FBiJE zA9}AJdcWNph~nB3E7(ii9q)OFigA z5*qoUD-Q1Chkn%${kq);h_7-)uDmW330-FQ5zvRxVUG+hx68{_bsN29m)n}EIZ9a7 z9VMhmm!U~lrY2q4x^!8(bmi*O)y|Nvj)rvQ8`9Oul&&tObQOf8r7$Ed#UUBo!<0&| zY!|U4+l4I4mY4=_`0v=|*(O*1SZ0@RqxUyq+)(HPA~lm3X&T zADY(CJhp-6vu(71?WUixy>ugcgKlE)(IR%7Ze}Ox76qS_lpI>D*tA3`q@_v)-KGqp zWy(mpU71YFm1?>}X`mHKg6>qVr+bwpbf2<cwPHU8t^q87WkE=GVRg38fwT#xOXVV7tB6?CCNgLJ4^psjpo74n7tLS{r z{(`ovE9n_^4Lz%Fr5)-%+NmC*=hU}omwJ?Ts~^)I^#r}3o}?GGYqF>6{Sx{}ucE)`SJ@ z-y21A(!fs(qmnVBiYdkfrW#Y2X4Ej#Xkj5^E=x0(vastjC0%FVs3ulWk=XC7e{=23Q*d5oQH z{+;zVzheVJ8apSH!Ojikv-3jT*uYRJ8x$JA&JSJ4hJ=Q(3qqsVg`x56NAzbR_L4Jr z(}(mC&IU$s`U`!Gu{8MEo1 zuw^I}MlU)6Tc$F|=!#SI8D%L;^aJ!YY}v{R{RR34wjAXneFl9CTds0kuchx`%Tq7X z+ta^cYp0IXE&2~^?bVgq4*DLpe07bsiB7`SK|P^O#aTT@9o3WCM8;sVwK1B;6xcdx zlhyB-3R`Dwy}FKRuyxV4st+?AwywIVj$#IE1$wqRjG3@?)2At4;oKjiLcL!3l%>H| zr0-JhWntKg^?k}RmJVBYqoZ;mvta9C6e;Jh4A^>NAAP_wVe5t6^foHTXVe>e=N6U? zTM2g1e3k=SDfUY_%Z05ByQVwKgRPG_pN_D0tUYQNWBIIu^J5D234fr#tIY3wAMr7| zY8&ggmcr0RL*vy@<<$^BX*In6i}7c{p_Iukq4sPT-w~AWWV<_p@>yrr1q@x`(@4oQ zpcf=%o9eMe0@y}?Z6w$(16x(fY~7Nw&Ggt>0@$tq+i0+j1>3lk*$R`g)q8A>0c;b& zb|u&*fo*ciY(+`gq8?jq0NWI>T?MwQ!4^rGtvD&$wI17?0Jdtd)qrg}*lJT|>z$F%b;@jgld?VQvF!|C zdkk!kgY5~htxK7$UsAT`J+?goY`+5AdaykSwv8#XRU~EG>#^+*VA}+?r@^)bY+F-i zJ1Z&M0gvtF0JiO5dj@Pfz_v4GwzHG6z3Q>O9>BH>Y`eksYq0G}m5p@PUrs?>V#uSA zGXV`)4_*8U#H0#4+b1wBCq~XX_+v+4KBkN|`M(X!4+Z99CTf#^FfiW=%*Wi(CjU@i zer8}kCW$uruLb632j-(&x5+;onBOiiAG1Z9{I>%0a|83yzuV-$6PTYLn2(O!CjXCt z`5goE(PP`>zaN<2B`_advrYbof%%;R^U(*}5U_QD)oBWf3`TYX(QEC18iV~F12J$M&2K^UCV@a6+ literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/dialog/ConfigShowEditorButtonsPage.java b/src/cx/fbn/nevernote/dialog/ConfigShowEditorButtonsPage.java new file mode 100644 index 0000000..e234f96 --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/ConfigShowEditorButtonsPage.java @@ -0,0 +1,521 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.dialog; + +import com.trolltech.qt.gui.QComboBox; +import com.trolltech.qt.gui.QGridLayout; +import com.trolltech.qt.gui.QGroupBox; +import com.trolltech.qt.gui.QHBoxLayout; +import com.trolltech.qt.gui.QRadioButton; +import com.trolltech.qt.gui.QWidget; + +public class ConfigShowEditorButtonsPage extends QWidget { + private final QRadioButton showUndo; + private final QRadioButton hideUndo; + private final QRadioButton showRedo; + private final QRadioButton hideRedo; + private final QRadioButton showCut; + private final QRadioButton hideCut; + private final QRadioButton showCopy; + private final QRadioButton hideCopy; + private final QRadioButton showPaste; + private final QRadioButton hidePaste; + private final QRadioButton showBold; + private final QRadioButton hideBold; + private final QRadioButton showItalic; + private final QRadioButton hideItalic; + private final QRadioButton showUnderline; + private final QRadioButton hideUnderline; + private final QRadioButton showStrikethrough; + private final QRadioButton hideStrikethrough; + private final QRadioButton showHline; + private final QRadioButton hideHline; + private final QRadioButton showOutdent; + private final QRadioButton hideOutdent; + private final QRadioButton showIndent; + private final QRadioButton hideIndent; + private final QRadioButton showBulletList; + private final QRadioButton hideBulletList; + private final QRadioButton showNumberList; + private final QRadioButton hideNumberList; + private final QRadioButton showFont; + private final QRadioButton hideFont; + private final QRadioButton showFontSize; + private final QRadioButton hideFontSize; + private final QRadioButton showFontColor; + private final QRadioButton hideFontColor; + private final QRadioButton showFontHighlight; + private final QRadioButton hideFontHighlight; + private final QRadioButton showAlignLeft; + private final QRadioButton hideAlignLeft; + private final QRadioButton showAlignCenter; + private final QRadioButton hideAlignCenter; + private final QRadioButton showAlignRight; + private final QRadioButton hideAlignRight; + + QComboBox messageCombo; + public ConfigShowEditorButtonsPage(QWidget parent) { + super(parent); + + // Undo Button + QGroupBox undoGroup = new QGroupBox(tr("Undo")); + QHBoxLayout undoLayout = new QHBoxLayout(); + showUndo = new QRadioButton(tr("Show")); + hideUndo = new QRadioButton(tr("Hide")); + undoLayout.addWidget(showUndo); + undoLayout.addWidget(hideUndo); + undoLayout.setStretch(1, 100); + undoGroup.setLayout(undoLayout); + + + // Redo Button + QGroupBox redoGroup = new QGroupBox(tr("Redo")); + QHBoxLayout redoLayout = new QHBoxLayout(); + showRedo = new QRadioButton(tr("Show")); + hideRedo = new QRadioButton(tr("Hide")); + redoLayout.addWidget(showRedo); + redoLayout.addWidget(hideRedo); + redoLayout.setStretch(1, 100); + redoGroup.setLayout(redoLayout); + + + // Paste button + QGroupBox pasteGroup = new QGroupBox(tr("Paste")); + QHBoxLayout pasteLayout = new QHBoxLayout(); + showPaste = new QRadioButton(tr("Show")); + hidePaste = new QRadioButton(tr("Hide")); + pasteLayout.addWidget(showPaste); + pasteLayout.addWidget(hidePaste); + pasteLayout.setStretch(1, 100); + pasteGroup.setLayout(pasteLayout); + + // Copy button + QGroupBox copyGroup = new QGroupBox(tr("Copy")); + QHBoxLayout copyLayout = new QHBoxLayout(); + showCopy = new QRadioButton(tr("Show")); + hideCopy = new QRadioButton(tr("Hide")); + copyLayout.addWidget(showCopy); + copyLayout.addWidget(hideCopy); + copyLayout.setStretch(1, 100); + copyGroup.setLayout(copyLayout); + + + // Cut Button + QGroupBox cutGroup = new QGroupBox(tr("Cut")); + QHBoxLayout cutLayout = new QHBoxLayout(); + showCut = new QRadioButton(tr("Show")); + hideCut = new QRadioButton(tr("Hide")); + cutLayout.addWidget(showCut); + cutLayout.addWidget(hideCut); + cutLayout.setStretch(1, 100); + cutGroup.setLayout(cutLayout); + + // Notebook Column + QGroupBox underlineGroup = new QGroupBox(tr("Underline")); + QHBoxLayout underlineLayout = new QHBoxLayout(); + showUnderline = new QRadioButton(tr("Show")); + hideUnderline = new QRadioButton(tr("Hide")); + underlineLayout.addWidget(showUnderline); + underlineLayout.addWidget(hideUnderline); + underlineLayout.setStretch(1, 100); + underlineGroup.setLayout(underlineLayout); + + // Bold Button + QGroupBox boldGroup = new QGroupBox(tr("Bold")); + QHBoxLayout boldLayout = new QHBoxLayout(); + showBold = new QRadioButton(tr("Show")); + hideBold = new QRadioButton(tr("Hide")); + boldLayout.addWidget(showBold); + boldLayout.addWidget(hideBold); + boldLayout.setStretch(1, 100); + boldGroup.setLayout(boldLayout); + + + // Italic Button + QGroupBox italicGroup = new QGroupBox(tr("Italic")); + QHBoxLayout italicLayout = new QHBoxLayout(); + showItalic = new QRadioButton(tr("Show")); + hideItalic = new QRadioButton(tr("Hide")); + italicLayout.addWidget(showItalic); + italicLayout.addWidget(hideItalic); + italicLayout.setStretch(1, 100); + italicGroup.setLayout(italicLayout); + + // Strikethrough Button + QGroupBox strikethroughGroup = new QGroupBox(tr("Strikethrough")); + QHBoxLayout strikethroughLayout = new QHBoxLayout(); + showStrikethrough = new QRadioButton(tr("Show")); + hideStrikethrough = new QRadioButton(tr("Hide")); + strikethroughLayout.addWidget(showStrikethrough); + strikethroughLayout.addWidget(hideStrikethrough); + strikethroughLayout.setStretch(1, 100); + strikethroughGroup.setLayout(strikethroughLayout); + + + // Hline Button + QGroupBox hlineGroup = new QGroupBox(tr("Horizontal Line")); + QHBoxLayout hlineLayout = new QHBoxLayout(); + showHline = new QRadioButton(tr("Show")); + hideHline = new QRadioButton(tr("Hide")); + hlineLayout.addWidget(showHline); + hlineLayout.addWidget(hideHline); + hlineLayout.setStretch(1, 100); + hlineGroup.setLayout(hlineLayout); + + // Outdent Button + QGroupBox outdentGroup = new QGroupBox(tr("Outdent")); + QHBoxLayout outdentLayout = new QHBoxLayout(); + showOutdent = new QRadioButton(tr("Show")); + hideOutdent = new QRadioButton(tr("Hide")); + outdentLayout.addWidget(showOutdent); + outdentLayout.addWidget(hideOutdent); + outdentLayout.setStretch(1, 100); + outdentGroup.setLayout(outdentLayout); + + // Indent Button + QGroupBox indentGroup = new QGroupBox(tr("Indent")); + QHBoxLayout indentLayout = new QHBoxLayout(); + showIndent = new QRadioButton(tr("Show")); + hideIndent = new QRadioButton(tr("Hide")); + indentLayout.addWidget(showIndent); + indentLayout.addWidget(hideIndent); + indentLayout.setStretch(1, 100); + indentGroup.setLayout(indentLayout); + + // Bullet List Button + QGroupBox bulletListGroup = new QGroupBox(tr("Bullet List")); + QHBoxLayout bulletListLayout = new QHBoxLayout(); + showBulletList = new QRadioButton(tr("Show")); + hideBulletList = new QRadioButton(tr("Hide")); + bulletListLayout.addWidget(showBulletList); + bulletListLayout.addWidget(hideBulletList); + bulletListLayout.setStretch(1, 100); + bulletListGroup.setLayout(bulletListLayout); + + // Number List Button + QGroupBox numberListGroup = new QGroupBox(tr("Numbered List")); + QHBoxLayout numberListLayout = new QHBoxLayout(); + showNumberList = new QRadioButton(tr("Show")); + hideNumberList = new QRadioButton(tr("Hide")); + numberListLayout.addWidget(showNumberList); + numberListLayout.addWidget(hideNumberList); + numberListLayout.setStretch(1, 100); + numberListGroup.setLayout(numberListLayout); + + // Font drop down list + QGroupBox fontGroup = new QGroupBox(tr("Fonts")); + QHBoxLayout fontLayout = new QHBoxLayout(); + showFont = new QRadioButton(tr("Show")); + hideFont = new QRadioButton(tr("Hide")); + fontLayout.addWidget(showFont); + fontLayout.addWidget(hideFont); + fontLayout.setStretch(1, 100); + fontGroup.setLayout(fontLayout); + + // Font sizes drop down list + QGroupBox fontSizeGroup = new QGroupBox(tr("Font Size")); + QHBoxLayout fontSizeLayout = new QHBoxLayout(); + showFontSize = new QRadioButton(tr("Show")); + hideFontSize = new QRadioButton(tr("Hide")); + fontSizeLayout.addWidget(showFontSize); + fontSizeLayout.addWidget(hideFontSize); + fontSizeLayout.setStretch(1, 100); + fontSizeGroup.setLayout(fontSizeLayout); + + // Font color button + QGroupBox fontColorGroup = new QGroupBox(tr("Font Color")); + QHBoxLayout fontColorLayout = new QHBoxLayout(); + showFontColor = new QRadioButton(tr("Show")); + hideFontColor = new QRadioButton(tr("Hide")); + fontColorLayout.addWidget(showFontColor); + fontColorLayout.addWidget(hideFontColor); + fontColorLayout.setStretch(1, 100); + fontColorGroup.setLayout(fontColorLayout); + + // highlight button + QGroupBox fontHighlightGroup = new QGroupBox(tr("Text Highlight")); + QHBoxLayout fontHighlightLayout = new QHBoxLayout(); + showFontHighlight = new QRadioButton(tr("Show")); + hideFontHighlight = new QRadioButton(tr("Hide")); + fontHighlightLayout.addWidget(showFontHighlight); + fontHighlightLayout.addWidget(hideFontHighlight); + fontHighlightLayout.setStretch(1, 100); + fontHighlightGroup.setLayout(fontHighlightLayout); + + // Align Left + QGroupBox alignLeftGroup = new QGroupBox(tr("Align Left")); + QHBoxLayout alignLeftLayout = new QHBoxLayout(); + showAlignLeft = new QRadioButton(tr("Show")); + hideAlignLeft = new QRadioButton(tr("Hide")); + alignLeftLayout.addWidget(showAlignLeft); + alignLeftLayout.addWidget(hideAlignLeft); + alignLeftLayout.setStretch(1, 100); + alignLeftGroup.setLayout(alignLeftLayout); + + // Align Center + QGroupBox alignCenterGroup = new QGroupBox(tr("Align Center")); + QHBoxLayout alignCenterLayout = new QHBoxLayout(); + showAlignCenter = new QRadioButton(tr("Show")); + hideAlignCenter = new QRadioButton(tr("Hide")); + alignCenterLayout.addWidget(showAlignCenter); + alignCenterLayout.addWidget(hideAlignCenter); + alignCenterLayout.setStretch(1, 100); + alignCenterGroup.setLayout(alignCenterLayout); + + // Align Right + QGroupBox alignRightGroup = new QGroupBox(tr("Align Right")); + QHBoxLayout alignRightLayout = new QHBoxLayout(); + showAlignRight = new QRadioButton(tr("Show")); + hideAlignRight = new QRadioButton(tr("Hide")); + alignRightLayout.addWidget(showAlignRight); + alignRightLayout.addWidget(hideAlignRight); + alignRightLayout.setStretch(1, 100); + alignRightGroup.setLayout(alignRightLayout); + + QGridLayout mainLayout = new QGridLayout(); + mainLayout.addWidget(undoGroup, 0,0); + mainLayout.addWidget(redoGroup, 0,1); + mainLayout.addWidget(cutGroup, 0,2); + mainLayout.addWidget(copyGroup, 1,0); + mainLayout.addWidget(pasteGroup, 1,1); + mainLayout.addWidget(boldGroup, 1,2); + mainLayout.addWidget(italicGroup, 2,0); + mainLayout.addWidget(underlineGroup, 2,1); + mainLayout.addWidget(strikethroughGroup, 2,2); + mainLayout.addWidget(hlineGroup, 3,0); + mainLayout.addWidget(indentGroup, 3,1); + mainLayout.addWidget(outdentGroup, 3,2); + mainLayout.addWidget(bulletListGroup, 4,0); + mainLayout.addWidget(numberListGroup, 4,1); + mainLayout.addWidget(fontGroup, 5,0); + mainLayout.addWidget(fontSizeGroup, 5,1); + mainLayout.addWidget(fontColorGroup, 5,2); + mainLayout.addWidget(fontHighlightGroup, 4,2); + mainLayout.addWidget(alignLeftGroup, 6,0); + mainLayout.addWidget(alignCenterGroup, 6,1); + mainLayout.addWidget(alignRightGroup, 6,2); + + mainLayout.setColumnStretch(3, 100); + mainLayout.setRowStretch(7, 100); + setLayout(mainLayout); + } + + public void setUndo(boolean value) { + if (value) + showUndo.click(); + else + hideUndo.click(); + } + + public void setRedo(boolean value) { + if (value) + showRedo.click(); + else + hideRedo.click(); + } + + public void setCut(boolean value) { + if (value) + showCut.click(); + else + hideCut.click(); + } + + public void setCopy(boolean value) { + if (value) + showCopy.click(); + else + hideCopy.click(); + } + + public void setPaste(boolean value) { + if (value) + showPaste.click(); + else + hidePaste.click(); + } + public void setUnderline(boolean value) { + if (value) + showUnderline.click(); + else + hideUnderline.click(); + } + public void setBold(boolean value) { + if (value) + showBold.click(); + else + hideBold.click(); + } + public void setItalic(boolean value) { + if (value) + showItalic.click(); + else + hideItalic.click(); + } + public void setStrikethrough(boolean value) { + if (value) + showStrikethrough.click(); + else + hideStrikethrough.click(); + } + public void setHline(boolean value) { + if (value) + showHline.click(); + else + hideHline.click(); + } + public void setIndent(boolean value) { + if (value) + showIndent.click(); + else + hideIndent.click(); + } + public void setOutdent(boolean value) { + if (value) + showOutdent.click(); + else + hideOutdent.click(); + } + public void setBulletList(boolean value) { + if (value) + showBulletList.click(); + else + hideBulletList.click(); + } + public void setNumberList(boolean value) { + if (value) + showNumberList.click(); + else + hideNumberList.click(); + } + public void setFont(boolean value) { + if (value) + showFont.click(); + else + hideFont.click(); + } + public void setFontSize(boolean value) { + if (value) + showFontSize.click(); + else + hideFontSize.click(); + } + public void setFontColor(boolean value) { + if (value) + showFontColor.click(); + else + hideFontColor.click(); + } + public void setFontHighlight(boolean value) { + if (value) + showFontHighlight.click(); + else + hideFontHighlight.click(); + } + public void setAlignLeft(boolean value) { + if (value) + showAlignLeft.click(); + else + hideAlignLeft.click(); + } + public void setAlignCenter(boolean value) { + if (value) + showAlignCenter.click(); + else + hideAlignCenter.click(); + } + public void setAlignRight(boolean value) { + if (value) + showAlignRight.click(); + else + hideAlignRight.click(); + } + + + + public boolean showUndo() { + return showUndo.isChecked(); + } + public boolean showCut() { + return showCut.isChecked(); + } + public boolean showRedo() { + return showRedo.isChecked(); + } + public boolean showCopy() { + return showCopy.isChecked(); + } + public boolean showPaste() { + return showPaste.isChecked(); + } + public boolean showBold() { + return showBold.isChecked(); + } + public boolean showUnderline() { + return showUnderline.isChecked(); + } + public boolean showItalic() { + return showItalic.isChecked(); + } + public boolean showStrikethrough() { + return showStrikethrough.isChecked(); + } + public boolean showHline() { + return showHline.isChecked(); + } + public boolean showIndent() { + return showIndent.isChecked(); + } + public boolean showOutdent() { + return showOutdent.isChecked(); + } + public boolean showNumberList() { + return showNumberList.isChecked(); + } + public boolean showBulletList() { + return showBulletList.isChecked(); + } + public boolean showFont() { + return showFont.isChecked(); + } + public boolean showFontSize() { + return showFontSize.isChecked(); + } + public boolean showFontColor() { + return showFontColor.isChecked(); + } + public boolean showFontHilight() { + return showFontHighlight.isChecked(); + } + public boolean showAlignCenter() { + return showAlignCenter.isChecked(); + } public + boolean showAlignLeft() { + return showAlignLeft.isChecked(); + } + public boolean showAlignRight() { + return showAlignRight.isChecked(); + } + + + + + +} \ No newline at end of file diff --git a/src/cx/fbn/nevernote/dialog/DatabaseLoginDialog.java b/src/cx/fbn/nevernote/dialog/DatabaseLoginDialog.java new file mode 100644 index 0000000..1a6fb8c --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/DatabaseLoginDialog.java @@ -0,0 +1,98 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.dialog; + +import com.trolltech.qt.gui.QDialog; +import com.trolltech.qt.gui.QGridLayout; +import com.trolltech.qt.gui.QLabel; +import com.trolltech.qt.gui.QLineEdit; +import com.trolltech.qt.gui.QPushButton; + +public class DatabaseLoginDialog extends QDialog { + + private boolean okPressed; + private final QLineEdit password; + private final QPushButton ok; + + + // Constructor + public DatabaseLoginDialog() { + okPressed = false; + setWindowTitle("Database Password"); + QGridLayout grid = new QGridLayout(); + setLayout(grid); + QGridLayout passwordGrid = new QGridLayout(); + QGridLayout buttonGrid = new QGridLayout(); + + String passwordValue = ""; + + password = new QLineEdit(passwordValue); + password.setEchoMode(QLineEdit.EchoMode.Password); + + password.textChanged.connect(this, "validateInput()"); + + passwordGrid.addWidget(new QLabel("Password"), 2,1); + passwordGrid.addWidget(password, 2, 2); + passwordGrid.setContentsMargins(10, 10, -10, -10); + grid.addLayout(passwordGrid,1,1); + + ok = new QPushButton("OK"); + ok.clicked.connect(this, "okButtonPressed()"); + QPushButton cancel = new QPushButton("Cancel"); + cancel.clicked.connect(this, "cancelButtonPressed()"); + buttonGrid.addWidget(ok, 1, 1); + buttonGrid.addWidget(cancel, 1,2); + grid.addLayout(buttonGrid,2,1); + } + + // The OK button was pressed + @SuppressWarnings("unused") + private void okButtonPressed() { + okPressed = true; + close(); + } + + // The CANCEL button was pressed + @SuppressWarnings("unused") + private void cancelButtonPressed() { + okPressed = false; + close(); + } + + + // Get the password + public String getPassword() { + return password.text(); + } + + // Check if the OK button was pressed + public boolean okPressed() { + return okPressed; + } + + // Validate user input + public void validateInput() { + ok.setEnabled(true); + if (password.text().trim().equals("")) { + ok.setEnabled(false); + return; + } + } +} diff --git a/src/cx/fbn/nevernote/dialog/DatabaseStatus.class b/src/cx/fbn/nevernote/dialog/DatabaseStatus.class new file mode 100644 index 0000000000000000000000000000000000000000..89c5179004fb8b6e909d713e3a9597836c206ae0 GIT binary patch literal 3277 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 literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/dialog/EnCryptDialog.java b/src/cx/fbn/nevernote/dialog/EnCryptDialog.java new file mode 100644 index 0000000..dbfc433 --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/EnCryptDialog.java @@ -0,0 +1,134 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.dialog; + + +import com.trolltech.qt.gui.QDialog; +import com.trolltech.qt.gui.QGridLayout; +import com.trolltech.qt.gui.QLabel; +import com.trolltech.qt.gui.QLineEdit; +import com.trolltech.qt.gui.QPushButton; + +public class EnCryptDialog extends QDialog { + + private boolean okPressed; + private final QLineEdit password; + private final QLineEdit password2; + private final QLineEdit hint; + private final QPushButton ok; + private final QLabel error; + + + // Constructor + public EnCryptDialog() { + okPressed = false; + setWindowTitle("Encrypt Text"); + QGridLayout grid = new QGridLayout(); + QGridLayout input = new QGridLayout(); + QGridLayout msgGrid = new QGridLayout(); + QGridLayout button = new QGridLayout(); + setLayout(grid); + + + hint = new QLineEdit(""); + password = new QLineEdit(""); + password.setEchoMode(QLineEdit.EchoMode.Password); + password2 = new QLineEdit(""); + password2.setEchoMode(QLineEdit.EchoMode.Password); + + + input.addWidget(new QLabel("Password"), 1,1); + input.addWidget(password, 1, 2); + input.addWidget(new QLabel("Verify"), 2,1); + input.addWidget(password2, 2, 2); + input.addWidget(new QLabel("Hint"), 3,1); + input.addWidget(hint, 3, 2); + input.setContentsMargins(10, 10, -10, -10); + grid.addLayout(input, 1,1); + + error = new QLabel(); + msgGrid.addWidget(error, 1, 1); + grid.addLayout(msgGrid, 2, 1); + + ok = new QPushButton("OK"); + ok.clicked.connect(this, "okButtonPressed()"); + ok.setEnabled(false); + + QPushButton cancel = new QPushButton("Cancel"); + cancel.clicked.connect(this, "cancelButtonPressed()"); + button.addWidget(ok, 1, 1); + button.addWidget(cancel, 1,2); + grid.addLayout(button, 3, 1); + + password.textChanged.connect(this, "validateInput()"); + password2.textChanged.connect(this, "validateInput()"); + hint.textChanged.connect(this, "validateInput()"); + + } + + // The OK button was pressed + @SuppressWarnings("unused") + private void okButtonPressed() { + okPressed = true; + close(); + } + // The CANCEL button was pressed + @SuppressWarnings("unused") + private void cancelButtonPressed() { + okPressed = false; + close(); + } + // Get the the validated password from the field + public String getPasswordVerify() { + return password2.text(); + } + // Get the password + public String getPassword() { + return password.text(); + } + // Get the password hint + public String getHint() { + return hint.text(); + } + // Check if the OK button was pressed + public boolean okPressed() { + return okPressed; + } + // Check if proper input was input + @SuppressWarnings("unused") + private void validateInput() { + ok.setEnabled(false); + error.setText(""); + if (password.text().length()<4) { + error.setText("Password must be at least 4 characters"); + return; + } + if (!password.text().equals(password2.text())) { + error.setText("Passwords do not match"); + return; + } + if (hint.text().trim().equals("")) { + error.setText("Hint must be entered"); + return; + } + + ok.setEnabled(true); + } +} diff --git a/src/cx/fbn/nevernote/dialog/EnDecryptDialog.class b/src/cx/fbn/nevernote/dialog/EnDecryptDialog.class new file mode 100644 index 0000000000000000000000000000000000000000..b90f8aaa68e3af97d02bbfa87b23409049650990 GIT binary patch literal 3339 zcma)8TXPd-7=FGqY0|KT5)iB)R1P*t4*^BR6j3MzDk&6NgT>=!vrU(#yJfQ};0aH7 zKA+FWTgOp{rZYO@l~-Q)54`iIce7cbD7D4ow3b1)3qJX%oHuX?36M?_5ssy&(C@X)H;f=z(&KF$#||)E_O zN>wX!+`l2v=1h;eW~E{l1;iI1F3uz*VFUHjvsQZVopErR0+HhYb1J?h8wVjfgrknBydBriFf`5rDU7HhQ>;A zGEOnvD1bP&A}O8RAe~HW+*lDsufV1zqCsNf=s{A7WHdw(Yr{_590gO<{oiuihKwm^ zgwfTo3%8I9ql;WfHFGIYxhOgymEWdeH*ObL!Kl z)o>^7Vx;wA@uXEOndI8mW{CcUf#Km)K8F3IP~LQ{$@3EDfQBI)6iCpvLC5w?+pCP| zZppGM0@36!|5AB*@vw$r-0dr@r?#oWAho{292FjBF=V?W&QT4=Fe=cY6qc(qHpyms z#uOP&byC?@tdahXX;>*Ud{0vbUapTAPO_Gc9f@Py&-Ez{8rs{qykEluc#zH*Wy_eB zh20=~$H%Oat(S*pEYCCDZT@QKKnxEHtahgTA`Ci1G8IPw#VCwM6l#p5!NjDr!Le=A zV6M8CmfNwyX>JZQDnRMblm-i@1>%xFwq7VpC&I~7GMi-vcTl$tStK^A*iiFj_O_9P zvl`CGFs$&{2?nQFFW@4bkP&1cm&npe=0=iS zviB7YugV@P_hjGYQ$ltpu0~}~kty~2x}dG?SL7m&cko^m@3L5yw`L9R;{yi5JX6)n zOu`l2JD^kQR16;ptgAa%=_)#1d>^}JbX9KcW1enIkLa^OKI3Cf)iun6mdyCtWshgS zw1Dr)F!}2ame~o-N)%rRY`&_AURePQLr_ihw%+~tN-!~e!&?!OZxv?=*_+kKCZ|TW zcQvw()yQVRQFaEtbNpQmgzodDg_B-DBHc2NwdusV8m|2b8z&a9DHn_*!FV(nv*C14 z4V%+HVe3R<`vSV>k>a99E&ArspT30tAF!i_TbFKUxt;a5dzI)OiiX2A+|erq!Vx)B z2m5#ssUKt`>YyXe|Gzr^s$sCFS4th~Q+JQlLHY=iQXu|;G%Vao%)Zu+Vhtn8+yxw; z#|e4$go5qqlX?#EYU4&uond*d zeCP~!MwIrR&Ty;3q)(UNq!X?WlU-bV&qRda@%KG!=Wh~Wq?npCQ`3X>=*4FAp&R|! zfedcpr`mqp%)Y-16I@N=R?OmdTtF5tVgMgt55B@)e9I?o9{cbMZ~ult{Eh?ogU{2S zIEcS-h@Sw%qMdKhbvPonU_|ucsMw8TVvz4i4#&kf#)OV>VIz+!t=cPzB^=D*ELZEr zy*P*SB+h0ribpsLp<5irqnx#1hqx1uaTX@(emqXfMR@*1ooKj&D;j_m>98bO4Hr&c z4#G;sWy!_+`BCzKQm*;e1LYw+(*R2GwGos~r~;vk22cXe;-XJ~#+AK=R>hdaYz@zS z$GM-ER<%F5L_QXnA{g^V^8F3uPdAi*2^#|a`=~8Moo&>gVnw}tIVN#+V6&DT1+vb+ z7#Jbz_%*z)%zvXH+=)hTF5xOo;NA@2B6vEmE~DUq2(4TD&9czUEpaWfn5DNCv-Aw@ zm7(1&>qFKL#}kR|^pO)8D-JT`HN5>1+STEQG60-Suy{%`5-qAkHnFpTG>eg7t4Xcx yq*Xu3pP`|*kr$GxK3jGNc6_X4MTRDP!f6Pf;xmp3&I+Gw$I{yW8ED7NN literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/dialog/EnDecryptDialog.java b/src/cx/fbn/nevernote/dialog/EnDecryptDialog.java new file mode 100644 index 0000000..e1e4402 --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/EnDecryptDialog.java @@ -0,0 +1,149 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.dialog; + + +import com.trolltech.qt.gui.QCheckBox; +import com.trolltech.qt.gui.QDialog; +import com.trolltech.qt.gui.QGridLayout; +import com.trolltech.qt.gui.QLabel; +import com.trolltech.qt.gui.QLineEdit; +import com.trolltech.qt.gui.QPushButton; + +public class EnDecryptDialog extends QDialog { + + private boolean okPressed; + private final QLineEdit password; + private final QLineEdit password2; + private final QLabel hint; + private final QPushButton ok; + private final QLabel error; + private final QCheckBox permanent; + private final QCheckBox remember; + + + // Constructor + public EnDecryptDialog() { + okPressed = false; + setWindowTitle("Decrypt Text"); + QGridLayout grid = new QGridLayout(); + QGridLayout input = new QGridLayout(); + QGridLayout msgGrid = new QGridLayout(); + QGridLayout button = new QGridLayout(); + setLayout(grid); + + + hint = new QLabel(""); + password = new QLineEdit(""); + password.setEchoMode(QLineEdit.EchoMode.Password); + password2 = new QLineEdit(""); + password2.setEchoMode(QLineEdit.EchoMode.Password); + + + input.addWidget(new QLabel("Password"), 1,1); + input.addWidget(password, 1, 2); + input.addWidget(new QLabel("Verify"), 2,1); + input.addWidget(password2, 2, 2); + + permanent = new QCheckBox(); + permanent.setText("Permanently Decrypt"); + input.addWidget(permanent,3,2); + + remember = new QCheckBox(); + remember.setText("Remember For This Session"); + input.addWidget(remember,4,2); + + input.setContentsMargins(10, 10, -10, -10); + grid.addLayout(input, 1,1); + + msgGrid.addWidget(new QLabel("Hint: "), 1,1); + msgGrid.addWidget(hint, 1, 2); + msgGrid.addWidget(new QLabel(""), 1,3); + msgGrid.setColumnStretch(3, 100); + error = new QLabel(); + msgGrid.addWidget(error, 2, 2); + grid.addLayout(msgGrid, 2, 1); + + ok = new QPushButton("OK"); + ok.clicked.connect(this, "okButtonPressed()"); + ok.setEnabled(false); + + QPushButton cancel = new QPushButton("Cancel"); + cancel.clicked.connect(this, "cancelButtonPressed()"); + button.addWidget(ok, 1, 1); + button.addWidget(cancel, 1,2); + grid.addLayout(button, 3, 1); + + password.textChanged.connect(this, "validateInput()"); + password2.textChanged.connect(this, "validateInput()"); + + } + public boolean permanentlyDecrypt() { + return permanent.isChecked(); + } + // The OK button was pressed + @SuppressWarnings("unused") + private void okButtonPressed() { + okPressed = true; + close(); + } + // The CANCEL button was pressed + @SuppressWarnings("unused") + private void cancelButtonPressed() { + okPressed = false; + close(); + } + // Get the the validated password from the field + public String getPasswordVerify() { + return password2.text(); + } + // Get the password + public String getPassword() { + return password.text(); + } + // Get the password hint + public void setHint(String h) { + hint.setText(h.replace("'", "'")); + } + // Set the error message + public void setError(String e) { + error.setText(e); + } + // Check if the OK button was pressed + public boolean okPressed() { + return okPressed; + } + // Check if we should remember the password + public boolean rememberPassword() { + return remember.isChecked(); + } + // Check if proper input was input + @SuppressWarnings("unused") + private void validateInput() { + ok.setEnabled(false); + error.setText(""); + if (!password.text().equals(password2.text())) { + error.setText("Passwords do not match"); + return; + } + + ok.setEnabled(true); + } +} diff --git a/src/cx/fbn/nevernote/dialog/FindDialog.class b/src/cx/fbn/nevernote/dialog/FindDialog.class new file mode 100644 index 0000000000000000000000000000000000000000..68690c48bf4e8721d4fa765ae0cd237270346f7c GIT binary patch literal 3587 zcmb7H*>@A?75{ycUw&IA$y5zoBr32e)^7t33=d8}l4qm*2B^^2V)a|@=iIObfYq;lSImvy%! zpcZvwF(5Y>dexjY?W*NjmrQ{!XOT&Ca64VAE{xSY&#`GPcEGYN?~p)uDqUb4Ij3YM z(2b;qThXK9cAm+k6A;*}VGFhj+*&ogIi5Mor!B8ScXy=n7xYVdwxZkR?5yWnc6l^i zP;e(RYM=UJu2stGSDc!cKrfQg`aK%%#eD*CS`SzP+fyBK2n2j5+Xe1z@1#-R1hyd= zr;C0KQN$G7-%+Je=md5KDrpT0RH;0mAs$de8WI7O)o=?`1-k|A>JWooG%G3|WEoEr z3<*4deX_J$W#0QWJd8(}vR*39S*5Z`u=I6GIS?3~m`E3-?x=@8Vj+d;uu4pBRZwi$21(rgg}yalyhv)w7u%2?v^dP zN&~40{z(_&tldcsc}()ms946LNwlWd-{j1!RkroYu_ep%Ot(LH+dZn{l)%Oi=D9#W zl}=y=vkD#;*tM?G?G0%-jc>>h9NRVxmUh=_n4T(L;NfUH;HsDt*wpB*W&{f6JL0+3 zQ!37~|4yAu;0f%LxOqy0h7EDPo>ZaJu(KF+-?VF1t7a*cR$&N4a}}p*s$e_aZb)*C zkU)>b^HgoAXu7BMqU^h5-ZAt_L3b_r9v()#1&g=Qpa0)8Ob(thJF)YuX!R*&RXNV& z38#f~kp(|XzLm&4AN zA64*zKxQ4-Iw~l5i7@}#@(EnUD{>TkMI9|jL zHN1+~1h&XLWZPDcx=xKt%Q0$8Y*)^)|HG4v@eK_>!jE}3EVmp_Z6clVj@h*C>Yn2= zIvK}X8s3(1Xflq*Fp-RRHM}Pow@HQ^L(M5vxk4bE53XwP>jzmSGB?b6oL7_j#jpny zUb-B&>?Pj$y4@rf!cXKb_*mc;ik=EPl3mjdBK}TqbvXScW}TXAnB$i0!XBAPu=0nc zD<(a`iR0!fI{Uk-;8z0ot%Jo^XBNj)IQ|rT)^5tI0RwR@y-J`G0S&T>?QE)Ue#pd- zl&g+ZQtmJR$?fGoxx4%)H<$n9bmCKvDsFuKZUnj}0&QVtR56ma`tYB{>QpZDsnd|6_L`e+{ z%7c+mZfeMvJJgUHqTH}A7ch>H5tRlcBNLSd0>&5_u?Ax>)?z$LhSFf96rZs%!M|T@ z{GyKWfgx#bL|VI!6Pe^x9n+)+{g(n?!oWr%OzMgGfgZ$(g#tvjL z#7~EZu^TylrA}cl3fKn|55d8HT*4#xHb(F|M)5ws3$EcHKF1;a1&8rh9Kqjl6#u{& z{zdJ7bE9`*T=d|$*ve(T6DPzToD>I<7st7?XE7z75Mx zNSG98p+c&Qp8ts@Qr)yS37b@e)>4dY17XyKiw#&YBbt)`S}Di;gM#l$3z(s+E@vz*s+|CH^1cKj>F*b;}l>e1wm~9QN=jtEn=+zB)dUUIXk0 zK)AB125R#fe~M2-{cNZorT)3K%FnM-jy7-MXTFP{;}?A1$rNYsOZ*y}xQnjgH%EH8 K;;!Mhh<^#xK4y~u literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/dialog/FindDialog.java b/src/cx/fbn/nevernote/dialog/FindDialog.java new file mode 100644 index 0000000..0ed52f7 --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/FindDialog.java @@ -0,0 +1,132 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.dialog; + + +import com.trolltech.qt.gui.QCheckBox; +import com.trolltech.qt.gui.QDialog; +import com.trolltech.qt.gui.QGridLayout; +import com.trolltech.qt.gui.QLabel; +import com.trolltech.qt.gui.QLineEdit; +import com.trolltech.qt.gui.QPushButton; +import com.trolltech.qt.webkit.QWebPage; + +public class FindDialog extends QDialog { + + private final QLineEdit text; + private final QCheckBox wrap; + private final QCheckBox forward; + private final QCheckBox backward; + private final QCheckBox caseSensitive; + private final QPushButton ok; + + // Constructor + public FindDialog() { + setWindowTitle("Find"); + QGridLayout grid = new QGridLayout(); + setLayout(grid); + + text = new QLineEdit(); + wrap = new QCheckBox(); + forward = new QCheckBox(); + backward = new QCheckBox(); + caseSensitive = new QCheckBox(); + + QGridLayout textGrid = new QGridLayout(); + textGrid.addWidget(new QLabel("Text"), 1,1); + textGrid.addWidget(text, 1, 2); + grid.addLayout(textGrid, 1, 1); + + QGridLayout opt = new QGridLayout(); + opt.addWidget(new QLabel("Case Sensitive"), 1,1); + opt.addWidget(caseSensitive, 1, 2); + opt.addWidget(new QLabel("Forward"), 2,1); + opt.addWidget(forward, 2, 2); + opt.addWidget(new QLabel("Backward"), 3,1); + opt.addWidget(backward, 3, 2); + opt.addWidget(new QLabel("Wrap"), 4,1); + opt.addWidget(wrap, 4, 2); + opt.setContentsMargins(10, 10, -10, -10); + grid.addLayout(opt,2,1); + + forward.clicked.connect(this, "forwardClicked()"); + backward.clicked.connect(this, "backwardClicked()"); + + QGridLayout buttonLayout = new QGridLayout(); + ok = new QPushButton("OK"); + ok.clicked.connect(this, "okButtonPressed()"); + QPushButton cancel = new QPushButton("Close"); + cancel.clicked.connect(this, "closeButtonPressed()"); + buttonLayout.addWidget(ok, 1, 1); + buttonLayout.addWidget(cancel, 1,2); + grid.addLayout(buttonLayout,3,1); + } + + + //set focus on show + public void setFocusOnTextField() { + text.setFocus(); + } + + // The OK button was pressed + @SuppressWarnings("unused") + private void okButtonPressed() { +// close(); + } + // The CANCEL button was pressed + @SuppressWarnings("unused") + private void closeButtonPressed() { + close(); + } + // Check if the OK button was pressed + public void okPressed() { + return; + } + // The forward checkbox was clicked + @SuppressWarnings("unused") + private void forwardClicked() { + backward.setChecked(false); + } + // The backward checkbox was clicked + @SuppressWarnings("unused") + private void backwardClicked() { + forward.setChecked(false); + } + // Return search flags + public QWebPage.FindFlags getFlags() { + QWebPage.FindFlags flags = new QWebPage.FindFlags(); + + if (wrap.isChecked()) + flags.set(QWebPage.FindFlag.FindWrapsAroundDocument); + if (backward.isChecked()) + flags.set(QWebPage.FindFlag.FindBackward); + if (caseSensitive.isChecked()) + flags.set(QWebPage.FindFlag.FindCaseSensitively); + + return flags; + } + // Return search text + public String getText() { + return text.text(); + } + public QPushButton getOkButton() { + return ok; + } +} diff --git a/src/cx/fbn/nevernote/dialog/InsertLinkDialog.class b/src/cx/fbn/nevernote/dialog/InsertLinkDialog.class new file mode 100644 index 0000000000000000000000000000000000000000..f88d3b73065f1022810a099d8c12c18b1ae3edf9 GIT binary patch literal 2351 zcma)7TXPd-7=FHF)1>J_OF+v>N)ON^Z3#y?l!H>*5=jfC&{`CAvsuz@w!5(TQozG_ z>AiPec_|6UdrR z3J=O|!L`;b-}R(bsMv<%RSQM8ZuzogyR~b?+6?&wbr6-YqDa?aeh1~*OVG@T`7HK}crQ>b%3hb;~a?y4x-s3yA zbSyq(ODo2jQE&{mT9}uLtRK|z4h|6oS`VKD z`m=443IzfuhXoF`cCv|33IhU2qYpzW&0dw}Q5{L7lE?}iXrpbEEhmLMvAXL!X$)gX z#X6?r7zzy2s8km1O4X7AgYCi$1;&fT+=9|Qp_4eL1Tsuh^tfLd@P9ERW@jk9H7}K%M znj&KE%?ixT+f~!b!U3JxpjvAI3uR=>;$7>j+;o@Nuol|Ol)N^2dY@Zew9~tWi4AR*%%;z%;l=_W%#PA`1?{WSEN1)*-2gWeEkwq_Z zq(Gjh5sY#)p2u-q#|hl#sQUz`VBrjWPP4CZ7T@soTU@~R7{`yeh+l9CO%<7eC`;+$W-a_<^?WGm2sAe#%{(c243mBCqk**uCS1uP7&8=Ha}|qZ~mp7!;dah=OQhHPhdO z{~f`KSfZec2bIncS5@y6E3uzd7$D}VLLpp(k(;$ZUJTH~V{T)3f~Q>7gqgzU_!7JR E1@r$P?*IS* literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/dialog/InsertLinkDialog.java b/src/cx/fbn/nevernote/dialog/InsertLinkDialog.java new file mode 100644 index 0000000..d1ca887 --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/InsertLinkDialog.java @@ -0,0 +1,103 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.dialog; + + +import com.trolltech.qt.core.Qt; +import com.trolltech.qt.gui.QDialog; +import com.trolltech.qt.gui.QGridLayout; +import com.trolltech.qt.gui.QLabel; +import com.trolltech.qt.gui.QLineEdit; +import com.trolltech.qt.gui.QPushButton; + +public class InsertLinkDialog extends QDialog { + + private boolean okPressed; + private final QLineEdit url; + private final QPushButton ok; + private String urlText; + + + // Constructor + public InsertLinkDialog() { + okPressed = false; + setWindowTitle("Insert Link"); + QGridLayout grid = new QGridLayout(); + QGridLayout input = new QGridLayout(); + QGridLayout button = new QGridLayout(); + setLayout(grid); + + + url = new QLineEdit(""); + + input.addWidget(new QLabel("Url"), 1,1); + input.addWidget(url, 1, 2); + input.setContentsMargins(10, 10, -10, -10); + grid.addLayout(input, 1,1); + + ok = new QPushButton("OK"); + ok.clicked.connect(this, "accept()"); + ok.setEnabled(false); + + QPushButton cancel = new QPushButton("Cancel"); + cancel.clicked.connect(this, "reject()"); + button.addWidget(ok, 1, 1); + button.addWidget(cancel, 1,2); + grid.addLayout(button, 3, 1); + url.textChanged.connect(this, "validateInput()"); + + setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose); + } + + // Get the password + public String getUrl() { + return urlText; + } + // Set the url + public void setUrl(String u) { + url.setText(u); + } + // Check if the OK button was pressed + public boolean okPressed() { + return okPressed; + } + // Check that we have a valid URL + @SuppressWarnings("unused") + private void validateInput() { + ok.setEnabled(true); + if (url.text().trim().equals("")) + ok.setEnabled(false); + } + + @Override + public void accept() { + if (ok.isEnabled()) { + okPressed = true; + urlText = url.text(); + super.accept(); + } + } + + @Override + public void reject() { + okPressed=false; + super.reject(); + } +} diff --git a/src/cx/fbn/nevernote/dialog/LoginDialog.class b/src/cx/fbn/nevernote/dialog/LoginDialog.class new file mode 100644 index 0000000000000000000000000000000000000000..ea04a52f5144e0a85bc40d4e19f43f59a8e60bdb GIT binary patch literal 2933 zcmaJ@S#T3&9RGc3uBHo=073yddPtHU;YJ$n(n2LI#g>*}0N} zCr`OI1nRBnp}bZoXjuUS=~+vgfFUv!WApe+dgYrpt**~ zP_Zy|q-figNul6A-PG*^0(G(YsDQu6%4!kRp;3W?CG`-9DhMDL#!7)@gEG89hPTOy zE5hSP6s*P?fu#k_9@EXNb!9}i4NYKGEPX+}tR@ZB%q55Iyl&=F@zD_0GMMVI9Al(u z^_o?*BWOaS)c&Y~4cN%MP`i61usK#EF!utD)MGPRLTDCPU4hFn!? znX(3mf`XmcMHh$WQH|G%+vC8zXiECBN5SLRE6~8ym30bq)J$H55}C&sQVRBAKh@aU zRl8@3U`lRQaplyoo-p4Lz&cTEBU*Xvg9a97azFN2+C` zx*i2b(JK(jSf;6EYzi)>*U8BX+)PzMC<%8=U|o%ztCN}$MnB8ov{Pph^r2mnFRfqz zgXEo>&5r5WoJNZ+wNmF^NcH!}N5j}D#ZM`C62l}FbKhf`wr1Le0X5H7P+$zPe*VQr z<;BwqMlt5vDf7Fg9gp8qHiYq-WwcP=VLZiNaPmY1XV5OWcuqkC4fR|;t3Z{ohBAhp znbxvlWCWI5({5w%dQdDL21_H@qna6+s2r<0If5wfu-WDeFI)wlb-dhZK466;2bnY_5{^i?Ehb3KW1?N-{KH{VDJ6~NANqP{$yAF z8@>1keZq%h&}s3w3k5D&i)f>dyYUk)aTcK7 zHu~N`_2nih82`O#+D+4yBNj9Y3R)ovm8fWymZP*#sP+(BTPb*KHcPwhcDE!OE^qO^ z@fPnB4`kGVFxVN#@sr~?_`6t#!-LoX49r2LB?q(`@Zi!&+|UV@A*CZ^WWcn z58yg{r63@%Qs1B4owAd*vDe7hj%y^-re-;#$v&=Ajx(_-qmP+;4Fy4gCAu@2bTf`+ zxrRQL+~X!kb7pe;W=}&PB;|X|tSfLuPi0a0cGygh8g3iqor#W|>pFII`CD_@v4RZc zRb8`n!z$|3I}@FjsZSVb0Wl&_x6ZUpcY{DvtY=)?t0i-;X(i>2ZRPus_>e&TfH`Vw zZZ2a8jF+pd^8%PjijmeB`GF~8CNFIp%B`M{ig$6a(@7g))F7fl#f1VjvG`Cu1Qw|X zqd~z%0?Ym@e_<>}L@HgPq84>>yF|rOTqdwEYq$eW#x?EHEw+}jWP*Y*UR{r6xI)2l zf$J-q-;~O_8BKS)U1M^{H1;(O7?z>CrepWgWffPVNnl=Y&T`F}Hv%nHihXWtZPMix zDpn#Uut2(8dY8c3*#9#dA5xI0n!s5=g%K|#@M;wbLLnpt0{yqh<7-v+#~J~JUJV-i ziRVQ=J}k{1O%AvjrnXJyGmaZnwBSa{PGyX2R;D_Bw%^-5s99SkP1iLtO@-YxZ6T}` zXmD&F#<6%9ZCI~ho$SlZtHON_h<*4oEt_LBJ$^E6}O;=t)->Yg*F#hUagKk55$M0 zW}k|F+{(MD$^06wJ|;oi9UlteHi7w_mXkG>6-g-@Ch!MU+z$3}z|9D(C=I(kP_aW+cOI)dY}#pO-=OJQWVoGGLmes!bwq|bg1c1Qje82A7P4@TPzwS?jMPl2 z&}TxO(sW`;y2bX|?HQz71^EVyVO)VpSLgDXiV0Yx4brHDW_P?KP`~6-*H+PVPvsa#XjsOFzI8THc5(YjFr0S zmne)qI4D_gja=QQ;(keB4Kr+Dq$Nu{sNx|!Ok)Ix^nyKB4ODa8WyWP94ykw)j}cE< z^B_GT-FAoY1k>6-W!STzBFuVB+vv+pri{#>Bu;@ykE3hWkd`s!-aibwVTEB{IhpdNYEdUV$=Vk; z)eOucoCX9TC%Tz0(@XY>vk9#NG^n?DZn8Ko{e-P43;BFTrN9LPuBK1)YE!WKatR6fQBZ-G%fes?;Q=R?(Ty%s7QeB`H-1T0 z%Qj?wyUDegPD>--XBB+rcf_0zqq%I&3j3U|;7gKK2l;pXZ&<#{$0mnVR*0*p)big^8MzXiQ9F@s3lt_#~o< z6Nm=$xKuvB#pQWi#g}ouTy+x7JZz4v&f^-nIDzXEk(=^pofT;3d3&UzAkgj!Y^K08 zx@cfqYcLv=X7lJSp43Kbd0B6?RvP5Fw`k`gk%(;1V<3;=X^c>LS8H9gPC9mHw2r?T zH?`a(qIG$sm%fR<47?$eqH0)=)H5lgGW% znP@1F2Od?#B4yQSJRo?4I5Kr>=2v+cS zC3i7qJ&r~sumr1kdNr=aYP2GWtz6y4kByyJL!P>U9N2<`xCw`_7Ee*)C4LaRg?0FZ zWBxcc;v_a<8Xfo%o%jh`@C!%hZ?y6Uw&4uevbb5)qf1%yMiOD>* allBooks, List archive) { + okClicked = false; + openBookList = new QListWidget(); + openBookList.setSortingEnabled(true); + openBookList.setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection); + + okButton = new QPushButton(); + okButton.setText("OK"); + okButton.pressed.connect(this, "onClicked()"); + + cancelButton = new QPushButton(); + cancelButton.setText("Cancel"); + cancelButton.pressed.connect(this, "onCancel()"); + + QVBoxLayout openLayout = new QVBoxLayout(); + openLayout.addWidget(new QLabel("Open Notebooks")); + openLayout.addWidget(openBookList); + + rightButton = new QPushButton(this); + rightButton.setIcon(new QIcon(iconPath+"forward.png")); + leftButton = new QPushButton(this); + leftButton.setIcon(new QIcon(iconPath+"back.png")); + leftButton.setEnabled(false); + rightButton.setEnabled(false); + + QVBoxLayout middleLayout = new QVBoxLayout(); + middleLayout.addSpacerItem(new QSpacerItem(1,1)); + middleLayout.addWidget(rightButton); + middleLayout.addWidget(leftButton); + middleLayout.addSpacerItem(new QSpacerItem(1,1)); + + QVBoxLayout closeLayout = new QVBoxLayout(); + closeLayout.addWidget(new QLabel("Closed Notebooks")); + closedBookList = new QListWidget(); + closedBookList.setSortingEnabled(true); + closedBookList.setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection); + closeLayout.addWidget(closedBookList); + + openBookList.itemSelectionChanged.connect(this, "openBookSelected()"); + closedBookList.itemSelectionChanged.connect(this, "closedBookSelected()"); + leftButton.clicked.connect(this, "toOpenList()"); + rightButton.clicked.connect(this, "toClosedList()"); + + QHBoxLayout buttonLayout = new QHBoxLayout(); + buttonLayout.addStretch(1); + buttonLayout.addWidget(okButton); + buttonLayout.addWidget(cancelButton); + setWindowTitle(tr("Open/Close Notebooks")); + + QHBoxLayout upperLayout = new QHBoxLayout(); + upperLayout.addLayout(openLayout); + upperLayout.addLayout(middleLayout); + upperLayout.addLayout(closeLayout); + + QVBoxLayout mainLayout = new QVBoxLayout(); + mainLayout.addLayout(upperLayout); + //mainLayout.addStretch(1); + mainLayout.addSpacing(1); + mainLayout.addLayout(buttonLayout); + setLayout(mainLayout); + + for (int i=0; i items = openBookList.selectedItems(); + for (int i=items.size()-1; i>=0; i--) { + int row = openBookList.row(items.get(i)); + openBookList.takeItem(row); + closedBookList.addItem(items.get(i).text()); + } + if (openBookList.count() == 0) + okButton.setEnabled(false); + rightButton.setEnabled(false); + } + + + @SuppressWarnings("unused") + private void toOpenList() { + List items = closedBookList.selectedItems(); + for (int i=items.size()-1; i>=0; i--) { + int row = closedBookList.row(items.get(i)); + closedBookList.takeItem(row); + openBookList.addItem(items.get(i).text()); + } + okButton.setEnabled(true); + leftButton.setEnabled(false); + } + + @SuppressWarnings("unused") + private void closedBookSelected() { + if (closedBookList.selectedItems().size() > 0) + leftButton.setEnabled(true); + else + leftButton.setEnabled(false); + } + + @SuppressWarnings("unused") + private void openBookSelected() { + if (openBookList.selectedItems().size() > 0) + rightButton.setEnabled(true); + else + rightButton.setEnabled(false); + } + + @SuppressWarnings("unused") + private void onClicked() { + okClicked = true; + close(); + } + + @SuppressWarnings("unused") + private void onCancel() { + okClicked = false; + close(); + } + + public boolean okClicked() { + return okClicked; + } + + public QListWidget getOpenBookList() { + return openBookList; + } + + public QListWidget getClosedBookList() { + return closedBookList; + } + + @SuppressWarnings("unused") + private void itemSelected() { + if (openBookList.selectedItems().size() == openBookList.count()) { + okButton.setEnabled(false); + rightButton.setEnabled(false); + return; + } + rightButton.setEnabled(true); + okButton.setEnabled(true); + } +} diff --git a/src/cx/fbn/nevernote/dialog/NotebookEdit.class b/src/cx/fbn/nevernote/dialog/NotebookEdit.class new file mode 100644 index 0000000000000000000000000000000000000000..7f0c42d901b418dd531d1009a7af05e2cd34f8d2 GIT binary patch literal 3690 zcma)9TW}j^75-M1C0X7ij#}s1+*-GmWIJk-HZ8GhH&N1}M0T9mb(-`-SJFn_Sl&&f zmFx5Zl-_7dX-h9qF1-Q;TA+nknUWa>W|(0HW|-lPN8aF(r#>;jcm7@3vLZ3H#@hdK z&iTJ{&Ueng`qO`Y^IHIWu@pu?LtlO|bv9?GY;(aZ+m36d3YJlFim3^XbB;52q+q#W z1T|cjcji-W*(sG=Ge4WU;HHXID|O%uSZfO2sT_(9URxh%qssVQ03rYSyw% zF+Z%KyX54J(n)ikO6?WWvu1wokh4gIfEd2Mjp4~^W%f|jbsd|MJ^5<6Y}#(!p$eC> z=Zpm-RduaWDr;2)K-ZL2v<Nyty2s;Za%$jaatjj%w(L zCuTGR(@w#Rq657;)+5#h4I6cIA{4=94f?@CVP_ptlzUrsT!(EM)>cgSlw}v3ho>#K zL@>Q^4^7Fii>WEMY}v)(#7r1F7^c=?y}N7`vc^TH>PE30y<+`(9XFtlUeda^rD0dR zP4qkgb;wN`wzoc{p1UY+M6WoP&=E!?i~;)6M#adPr3i*Jtf_mxbHbQskdjDAkhTfl zJvzC$k5G+5;gnSUTSF*(Cjv^&Vnbgq@y^GV6I;Jqq zu4|V2yxE@N2*~I4&YV|LewD`)QQV6&VVu^`e^tU;ThehK z?iUP>ZJT)}w!e|w$8+bnINXZv;?RRSzEls+5!=X>%t8bP>n?5Bc_CJw#gbR!CZJv9 zsHx+u_}}d^*6CRmlc>*_qIu*R%)< z1HsCwm!XDhmA3_yrTS$jrKyY#-*1%^H>{sh--{rkH7~qJk&nep1I% z0ExE8pEzPz~J;6pGGSUT{`go=GD*B z#}hMBH{aB;25Whd*%~&iPCxs;qCf=S(ts#l!y93|&O4>qeI4J%cSuk3Le(e{YqXZ#>hOA749+cQovf+WS9uQxtFGJss~$62p>n z)p1|Lk97PP9}u^PFH^LgvY9r7Hmi` zZk+c^Bs%3(%X#xIONwZHoi%dd?-o~?#SGg(IbAaN)=&xK*S<5W-Z54;61w0wCG29F zI`|^fiGbXy9L3}UQct#B^FUKn9&+!arn!(nn9nvX?QjgyY;jehDX% zv3qJbB@^mApadSGz=7cApxVuOyYWjXBx6NRhD25&8`>OHxCVwog5?tx1&iP3u!Y}o z1d-rHm1KMdun~iN57~`Ar1-fRqu9eMX)mU+kG=a=_R#%sa2p=R?RbKB=yMpx8!XoM zaR)x6bPZ$pJ?_L`a1ejPA^aU_`~!!17I2FfXUw6**+%>o^RStPKKy|;ZRY7YcKGug zbI6-lY+*{nA})FiB2x07s3Ht`yoN_U<~RU}a7eAsH0VcsC>kEeHedfBr2~}i z5`D7m%PT%b)y93K_5I4o22ap8LKS=kUscCHfd$`OBb>1szV=ZQoQGP%c^a7(aK^UQ z@JurtlW@+qf%B~LnK#ffoRoscI;D3Tnz76^VCh^A&DWPhGwO#XBvrVj8OV7abD;r9 zXgMw+Qpt4X?flol{l1pK$Qv9~ currentNotebooks; + + // Constructor + public NotebookEdit() { + okPressed = false; + setWindowTitle("Add Notebook"); + QGridLayout grid = new QGridLayout(); + setLayout(grid); + + QGridLayout textLayout = new QGridLayout(); + notebook = new QLineEdit(); + textLayout.addWidget(new QLabel("Notebook Name"), 1,1); + textLayout.addWidget(notebook, 1, 2); + textLayout.setContentsMargins(10, 10,-10, -10); + grid.addLayout(textLayout,1,1); + + localRemote = new QCheckBox(); + localRemote.setText("Local Notebook"); + localRemote.setChecked(false); + grid.addWidget(localRemote, 2,1); + + QGridLayout buttonLayout = new QGridLayout(); + ok = new QPushButton("OK"); + ok.clicked.connect(this, "okButtonPressed()"); + ok.setEnabled(false); + QPushButton cancel = new QPushButton("Cancel"); + cancel.clicked.connect(this, "cancelButtonPressed()"); + notebook.textChanged.connect(this, "textChanged()"); + buttonLayout.addWidget(ok, 1, 1); + buttonLayout.addWidget(cancel, 1,2); + grid.addLayout(buttonLayout,3,1); + } + + // The OK button was pressed + @SuppressWarnings("unused") + private void okButtonPressed() { + okPressed = true; + close(); + } + + // The CANCEL button was pressed + @SuppressWarnings("unused") + private void cancelButtonPressed() { + okPressed = false; + close(); + } + + // Get the userid from the field + public String getNotebook() { + return notebook.text(); + } + + // Set the notebook name + public void setNotebook(String name) { + notebook.setText(name); + } + + // Is this a local notebook? + public boolean isLocal() { + return localRemote.isChecked(); + } + + // Hide the local/remote checkbox + public void setLocalCheckboxEnabled(boolean visible) { + localRemote.setEnabled(visible); + } + + + // Check if the OK button was pressed + public boolean okPressed() { + return okPressed; + } + + // Set the window title + public void setTitle(String s) { + setWindowTitle(s); + } + + // set notebooks + public void setNotebooks(List n) { + currentNotebooks = n; + } + + // Watch what text is being entered + @SuppressWarnings("unused") + private void textChanged() { + if (notebook.text().equals("")) { + ok.setEnabled(false); + return; + } + if (notebook.text().equalsIgnoreCase("All Notebooks")) { + ok.setEnabled(false); + return; + } + if (currentNotebooks == null) { + ok.setEnabled(false); + return; + } + for (int i=0; i versions) { + String fmt = Global.getDateFormat() + " " + Global.getTimeFormat(); + String dateTimeFormat = new String(fmt); + SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat); + + for (int i=0; i or encoded characters are ugly + js.append(""); + js.append(""); + js.append(""); + js.append(b.toString()); + js.append(""); +// js.replace("", ""); +// js.replace("", ""); + + browser.setNote(currentNote); + browser.getBrowser().page().mainFrame().setHtml(js.toString()); + } + + //************************************************* + //* XML Modifying Methods + //************************************************* + private StringBuffer rebuildNoteHTML(Note note) { + QDomDocument doc = new QDomDocument(); + QDomDocument.Result result = doc.setContent(note.getContent()); + if (!result.success) { + return new StringBuffer(note.getContent()); + } + + doc = modifyTags(note, doc); + QDomElement docElem = doc.documentElement(); + docElem.setTagName("Body"); + + // Fix the stupid problem where inserting an tag after an tag (which is done + // to get the application tag to work properly) causes spaces to be inserted + // between the & . This messes things up later. This is an ugly hack. + String docString = doc.toString(); + StringBuffer html = new StringBuffer(docString.substring(docString.toLowerCase().indexOf(""))); + + for (int i=html.indexOf("-1; i=html.indexOf("\n",i+1); + int z = html.indexOf("i; j--) + html.deleteCharAt(j); + i=html.indexOf("/>", z+1); + z = html.indexOf("",i); + for (int j=z-1; j>i+1; j--) + html.deleteCharAt(j); + } + return html; + } + + + + private QDomDocument modifyTags(Note note, QDomDocument doc) { + 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(note, docElem, enmedia, hash); + } + if (!type[0].equals("image")) { + modifyApplicationTags(note, doc, docElem, enmedia, hash, appl); + } +// if (type[0].equals("audio")) { +// 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("style","display:none"); + enmedia.setAttribute("contentEditable","false"); + enmedia.setAttribute("src", Global.getDirectoryPath()+"images/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 + enmedia.setAttribute("onClick", "window.jambi.decryptText('crypt"+Global.cryptCounter.toString()+"', '"+encryptedText+"', '"+enmedia.attribute("hint")+"');"); + enmedia.setAttribute("onMouseOver", "style.cursor='hand'"); + enmedia.setTagName("img"); + enmedia.removeChild(enmedia.firstChild()); // Remove the actual encrypted text + } + + return doc; + } + + + + + private void modifyApplicationTags(Note n, QDomDocument doc, QDomElement docElem, QDomElement enmedia, QDomAttr hash, String appl) { + + Resource r = null; + for (int i=0; i -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(); + if (fileDetails != null && !fileDetails.equals("")) + enmedia.setAttribute("href", "nnres://" +r.getGuid()+n.getUpdateSequenceNum() +Global.attachmentNameDelimeter +fileDetails); + else + enmedia.setAttribute("href", "nnres://" +r.getGuid()+n.getUpdateSequenceNum() +Global.attachmentNameDelimeter +appl); + 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"); + String icon = findIcon(appl); + if (icon.equals("attachment.png")) + icon = findIcon(fileDetails.substring(fileDetails.indexOf(".")+1)); + newText.setAttribute("src", Global.getDirectoryPath()+"images"+File.separator +icon); + newText.setAttribute("title", fileDetails); + enmedia.removeChild(enmedia.firstChild()); + enmedia.appendChild(newText); + } + } + } + // find the appropriate icon for an attachment + private String findIcon(String appl) { + appl = appl.toLowerCase(); + File f = new File(Global.getDirectoryPath()+"images"+File.separator +appl +".png"); + if (f.exists()) + return appl+".png"; + return "attachment.png"; + } + + + + + + + + private void modifyTodoTags(QDomElement todo) { + 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"); + } + + + private void modifyImageTags(Note note, QDomElement docElem, QDomElement enmedia, QDomAttr hash) { + String type = enmedia.attribute("type"); + if (type.startsWith("image/")) + type = "."+type.substring(6); + else + type=""; + + Resource r = null; + for (int i=0; i 0) { + tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly)); + QByteArray binData = new QByteArray(r.getData().getBody()); + tfile.write(binData); + tfile.close(); + enmedia.setAttribute("src", tfile.fileName()); + enmedia.setAttribute("en-tag", "en-media"); + enmedia.setNodeValue(""); + enmedia.setAttribute("guid", r.getGuid()); + enmedia.setTagName("img"); + } + } + enmedia.setAttribute("src", tfile.fileName()); + enmedia.setAttribute("en-tag", "en-media"); + enmedia.setNodeValue(""); + enmedia.setAttribute("guid", r.getGuid()); + enmedia.setTagName("img"); + } +} diff --git a/src/cx/fbn/nevernote/dialog/PreviewDialog.java b/src/cx/fbn/nevernote/dialog/PreviewDialog.java new file mode 100644 index 0000000..3b7d302 --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/PreviewDialog.java @@ -0,0 +1,82 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.dialog; + +import com.trolltech.qt.gui.QDialog; +import com.trolltech.qt.gui.QHBoxLayout; +import com.trolltech.qt.gui.QImage; +import com.trolltech.qt.gui.QPixmap; +import com.trolltech.qt.gui.QPushButton; +import com.trolltech.qt.gui.QScrollArea; +import com.trolltech.qt.gui.QVBoxLayout; +import com.trolltech.qt.gui.QWidget; + +import cx.fbn.nevernote.Global; +public class PreviewDialog extends QDialog { + + + public PreviewDialog(QWidget parent) { + + QWidget masterLabel = new QWidget(); + + QVBoxLayout subLayout = new QVBoxLayout(); + setMouseTracking(true); + + PreviewImage imageLabel = new PreviewImage(masterLabel); + imageLabel.ID = "Number 1"; + QImage image = new QImage(Global.currentDir+"res/thumbnail.png"); + imageLabel.setPixmap(QPixmap.fromImage(image).scaled(400, 400)); + subLayout.addWidget(imageLabel); + + PreviewImage imageLabel2 = new PreviewImage(masterLabel); + imageLabel2.ID = "Number 2"; + QImage image2 = new QImage(Global.currentDir+"res/thumbnail.png"); + imageLabel2.setPixmap(QPixmap.fromImage(image2).scaled(400,400)); + subLayout.addWidget(imageLabel2); + masterLabel.setLayout(subLayout); + + QScrollArea scrollArea = new QScrollArea(); + scrollArea.setWidget(masterLabel); + + QPushButton okButton = new QPushButton(tr("OK")); + okButton.clicked.connect(this, "okPushed()"); + ; + + QVBoxLayout verticalLayout = new QVBoxLayout(); + verticalLayout.addWidget(scrollArea); + + QHBoxLayout buttonLayout = new QHBoxLayout(); + buttonLayout.addStretch(1); + buttonLayout.addWidget(okButton); + setWindowTitle(tr("Note Preview")); + + QVBoxLayout mainLayout = new QVBoxLayout(); + mainLayout.addLayout(verticalLayout); + mainLayout.addSpacing(1); + mainLayout.addLayout(buttonLayout); + setLayout(mainLayout); + + } + public void okPushed() { + + close(); + } + +} diff --git a/src/cx/fbn/nevernote/dialog/PreviewImage.java b/src/cx/fbn/nevernote/dialog/PreviewImage.java new file mode 100644 index 0000000..17c73ec --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/PreviewImage.java @@ -0,0 +1,32 @@ +package cx.fbn.nevernote.dialog; + +import com.trolltech.qt.core.QEvent; +import com.trolltech.qt.gui.QLabel; +import com.trolltech.qt.gui.QMouseEvent; +import com.trolltech.qt.gui.QWidget; + +public class PreviewImage extends QLabel { + + public String ID; + + public PreviewImage(QWidget parent) { + super(parent); + setMouseTracking(true); + } + + @Override + public void enterEvent(QEvent arg__1) { + System.out.println("Entering "+ID); + } + + @Override + public void leaveEvent(QEvent arg__1) { + System.out.println("Leaving "+ID); + } + + @Override + public void mousePressEvent(QMouseEvent arg__1) { + System.out.println("Selection of " +ID); + } + +} diff --git a/src/cx/fbn/nevernote/dialog/SavedSearchEdit.class b/src/cx/fbn/nevernote/dialog/SavedSearchEdit.class new file mode 100644 index 0000000000000000000000000000000000000000..d918bf79620b6f1d2a18580416d323b1801a869f GIT binary patch literal 3595 zcma)9TW}lI8UBv$mNz%ygeDGPz^x_Ou>gk@A~zv%9AaW8F%C{+0%a|22TjKCdD-{_xx?(x?x(r8%|JW03#_kN!3o1BZAvXEh+lbQ$u% zx7|uHH=e|;3|QlMJ?PuzVRO-|1!>%ZHmUt~19#v~I!f(&i)+~?@zVmz$QK1}ZER#I zDQR?~O*)q~kVGnpyg+-CBj%*#q|n3I$b_enL$8d@b_w$?19#&dA~eh86Lz^`1p;?A zL#PFcLqoZ7X?mxD7NkkVb0@rw)a}*@VLOb6${xMds!CUk=pE}5mWIE%fZ_9bO z7z?IsrkJt(e8k1xjaAq)%^796qbQq}sFv!)m{dfwG)-tH33W|oWD`ysn1MqQD>+`3 z;K>uDz?&Mxh3Q}eXjW{?=5CC>?7BGvK0IQVc+vk!#1Pgt}bC#F-l{3Zw{WRMT&Y2g0G4p0bPE9sRUh6T0E zxRM|5U%UD_iB`A#iv|p=<0V4jT%vsi@mB_Zjf>1x)jq4Mh`l3h{`0wREHFzmBj%Z~7t&*1 z%`aI8ZP_htYi{gb=_c=@A$Gn$;F!FZt4UlExb6RN2TLa8A>7Wwj`D3Gj)=V6ILgR- zKs`yye99cOswXo>>Gd2(uz_oI9Gm!^0mLPqj&tXq`K!1oAH9Oj`OM9AY`unCPF}@r z!};zyI>O0F{u(;D`lT!A>bZv8$xQcE?1;tcDD>nnqbnBYXj!ID%iK$u_>xRtT*~xp zO!M>E#?R{ba(9nZPz+5R;qkpEGyAS$;0g{<>4D2Qn9n>^$FQ74>v&iRj8kBDY->#I zepT;wUB*N{^O&CWU7zfb2NlR2TVo1hx586=Qw8K}{GP@(erFNm)!2eOgVc?i(Sz;i zWy2TvxeI%EPafjS*%N>#_GYP5kWA)87U6C=WI zP^ef9b)2cA`d3aPkU>tUtw$QFSYW7CJu*-cet;HPP^`VhWw+95V}ix~s8X^;3x+Q7 z2%f^z3c)iC5%o1j^ms!==NcmFYlLW$h)PWmJsTp5GoRYQfU zjtM+>9m}3DItkg9Ti1qWhG}wE07+aAO#;t{K+fX=b!aa5hGYOHR!5vVuiyo#Gph2X z!|hS$nI<}4QoQm_p3v2mz)Nf$zIE}vVu@ecIg3)_6`4<+fXuh*c;$5%vM*&rzsbQ1 z@2#GPxw=6#+W!W6rF{Ea_+A9>;_SyI4LY_q2^h-YvR&*CuiaEfu9#(BN~TtJm;=h>() z)9WXwr9=A}#{3Ye;5Ya!qj8E2E~6j8? currentSearches; + + + // Constructor + public SavedSearchEdit() { + okPressed = false; + setWindowTitle("Add a search"); + QGridLayout grid = new QGridLayout(); + setLayout(grid); + + QGridLayout textLayout = new QGridLayout(); + searchName = new QLineEdit(); + textLayout.addWidget(new QLabel("Name"), 1,1); + textLayout.addWidget(searchName, 1, 2); + query = new QLineEdit(); + textLayout.addWidget(new QLabel("String"), 2,1); + textLayout.addWidget(query, 2, 2); + textLayout.setContentsMargins(10, 10,-10, -10); + grid.addLayout(textLayout, 1, 1); + + QGridLayout buttonLayout = new QGridLayout(); + ok = new QPushButton("OK"); + ok.clicked.connect(this, "okButtonPressed()"); + ok.setEnabled(false); + QPushButton cancel = new QPushButton("Cancel"); + cancel.clicked.connect(this, "cancelButtonPressed()"); + searchName.textChanged.connect(this, "textChanged()"); + query.textChanged.connect(this, "textChanged()"); + buttonLayout.addWidget(ok, 1, 1); + buttonLayout.addWidget(cancel, 1,2); + grid.addLayout(buttonLayout,2,1); + } + + // The OK button was pressed + @SuppressWarnings("unused") + private void okButtonPressed() { + okPressed = true; + close(); + } + + // The CANCEL button was pressed + @SuppressWarnings("unused") + private void cancelButtonPressed() { + okPressed = false; + close(); + } + + // Get the name from the field + public String getName() { + return searchName.text().trim(); + } + + // Set the tag name + public void setName(String name) { + searchName.setText(name); + } + // get the query + public String getQuery() { + return query.text().trim(); + } + // Set the query + public void setQuery(String q) { + query.setText(q); + } + // Check if the OK button was pressed + public boolean okPressed() { + return okPressed; + } + + // Set the window title + public void setTitle(String s) { + setWindowTitle(s); + } + // List of existing tags + public void setSearchList(List t) { + currentSearches = t; + } + // Watch what text is being entered + @SuppressWarnings("unused") + private void textChanged() { + if (searchName.text().trim().equals("")) { + ok.setEnabled(false); + return; + } + if (currentSearches == null) { + ok.setEnabled(false); + return; + } + if (query.text().trim().equals("")) { + ok.setEnabled(false); + return; + } +/* for (int i=0; i 100) + width.setText("80"); + widthValidator.setTop(100); + } else { + widthValidator.setTop(32767); + } + } + + public int getRows() { + return new Integer(rows.text()); + } + public int getCols() { + return new Integer(cols.text()); + } + public int getWidth() { + return new Integer(width.text()); + } + public boolean isPercent() { + if (unit.currentText().equalsIgnoreCase("percent")) + return true; + else + return false; + } + +} diff --git a/src/cx/fbn/nevernote/dialog/TagAssign.java b/src/cx/fbn/nevernote/dialog/TagAssign.java new file mode 100644 index 0000000..b939f7f --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/TagAssign.java @@ -0,0 +1,160 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.dialog; + +import java.util.ArrayList; +import java.util.List; + +import com.evernote.edam.type.Tag; +import com.trolltech.qt.gui.QAbstractItemView; +import com.trolltech.qt.gui.QDialog; +import com.trolltech.qt.gui.QHBoxLayout; +import com.trolltech.qt.gui.QLineEdit; +import com.trolltech.qt.gui.QListWidget; +import com.trolltech.qt.gui.QListWidgetItem; +import com.trolltech.qt.gui.QPushButton; +import com.trolltech.qt.gui.QVBoxLayout; + +public class TagAssign extends QDialog { + private final QListWidget tagList; + private final QPushButton okButton; + private final QPushButton cancelButton; + private final QLineEdit newTag; + private final QPushButton newTagButton; + private boolean okClicked; + private final List tags; + + public TagAssign(List allTags, List selectedTags) { + okClicked = false; + tags = new ArrayList(); + + tagList = new QListWidget(); + tagList.setSortingEnabled(true); + tagList.setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection); + + newTag = new QLineEdit(); + newTag.textChanged.connect(this, "newTagTextChanged()"); + newTagButton = new QPushButton("Add"); + newTagButton.setEnabled(false); + newTagButton.clicked.connect(this, "addTag()"); + + QHBoxLayout addLayout = new QHBoxLayout(); + addLayout.addWidget(newTag); + addLayout.setStretch(0, 10); + addLayout.addWidget(newTagButton); + + okButton = new QPushButton(); + okButton.setText("OK"); + okButton.pressed.connect(this, "onClicked()"); + + cancelButton = new QPushButton(); + cancelButton.setText("Cancel"); + cancelButton.pressed.connect(this, "onCancel()"); + + QHBoxLayout horizontalLayout = new QHBoxLayout(); + horizontalLayout.addWidget(tagList); + + QHBoxLayout buttonLayout = new QHBoxLayout(); + buttonLayout.addStretch(1); + buttonLayout.addWidget(okButton); + buttonLayout.addWidget(cancelButton); + setWindowTitle(tr("Note Tags")); + + QVBoxLayout mainLayout = new QVBoxLayout(); + mainLayout.addLayout(horizontalLayout); + mainLayout.addLayout(addLayout); + //mainLayout.addStretch(1); + mainLayout.addSpacing(1); + mainLayout.addLayout(buttonLayout); + setLayout(mainLayout); + + if (allTags != null) { + for (int i=0; ivI!T6#v~cuciwv0a~Cag;tuRv=QVXv=pHfD5N}WDYmGvO_p@qbhjiMo}#GW z3m^CvQIt7W1J`vt%{ z+zh}Yup)UTeqz{&8`>!?YnYZ6Pw8sLOvn4xbazU(0`LkfPnzR#D{E#lmX;iepS0rX zydFQa)7BKIG{+8RwOme135X$q3QJ83G$hJfC3HiRp4$aH=9s{$IrI+Zb0a(QmSq~$ ztV-syS% zy_3fN4&BhLP9l#)2L!xbW=ad80t*#Xqoxu9ixv3b528*WusxM(pk;{5OBF0by}G-9EQt64z+!2qHH^>di0!&)YY7J(pxZrHDm zlbQ%xB{lUDYFxpSSWA>@Ds@Cpr8P^SaW0gOLVHh7bU@lZrC>ca2!t77muXncaIRO) zrgei^4n%tR=O}Jc@H93%hfGm1=OHc?(l!95cMis93M`1NEXD)-LfC> z%x%Ibt4rBk^jaf2Q@k?qi1EYhdDHBSxyQsz-%vLw(a05sJ8aJmNANp=5nf3) zWSeOUPJjc;m&}+s0_G6l5L;M=3$n%XW*Z1BibNkKT((t4!8k?=uj2jz*_;l z$#FS*d@Fbx?~r$UbS#ea6f^5u2k@@IGTAQW$9M==@VF1n!V6O_DZ+_3~v()5RuR7sYa;VSDXOr44 zUDmq76v?}-O$JD@hy9xE%BZ{>a{+uKuiMg_bauxRy*oWP`bi0IYA-zU?%`8d&T4)` z4k!DYnWNS`K6@~qt1NKT@N)qmMrh^Z&hN212*)ZWu_zX*} zZ|puAx%$K;ReS5EZs~mwN5pK4*9JZ5)n;pQF$!b^Y?p)}>y*Jh7$K zM{(mVJH8=)4xyHx&EzD)XrqiahB~zHCTT?z+7Rcflh@H6tVKV6;~eGnlEel~U?VPI z6E5=>xr)uW&bjzK+VL|wa1UGY8?BDg^LmFdJdYPB)!_%ch-2il2{&+@Pab+Z29@s$ z`dNoz=0WBsImJ4Cd8iLm#k`X70#Zk2;Lo=c+Qmb5(y-e;QYMh^Q+C=`%Hl&+~Q%zC;Tr zk$#+KC-T<>?@PB6@i!&e$%e~*_(B1%T!TW#WU0n9yS6nIJ zy currentTags; + + + // Constructor + public TagEdit() { + okPressed = false; + setWindowTitle("Add Tag"); + QGridLayout grid = new QGridLayout(); + setLayout(grid); + + QGridLayout textGrid = new QGridLayout(); + tag = new QLineEdit(); + textGrid.addWidget(new QLabel("Tag Name"), 1,1); + textGrid.addWidget(tag, 1, 2); + textGrid.setContentsMargins(10, 10,-10, -10); + grid.addLayout(textGrid,1,1); + + QGridLayout buttonGrid = new QGridLayout(); + ok = new QPushButton("OK"); + ok.clicked.connect(this, "okButtonPressed()"); + ok.setEnabled(false); + QPushButton cancel = new QPushButton("Cancel"); + cancel.clicked.connect(this, "cancelButtonPressed()"); + tag.textChanged.connect(this, "textChanged()"); + buttonGrid.addWidget(ok, 3, 1); + buttonGrid.addWidget(cancel, 3,2); + grid.addLayout(buttonGrid,2,1); + } + + // The OK button was pressed + @SuppressWarnings("unused") + private void okButtonPressed() { + okPressed = true; + close(); + } + + // The CANCEL button was pressed + @SuppressWarnings("unused") + private void cancelButtonPressed() { + okPressed = false; + close(); + } + + // Get the name from the field + public String getTag() { + return tag.text(); + } + + // Set the tag name + public void setTag(String name) { + tag.setText(name); + } + + // Check if the OK button was pressed + public boolean okPressed() { + return okPressed; + } + + // Set the window title + public void setTitle(String s) { + setWindowTitle(s); + } + // List of existing tags + public void setTagList(List t) { + currentTags = t; + } + // Watch what text is being entered + @SuppressWarnings("unused") + private void textChanged() { + if (tag.text().equals("")) { + ok.setEnabled(false); + return; + } + if (currentTags == null) { + ok.setEnabled(false); + return; + } + for (int i=0; i guids; + + + public ThumbnailViewer() { + this.setVisible(false); + + leftArrow = new Signal0(); + rightArrow = new Signal0(); + upArrow = new Signal0(); + downArrow = new Signal0(); + + + setAutoFillBackground(true); + QPalette palette = new QPalette(palette()); + // Set background colour to black + palette.setColor(ColorRole.Base, QColor.black); + setPalette(palette); + + grid = new QGridLayout(); + setLayout(grid); + + + picture = new QLabel(); +/* + QLabel left = new QLabel(); + QLabel right = new QLabel(); + + grid.addWidget(left, 0,0); + grid.addWidget(picture,0,1); + grid.addWidget(right, 0,2); + grid.setWidgetSpacing(1); + grid.setContentsMargins(10, 10, -10, -10); +*/ + + setWindowModality(WindowModality.ApplicationModal); + setWindowFlags(Qt.WindowType.FramelessWindowHint); + setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground); +// setBackgroundRole(ColorRole.Shadow); +// setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose); +// showFullScreen(); +// this.hide(); + + } + public void setThumbnail(String thumb) { + thumbnail = thumb; + image = new QImage(thumbnail); + picture.setPixmap(QPixmap.fromImage(image)); + } + public void setThumbnail(QImage i) { + image = i; + picture.setPixmap(QPixmap.fromImage(image)); + } + + + @Override + public void keyPressEvent(QKeyEvent e) { + if (e.key() == Qt.Key.Key_Up.value() || e.key() == Qt.Key.Key_Right.value()) { + upArrow.emit(); + } + if (e.key() == Qt.Key.Key_Down.value() || e.key() == Qt.Key.Key_Left.value()) { + downArrow.emit(); + } + + super.keyPressEvent(e); + } + + + @Override + public void mousePressEvent(QMouseEvent e) { + if (e.button() == Qt.MouseButton.LeftButton) + close(); + } + + @Override + public void wheelEvent(QWheelEvent e) { + int numDegrees = e.delta() / 8; + int numSteps = numDegrees / 15; + + if (e.orientation().equals(Qt.Orientation.Vertical)) { + if (numSteps > 0) { + for (int i=0; i getGuids() { + return guids; + } + public void setGuids(List g) { + guids = g; + } + + +} diff --git a/src/cx/fbn/nevernote/dialog/WatchFolder.java b/src/cx/fbn/nevernote/dialog/WatchFolder.java new file mode 100644 index 0000000..3bec89b --- /dev/null +++ b/src/cx/fbn/nevernote/dialog/WatchFolder.java @@ -0,0 +1,260 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.dialog; + +import java.util.ArrayList; +import java.util.List; + +import com.evernote.edam.type.Notebook; +import com.trolltech.qt.core.QModelIndex; +import com.trolltech.qt.gui.QApplication; +import com.trolltech.qt.gui.QDialog; +import com.trolltech.qt.gui.QFontMetrics; +import com.trolltech.qt.gui.QHBoxLayout; +import com.trolltech.qt.gui.QPushButton; +import com.trolltech.qt.gui.QTableWidget; +import com.trolltech.qt.gui.QTableWidgetItem; +import com.trolltech.qt.gui.QVBoxLayout; +import com.trolltech.qt.gui.QAbstractItemView.SelectionBehavior; +import com.trolltech.qt.gui.QAbstractItemView.SelectionMode; + +import cx.fbn.nevernote.sql.runners.WatchFolderRecord; + +public class WatchFolder extends QDialog { + private final QPushButton okButton; + private final QPushButton cancelButton; + private final QPushButton addButton; + private final QPushButton editButton; + private final QPushButton deleteButton; + private boolean okClicked; + public final QTableWidget table; + private final List notebooks; + private final List records; + + public WatchFolder(List w, List n) { + okClicked = false; + notebooks = n; + records = w; + + okButton = new QPushButton(); + okButton.setText("OK"); + okButton.pressed.connect(this, "onClicked()"); + + cancelButton = new QPushButton(); + cancelButton.setText("Cancel"); + cancelButton.pressed.connect(this, "onCancel()"); + + QHBoxLayout horizontalLayout = new QHBoxLayout(); + QHBoxLayout buttonLayout = new QHBoxLayout(); + buttonLayout.addStretch(1); + buttonLayout.addWidget(okButton); + buttonLayout.addWidget(cancelButton); + setWindowTitle(tr("Auto Import Folders")); + + table = new QTableWidget(records.size(),3); + List headers = new ArrayList(); + headers.add("Directory"); + headers.add("Target Notebook"); + headers.add("Keep"); + table.setHorizontalHeaderLabels(headers); + table.verticalHeader().setVisible(false); + table.setAlternatingRowColors(true); + table.setSelectionBehavior(SelectionBehavior.SelectRows); + table.setSelectionMode(SelectionMode.SingleSelection); + table.itemSelectionChanged.connect(this, "tableSelection()"); + horizontalLayout.addWidget(table); + + + addButton = new QPushButton(); + addButton.setText("Add"); + addButton.clicked.connect(this, "addPressed()"); + + editButton = new QPushButton(); + editButton.setText("Edit"); + editButton.setEnabled(false); + editButton.clicked.connect(this, "editPressed()"); + + deleteButton = new QPushButton(); + deleteButton.setText("Delete"); + deleteButton.setEnabled(false); + deleteButton.clicked.connect(this, "deletePressed()"); + + QVBoxLayout editLayout = new QVBoxLayout(); + editLayout.addWidget(addButton); + editLayout.addWidget(editButton); + editLayout.addWidget(deleteButton); + + QHBoxLayout listLayout = new QHBoxLayout(); + listLayout.addLayout(horizontalLayout); + listLayout.addLayout(editLayout); + + QVBoxLayout mainLayout = new QVBoxLayout(); + mainLayout.addLayout(listLayout); + mainLayout.addSpacing(1); + mainLayout.addLayout(buttonLayout); + setLayout(mainLayout); + +// QTableWidgetItem dir = new QTableWidgetItem(); +// QTableWidgetItem book = new QTableWidgetItem(); + + table.setColumnWidth(0, 160); + resize(500, 200); + load(); + + } + + @SuppressWarnings("unused") + private void onClicked() { + okClicked = true; + close(); + } + + @SuppressWarnings("unused") + private void onCancel() { + okClicked = false; + close(); + } + + public boolean okClicked() { + return okClicked; + } + + @SuppressWarnings("unused") + private void itemSelected() { + okButton.setEnabled(true); + } + + private void load() { + for (int i=0; i notebooks; + private final WatchFolderRecord record; + public final QLabel directory; + public final QComboBox keep; + public final QComboBox books; + + public WatchFolderAdd(WatchFolderRecord w, List n) { + okClicked = false; + notebooks = n; + record = w; + + okButton = new QPushButton(); + okButton.setText("OK"); + okButton.pressed.connect(this, "onClicked()"); + + cancelButton = new QPushButton(); + cancelButton.setText("Cancel"); + cancelButton.pressed.connect(this, "onCancel()"); + + QPushButton folderButton = new QPushButton(); + folderButton.setText("Directory"); + folderButton.clicked.connect(this, "folderButtonClicked()"); + + directory = new QLabel(); + if (record != null) + directory.setText(record.folder); + else + directory.setText(System.getProperty("user.home")); + + keep = new QComboBox(); + keep.addItem("Keep"); + keep.addItem("Delete"); + if (record != null) { + if (record.keep) + keep.setCurrentIndex(0); + else + keep.setCurrentIndex(1); + } + + books = new QComboBox(); + for (int i=0; im4^!U@`=`W9M`rJF4g-w>W=VWHy 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 literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/evernote/EnCrypt.java b/src/cx/fbn/nevernote/evernote/EnCrypt.java new file mode 100644 index 0000000..5769d4f --- /dev/null +++ b/src/cx/fbn/nevernote/evernote/EnCrypt.java @@ -0,0 +1,167 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ +package cx.fbn.nevernote.evernote; + +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.zip.CRC32; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.RC2ParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import cx.fbn.nevernote.utilities.Base64; + +public class EnCrypt { + + // Convert a string of text to a hex string + public static String asHex (byte buf[]) { + StringBuffer strbuf = new StringBuffer(buf.length * 2); + int i; + + for (i = 0; i < buf.length; i++) { + if ((buf[i] & 0xff) < 0x10) + strbuf.append("0"); + + strbuf.append(Long.toString(buf[i] & 0xff, 16)); + } + + return strbuf.toString(); + } + // Encrypte the text and return the base64 string + public String encrypt(String text, String passphrase, int keylen) { + RC2ParameterSpec parm = new RC2ParameterSpec(keylen); + MessageDigest md; + try { + int len = text.length()+4; + int mod = (len%8); + if (mod>0) { + for (; mod !=0; len++) { + mod = len%8; + } + len--; + } + len = len-4; + StringBuffer textBuffer = new StringBuffer(text); + textBuffer.setLength(len); + // Get a MD5 for the passphrase + md = MessageDigest.getInstance("MD5"); + md.update(passphrase.getBytes()); + + // Setup parms for the cipher + SecretKeySpec skeySpec = new SecretKeySpec(md.digest(), "RC2"); + Cipher cipher = Cipher.getInstance("RC2/ECB/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, skeySpec, parm); + String encoded = crcHeader(textBuffer.toString()) +textBuffer; + byte[] d = cipher.doFinal(encoded.getBytes()); + return Base64.encodeBytes(d); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (InvalidAlgorithmParameterException e) { + e.printStackTrace(); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } + + return null; + } + // Decrypt the base64 text and return the unsecure text + public String decrypt(String text, String passphrase, int keylen) { + RC2ParameterSpec parm = new RC2ParameterSpec(keylen); + MessageDigest md; + try { + // Get a MD5 for the passphrase + md = MessageDigest.getInstance("MD5"); + StringBuffer p = new StringBuffer(passphrase); + md.update(p.toString().getBytes()); + + // Setup parms for the cipher + SecretKeySpec skeySpec = new SecretKeySpec(md.digest(), "RC2"); + Cipher cipher = Cipher.getInstance("RC2/ECB/NOPADDING"); + cipher.init(Cipher.DECRYPT_MODE, skeySpec, parm); + + // Decode the encrypted text and decrypt + byte[] dString = Base64.decode(text); + byte[] d = cipher.doFinal(dString); + + // We have a result. Separate it into the 4 byte header and the decrypted text + StringBuffer buffer = new StringBuffer(new String(d)); + String cryptCRC = buffer.substring(0,4); + String clearText = buffer.substring(4); + String realCRC = crcHeader(clearText); + // We need to get the real CRC of the decrypted text + if (realCRC.equalsIgnoreCase(cryptCRC)) { + int endPos = clearText.length(); + for (int i=buffer.length()-1; i>=0; i--) { + if (buffer.charAt(i) == 0) + endPos--; + else + i=-1; + } + clearText = clearText.substring(0,endPos); + return clearText; + } + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (InvalidAlgorithmParameterException e) { + e.printStackTrace(); + } catch (IllegalBlockSizeException e) { + e.printStackTrace(); + } catch (BadPaddingException e) { + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } + // Utility function to return the CRC header of an encoded string. This is + // used to verify good decryption and put in front of a new encrypted string + private String crcHeader(String text) { + CRC32 crc = new CRC32(); + crc.update(text.getBytes()); + int realCRC = (int)crc.getValue(); + + // The first 4 chars of the hex string will equal the first + // 4 chars of the decyphered text. If they match we have a + // good password. This is what we return + realCRC = realCRC ^ (-1); + realCRC = realCRC >>> 0; + String hexCRC = Integer.toHexString(realCRC).substring(0,4); + return hexCRC.toString().toUpperCase(); + + } + +} diff --git a/src/cx/fbn/nevernote/evernote/EnmlConverter.class b/src/cx/fbn/nevernote/evernote/EnmlConverter.class new file mode 100644 index 0000000000000000000000000000000000000000..32dbc69988aa4cb49aa67cdcc341c9336466539e GIT binary patch literal 5221 zcmbtXdvqLS75{yk-Rxw$*fJ%RSPIin+9XZ0EyV(xM`@D)DVruVA#Hfc?CvBPx;wL- zolR4L@)Q9Dq?Mv5_~fCY7Nr}cfW;RAO4X`}D1wi3U$U4ac%wBQmq-wbH3>+aldHoFM!H z3$D~B^+-y$#v=pqD~*IJP@A&H#|=lIEjC9|&NWk}YZ}?ehD;`9CUn=dt(eE(E>Pzf zSv%(>j4TDmJjwDvBxYt^xjkf#Te_Qb41r}8+Z}~>Pmv+lF|G0TE*`1vFfG&V5?Isp z-jrz`5%720Nh5?B%nxH876{ZdHILLmKn){++8|C4Sa?*+4UVJllB$NV5c4J92g3+L z5ttt{En{;o9XFg|J)WZaYRpdPsS({V<$ICncPC6*-aJ>+>H(mAA|((WH{2~p9j7)m zSNMi}%jXc^#$mxkA-n=-HO+PDTuSk-*?yNEJ2i}DI88vIZrv$8OS2Z1RPcB`V!MJB z0;lv^%qB)m>)E&^XIX~RR#alxmI)U^Ggb!CBGCF?@+pi~tYXZVjRK3B`l{$Y5=4Yi zI-0_T%-NVTQ%S>7utp%XnE=p+jVU)8LL1h~OgKZJzKV02MDp)w>ldy8a{W`S&i$v zLLEzc2D*nw2Yb1>O4c`RXmn_}w_j_VaNSHaA|2RPLL5^u9m(Y45rdi7mUNSiU7--6 zeQ_9<;8F%=%$yo>a~U(atv@#C*hF)h$-ewu1)b6E#N}ap1XnQAvV@9FC|InaT~*H? zGt|pi2XZO5y$*3CgGdN8z1uTk7+{2h*<6D4mnMjd6-)@M-r%}MI^#-wy0+#R8QpX= z)0)&%W>TZkTx;%xp(Tsy7Q~eTjdPGHvvONHCE>KilM#Z6`SOtt!;-EHWOOHMD98w$ zIw+T#;W)OV?VKkth<4kl zT-ws4l(mYR6;ffGG zi93S0y&UJevW#pPcj8m*b;guQXZd-_h=M%?S|Li>PCcs?b7Cx)3gXkUS0F*2Rtq7PeAfoOu_rjGZ%J728?vIl2&e0xicDQbMVBO2SEwGu3@M z8!)_EVYM-mgb{YQt%?7GGoYuQ?%n3oF_UaI2rtk^UTb)X=QS5k>l5enUe$sznv|EowwkN-$@y9 z%J@CaC}nIl=PLMvz-c9pnc1ist8`S9H*??^v}Nr!c?n;bs6*aBeXi+Eon`ZTn=DYQ zTYYlm^5!u)ch?qL2$r(R)$psp2UQNc-ipI4sde5u1V7jF5a#nZQZ6F5kH7UT)A&Hk z$^$sQ-??i`QC56|9+?k(LLH)Q}54X z(=;~sx2gkqT)3{*BiGmFF-&SS;7Q#|sSN>&mFK1GXrM*Dk46KliBzksVBkktywRzmA-b~Zw%Po8D75=Fom4I&cfuw{xz$8(p{$>+t|KV4CN8fajZ<|Kjo>I>lS! zOoW0EL3DfnJLQUh@gPjDfPWFx0-T!plt?^Ms4KorvjbVH<{1x(nw1hpv$q23;}yXR ztgIxcPmt28J}I&1e+U~|)u-$I{wwl0)YZB~{tg!~IE^2+)-1{6M|u2IeL^lE58jLzy6i zO~NsaL4Imn0-GtE;d2LpYTdF_pl0J6BoU^o3 Z{$rJSosRe6&#V_BL_l{tw55aNYm_ literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/evernote/EnmlConverter.java b/src/cx/fbn/nevernote/evernote/EnmlConverter.java new file mode 100644 index 0000000..29b4ef7 --- /dev/null +++ b/src/cx/fbn/nevernote/evernote/EnmlConverter.java @@ -0,0 +1,281 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ +package cx.fbn.nevernote.evernote; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import cx.fbn.nevernote.Global; +import cx.fbn.nevernote.utilities.ApplicationLogger; +import cx.fbn.nevernote.xml.XMLCleanup; +import cx.fbn.nevernote.xml.XMLNoteRepair; + +public class EnmlConverter { + private final ApplicationLogger logger; + private List resources; + public boolean saveInvalidXML; + + public EnmlConverter(ApplicationLogger l) { + logger = l; +// conn = c; + saveInvalidXML = false; + resources = new ArrayList(); + } + + public List getResources() { + return resources; + } + public String convert(String noteGuid, String content) { + logger.log(logger.HIGH, "Entering DBRunner.convertToEnml"); + logger.log(logger.EXTREME, "Note Text:" +content); + + // Replace the en-note tags with body tags in case we came from + // someplace other than the editor (for example, if we are merging notes). + content = content.replace("", ""); + content = content.replace("", ""); + // Start removing stuff we don't need or want + int br = content.lastIndexOf(""); + if (br > 0) + content = new String(content.substring(0,br)); + String newContent; + int k = content.indexOf("-1) + newContent = new String(content.substring(k)); + else + newContent = ""+content; + + + // Check that we have a vaild header. Normally we should not + // but sometimes it seems that we can. I don't see how, but it is + // easy enough to check. + if (!newContent.startsWith("\n" + +"\n" + +newContent + +""; + + + // Fix the more common XML problems that Webkit creates, but are not considered + // valid XML. + newContent = fixStupidXMLProblems(newContent); + + + // Change the contents to have enml instead of body tags or + // we'll fail validation later. + newContent = newContent.replace("", ""); + + // First pass through the data. The goal of this pass is to + // validate that we have a good XML document and to repair + // any problems found. + + XMLNoteRepair repair = new XMLNoteRepair(); + logger.log(logger.HIGH, "Checking XML Structure"); + newContent = repair.parse(newContent, false); + logger.log(logger.HIGH, "Check complete"); + + + // If the repair above returned null, then the XML is foobar. + // We are done here. + if (newContent == null) { + // Houston, we've had a problem. + logger.log(logger.LOW, "Parse error when converting to ENML"); + logger.log(logger.LOW, "Start of unmodified note HTML"); + logger.log(logger.LOW, content); + logger.log(logger.LOW, "End of unmodified note HTML"); + logger.log(logger.LOW, "Start of modified note HTML"); + logger.log(logger.LOW, newContent); + logger.log(logger.LOW, "End of modified note HTML"); +// logger.log(logger.LOW, result.errorMessage); +// logger.log(logger.LOW, "Error Line:Column "+result.errorLine+":" +result.errorColumn); + System.exit(16); + + + } + + // Second pass through the data. The goal of this pass is to + // remove any things we added in NeverNote that do not match + // the ENML schema + XMLCleanup v = new XMLCleanup(); + v.setValue(newContent); + logger.log(logger.HIGH, "Beginning ENML Cleanup"); + v.validate(); + logger.log(logger.HIGH, "Cleanup complete."); + + + + // Final pass through the data. In this one we + // remove any invalid attributes and to save the + // new resources. + logger.log(logger.EXTREME, "Rebuilt ENML:"); + logger.log(logger.EXTREME, v.getValue()); + logger.log(logger.EXTREME, "End Of Rebuilt ENML:"); + resources = v.getResources(); + + + // The XML has the dtd to validate set against Evernote's web + // address. We change it to a local one because otherwise it would + // fail if the user doesn't have internet connectivity. The local copy + // also contains the 3 other PUBLIC definitions at the beginning of the dtd. + newContent = v.getValue(); + File dtdFile = new File(Global.getDirectoryPath()+"xml/enml2.dtd"); + String dtd = dtdFile.toURI().toString(); + newContent = newContent.replace("", + ""); + + logger.log(logger.HIGH, "Validating ENML"); + newContent = repair.parse(newContent, true); + logger.log(logger.HIGH, "Validation complete"); + saveInvalidXML = repair.saveInvalidXML; + + // Restore the correct XML header. + newContent = newContent.replace("", + ""); + + + + return newContent; + } + + + // Fix XML problems that Qt can't deal with + public String fixStupidXMLProblems(String content) { + logger.log(logger.HIGH, "Entering DBRunner.fixStupidXMLProblems"); + + // Fix the problem that the document body isn't properly closed + String newContent = new String(content); + logger.log(logger.MEDIUM, "Inside fixStupidXMLProblems. Old content:"); + logger.log(logger.MEDIUM, content); + + // Fix the problem that the img tag isn't properly closed + int endPos; + logger.log(logger.MEDIUM, "Checking img tags"); + for (int i=newContent.indexOf("0; i = newContent.indexOf("",i+1); + String end = newContent.substring(endPos+1); + newContent = newContent.subSequence(0,endPos) +"/>"+end; + } + + // Fix the problem that the input tag isn't properly closed + logger.log(logger.MEDIUM, "Checking input tags"); + for (int i=newContent.indexOf("0; i = newContent.indexOf("",i+1); + String end = newContent.substring(endPos+1); + newContent = newContent.subSequence(0,endPos) +"/>"+end; + } + + + // Fix the problem that the
tag isn't properly closed + logger.log(logger.MEDIUM, "Checking br tags"); + for (int i=newContent.indexOf("0; i = newContent.indexOf("",i+1); + String end = newContent.substring(endPos+1); + newContent = newContent.subSequence(0,endPos) +"/>"+end; + } + + // Fix the problem that the
tag isn't properly closed + logger.log(logger.MEDIUM, "Checking hr tags"); + for (int i=newContent.indexOf("0; i = newContent.indexOf("",i+1); + String end = newContent.substring(endPos+1); + newContent = newContent.subSequence(0,endPos) +"/>"+end; + } + + logger.log(logger.MEDIUM, "Leaving fixStupidXMLProblems"); + logger.log(logger.HIGH, "Leaving DBRunner.fixStupidXMLProblems"); + return newContent.toString(); + } + + + // Fix XML that Evernote thinks is invalid + public String fixEnXMLCrap(String note) { + int pos; + StringBuffer buffer = new StringBuffer(note); + + // change all to because Evernote hates them if they happen in + pos = buffer.indexOf(""); + for (; pos>-1; ) { + buffer.replace(pos, pos+4, ""); + pos = buffer.indexOf("",pos); + } + // change all
to

because Evernote hates them if they happen in + pos = buffer.indexOf("
"); + for (; pos>-1; ) { + buffer.replace(pos, pos+5, "

"); + pos = buffer.indexOf("
",pos); + } + + // change all elements in lists because Evernote hates them if they happen + int endPos = 0; + int spanPos; + pos = buffer.indexOf("
  • "); + spanPos = buffer.indexOf(""); +/* for (; pos>-1 && spanPos >-1;) { + endPos = buffer.indexOf("
  • ",pos); + if (spanPos > pos && spanPos < endPos) { + buffer.replace(spanPos,spanPos+6,""); + spanPos = buffer.indexOf("
    "); + buffer.replace(spanPos,spanPos+7,""); + } + pos=buffer.indexOf("
  • ",pos+1); + spanPos = buffer.indexOf("",spanPos); + } +*/ + // Get rid of empty spans in
  • elements + pos = buffer.indexOf("
  • "); + spanPos = buffer.indexOf(""); + for (; pos>-1 && spanPos >-1;) { + endPos = buffer.indexOf("
  • ",pos); + if (spanPos > pos && spanPos < endPos) { + buffer.replace(spanPos,spanPos+7,""); + } + pos=buffer.indexOf("
  • ",pos+1); + spanPos = buffer.indexOf("",spanPos); + } + + return buffer.toString(); + } + + // Fix stupid en-media problems + public String fixEnMediaCrap(String note) { + if (note == null) + return null; + + StringBuffer buffer = new StringBuffer(note); + // get rid of any tags since they shouldn't exist. + int pos = buffer.indexOf(""); + for (; pos>-1; ) { + buffer.replace(pos, pos+11, ""); + pos = buffer.indexOf("",pos); + } + + + // Make sure we have a proper /> ending the en-media tag + pos = buffer.indexOf("-1; ) { + pos=buffer.indexOf(">", pos); + if (!buffer.substring(pos-1,pos).equals("/")) + buffer.replace(pos, pos+1, " />"); + pos = buffer.indexOf("4^1)m8oa_WS~17wb8s1ibc5a2}~Z$!nRYo|eIR+|@Ga2M1awaWv5K z$Ufwd5tzCRufw1ls!nhmUCOo=$f)p23Y6+!Urhp4XHOvAm+TOy0?vM{VqFucc)uH~ zEz%tJ&SU{;Ot{Enl31_W%7Y_aWZ{^syUzlq7v`a2ojM%Htsi#18Sj%Tu17LHCy(ozg-9vn!Q2NHv6Kc^2q*n z%zm&zA8D>Xg_5ylGn(R^;ZGg~#&K51>`3u0`cH8E?MEi*M@-*azzk!F0AP`EiLhl% zVg+Ts%znU7VP;Mda~wlE+}-?;yf!3v{G}h91&dvyu=Q_T&L@|H1xhtsi=6r)G_W<0 n^&c>O%Yi8vd1fTAX=z-WXNNR`VpskE7w<;ETYrLAZP(g6pMH1c literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/filters/AttributeFilter.java b/src/cx/fbn/nevernote/filters/AttributeFilter.java new file mode 100644 index 0000000..375909d --- /dev/null +++ b/src/cx/fbn/nevernote/filters/AttributeFilter.java @@ -0,0 +1,39 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.filters; + + +public class AttributeFilter { + private final String name; + private boolean set; + public AttributeFilter(String n) { + name = n; + set = false; + } + public void set(boolean b) { + set = b; + } + public boolean isSet() { + return set; + } + public String getName() { + return name; + } +} diff --git a/src/cx/fbn/nevernote/filters/EnSearch.class b/src/cx/fbn/nevernote/filters/EnSearch.class new file mode 100644 index 0000000000000000000000000000000000000000..b72d6a03c76bce4cce1d0f6a19e7a5c5ad9ccb5a GIT binary patch literal 2133 zcma)7-*XdH6#j00Ee%_!m4KlNv?wH@>Dm?$no=!=LL?MzYAY4RO>&zqO*dt;0m}HM zKKbUGkIp#blZ-e`5t(s#(i#5-{}N{uzq{GcAEBd@$?m=9oO^zJ=iG1q_~(~j0Sw{3 zhJZkC@t(0zunk+@k&az;rLkaDT9!6>iC*E1)f# zZgEl8sLXlVx@%R8oK|BYh>Tjc<&Fs?64|B~FNM78SavzH&2J`~P0k8T{twd~QVmP2-{}ynXndx{1ae)xiTo%}uNVey`3q1l*K3>yt2!~m# zyj?ddgfo`dWZpzOlblz9dv$~n(Qs5C-PX6-?TX>hhpf39&6{otqUb|c2Or0D97j|@ z_bsc=O{=67NgXMiU{`A%wu1uQo3ii$*N|rQ8_gbf9CKB5Jc|CN|2K6EBBDw+%eCDY z#wiUa1@>&5QRX^M<1OM@mYkzlBD)zMzhDh#1rF{oDC|-cXOPh`igNZ*&R9997 z4iW2}4`ozFZ|itR;T<$fCAB}VV*(eLa?QHWX=RhM3Xn-1mlRSV%XSBqAgklumSCs@ zIZSD|DsZ5!5tk~}f?3gV4ezPk3e$DlmX5&DT$`!8=t#3vGcKHO8fBuG#*Bvii!SDN zV;vuW^RBUuxvH}yFqCMIuw^P*Vf?AcBxj?n<3kpnywx&SVaEOv zHmcNLVOA@YY4jh(ZOSw_wA6iXOQ_L@OGz)n&sYS%6hdf-X&4p^sQ-;24Sk~LFCG_6 p{Lb@M-c_w+ksNNm!-VX}k6Z*igw!km<6bq*SYf{!fqS0S>c7BY3!MM} literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/filters/EnSearch.java b/src/cx/fbn/nevernote/filters/EnSearch.java new file mode 100644 index 0000000..5265b1d --- /dev/null +++ b/src/cx/fbn/nevernote/filters/EnSearch.java @@ -0,0 +1,73 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + + +package cx.fbn.nevernote.filters; + +import java.util.ArrayList; +import java.util.List; + +import com.evernote.edam.type.Note; +import com.evernote.edam.type.Tag; + +import cx.fbn.nevernote.Global; +import cx.fbn.nevernote.sql.requests.EnSearchRequest; + +public class EnSearch { + + + private List matches; + public List hilightWords; + int id; + + public EnSearch(int i, String s, List t, int len, int weight) { + id = i; + if (s == null) + return; + if (s.trim().equals("")) + return; + + matches = null; + EnSearchRequest request = new EnSearchRequest(); + request.requestor_id = id; +// request.type = DeletedItemRequest.Get_All; + request.string1 = s; + if (t!=null) { + request.tags = new ArrayList(); + for (int k=0; k matchWords() { + return matches; + } + + + + +} diff --git a/src/cx/fbn/nevernote/filters/NoteSortFilterProxyModel.class b/src/cx/fbn/nevernote/filters/NoteSortFilterProxyModel.class new file mode 100644 index 0000000000000000000000000000000000000000..08f539bcc2a4ab70c0e687fa52701f9bebef7d2c GIT binary patch literal 3351 zcma)8YgZFj6y293jD*1l_)66Z*eXxsTO@#0R7^!gL3~y_Bm)d4GdP*}s;!_N)J>A9Qu!n@NabmM+5N-aF@>bM`*_o|{Kc{`?!j2K=g_OkjQD zLUd%bXvewu!Om zSuZ-8wW0@~XD<-qyJSXSUhlYZ&WL6`D;3>uOvD5#2CPxr@UpHcu=(k?9l2@But%c< zo@?2ovDqtK^bt-Pp1H?y(}pKdJ==yB8N%pxQrWaEAmRe$9hPl*T>|wDy|aKM9M_B< zJTN?NCcIeVkU+4Tu)_#ofsQK7)leg_UFA*w8o|YZ&!-O~WdI z`On7F@j6xuXy=Sn);usGu)3jWe;#hpl23XV5j03#jRK2`xA^ZHhvuM}wAM<)Rvl{* zCBeqTglQ)QTA#OLRuG?ym?UGpPHp;l2d%VUS?PR}j?MDT9M8$cmK1N*QGsxnqis4W z(XPmk%Qqczu1nQfw%M0W51a0wF`S~(s(YP;ks2~wOV0hppf_ewqZ@l?mElDPf*LHJ zFkI87{#L#~Pdp5Xlxet?*o__ydsx>QB~e8>x}|_LBbn^sp^;{9>ez=~;+n`ZKwB}P ze$|Tjd`=zxCF)onL*|;pBPr|GaZrYvZ`qWEr4Euh?Oe)P?MNid2`_WVIWMrLAzlid zY7B8ZXNtku0+ksj>n2RKL7;^qE^z>N3}-yoNO*D2 zOe^bH1=Vp<$6KsFqUgDC zzpuYlrRXfmfoRjRk+X}JvYt&oqe}Ux8dJ0bo{>01y{ZyupfKx7Fg_EQCpTqgGJ|6V z+i?74*eaFYj8Do<%Ho2Ki&7Smf-JgS(~y$LOG8?{qvNu)S~_FJTt>};ex%VA9q&n_ zk$Bo2yV5*YS~t57`S!Fd`kv&ZgsIe8Ssl#C6iSh9=Nc ze7yY*TXekrm68h0yJjc7jvG2Y!%Y^BdC2}W=#-FDTwWVrNb4`3vB<}xMF3yx$l@IJ zo-#*R@Q`bbj`5pC9g#N^k3jM5TWC8K$}VS+w`CKqD^=VA24co>za2nXBuZ^n8SZwBx=lSgWvKUuX{e{adsI& zS^#ZL%~P1)^cSj+O<~~!Ea5P6Y#Pg^Q8$G()lHLVnZ`OkC$aGXwlr~}?EzxHE6<&L zE@oVyfzL+FM-!rG##XeVOTAMuupMu3#%S1qoy?Q*;R+aS9EFK~rz>#MiZ6FaFixR6UBvys}bSo3j7KXMR)HJ|3Nf6D guids; + private String dateFormat; + + public NoteSortFilterProxyModel(QObject parent) { + super(parent); + guids = new HashMap(); + dateFormat = Global.getDateFormat() + " " + Global.getTimeFormat(); + setDynamicSortFilter(true); +// logger = new ApplicationLogger("filter.log"); + } + public void clear() { + guids.clear(); + } + public void addGuid(String guid) { +// if (!guids.containsKey(guid)) + guids.put(guid, null); + } + public void filter() { + dateFormat = Global.getDateFormat() + " " + Global.getTimeFormat(); + invalidateFilter(); + } + @Override + protected boolean filterAcceptsRow(int sourceRow, QModelIndex sourceParent) { + if (guids.size() == 0) + return false; + QAbstractItemModel model = sourceModel(); + QModelIndex guidIndex = sourceModel().index(sourceRow, Global.noteTableGuidPosition); + String guid = (String)model.data(guidIndex); + + if (guids.containsKey(guid)) + return true; + else + return false; + } + + @Override + protected boolean lessThan(QModelIndex left, QModelIndex right) { + Object leftData = sourceModel().data(left); + Object rightData = sourceModel().data(right); + + if (sortColumn() == Global.noteTableCreationPosition || + sortColumn() == Global.noteTableChangedPosition || + sortColumn() == Global.noteTableSubjectDatePosition) { + QDateTime leftDate = QDateTime.fromString(leftData.toString(), dateFormat); + QDateTime rightDate = QDateTime.fromString(rightData.toString(), dateFormat); + return leftDate.compareTo(rightDate) < 0; + } + if (leftData instanceof String && rightData instanceof String) { + String leftString = (String)leftData; + String rightString = (String)rightData; + return leftString.compareTo(rightString) < 0; + } + + return super.lessThan(left, right); + } +} \ No newline at end of file diff --git a/src/cx/fbn/nevernote/filters/NotebookCounter.class b/src/cx/fbn/nevernote/filters/NotebookCounter.class new file mode 100644 index 0000000000000000000000000000000000000000..84a82a00c1122fc0edb40e73c216f0c86c5f0fd6 GIT binary patch literal 1026 zcma)4+iuf96r7Vdc4|y7X)ZwNCB0!gZ7lH$>Psb1rBEJ|NQs`;5pg`3Isd+^bN%37J@pvEs~n=)2QpWR2M9nQ; zqVZJ~KIXB)K;S8l%UHk)>R81S-mymISmHA%>gAmJJ!1>9W=!4sj+LC8r|Wm{uW?Ni zi&$sA4aHv{ape3`!8X5~1D>Ip-?XP}vNgBG!Y7(dRlCIjY+vKj$6PvW6$i=I z7%2Dw{7~X^(`YxRAcfm=&OPV3zvtxpk1yWecMsSmlS&c%lqs7Dtm&lxve$#YXW~PX*h<|5yS&Ia5`! z&uh$HqQMC02j}pDuULN5UO7km4Beo9hW@8=@D|TD8-Y7K*RhJb=;0o2v*OLivBoSgU{%G*&&Gk50Fi6%z$iRyVAM{(*N)WNbpyXhh^8!PyC67g8%>k literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/filters/TagCounter.java b/src/cx/fbn/nevernote/filters/TagCounter.java new file mode 100644 index 0000000..db94809 --- /dev/null +++ b/src/cx/fbn/nevernote/filters/TagCounter.java @@ -0,0 +1,45 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + + +package cx.fbn.nevernote.filters; + +public class TagCounter { + private String guid; + private int count; + + + public TagCounter() { + guid = new String(""); + count = 0; + } + public void setGuid(String g) { + guid = g; + } + public String getGuid() { + return guid; + } + public void setCount(int i) { + count = i; + } + public int getCount() { + return count; + } + +} diff --git a/src/cx/fbn/nevernote/filters/WordFilter.class b/src/cx/fbn/nevernote/filters/WordFilter.class new file mode 100644 index 0000000000000000000000000000000000000000..5016302253ca49d5ff214157e816db3dd3b25d2e GIT binary patch literal 3134 zcmbVOYit`;7XEH*XB>BEi%ARRRi|xQJBe#rpg_`wHZ3VBPWni(X+aPbH4AKbML?Y_m58jtj7l$S_D>_M>1mtC*#ON(sNv2X2vYrmtHlKcfI0ZAZrK< zEIwcyGBUQ|lrlRD2c+o>L=RIXYgH*O&IZdh-?B4mrca=4)G9fKU-P8Es-G-xY>b1` zMt#q6N`3v@(o!tYqpazcGrs5A^urv_O!%4Vgq_(vI$>`!e4}7gB~@EDT8`!S3v5XK z4E>*&?@Q$bcKm{k=k!}07T)R>Weg!K*0BH=3WSoWTpI)~(h)(cl9uRbL#z!KW0{6a z1TLO~{C3+d7`Bc}aTxwBcYtqZEhKK zy}W1nQo{;?E9b>}cTIXnW9Yyt6;Y?a>YsyGDz^Y@kkXJ8SU5W+babJcNL8)7m=VNh zD2lW|x9Lg4mkD2%E3RjFM-$}OmWfi$3UVuvR1%ku_$lR1M#oiH$8+QnX%f}s+*C^K zSBh8bxJCsXF>PshQEU)sFG^d|)|ls(rwv4Ly};&Cu9$u>*;rP&T}>Pwm!3>0IbmA| zWui9_4X2nmEUnVG-@mE1At;NzI{K7rTE&wU!;?{L66ms=s`UJX<@oNj%|=kE#3943 z$!a3mt71$=aU+E-+NWXr zth#L+62l;dbnL(_^fYi_=UBk*S!>PxGmmUmX$+e&tP)~m9_VvX>=F>2N^y^lQS4SfgcnX$N%qe6A)||uQ z41-gF((7LnjV70>Mt`Hj0K3s8W%ikJt-ME?ZiyYoa-Dp@JcAsHp@=aJv~%HE@P-^; zmZYZ;E(t81%}jHVv30;wnS3B9h5gDTE58hfaM^B&2MDa4TluQN(g|73Y^hXi%QTcj z*+8FXhEUNl0d9>lEwlC;XdNS`)p6B2pVaYGFjaF@ZxmRRwH!H8D;K1{!C`a9ZBVdcmSxi`$o_&*W;Q2l>`)dG_o zq~kqxtj(wESf7qxdse)zjvMmJ!tssjKeQoo9MyEZ|1>tMv*Sx5pJ1Q`pJDK0+-W!O;q$w~|P$ zLOVM7idc;_lDt?`xR&?%7Ib3(Js9HbFxFx(GPsRh?M|#iiEqp@uEz7!evR7iU;{qI z4fr>D@gH1|FS-6T`tc2J#J6nq-|@5`F(5+Nif3rOzrhQh#d92yA)XW?uS$A>Yc2HV zE4+x8$a@-J;AKi-9Ke0}BMQucKXH>jtskZSBxhDaJ40t88ia;FYgnV9gFmYNfG+Vp zcD1**aMLRcfG-#t3-Qn}H@edZP9hRM5g_*JjHDRui62u0_r%}qCId``@%(Y5PNTT5 zr%B8yygfp+-CnyOVTh6M;2Yo; zBAz9}!$fw38at80F6_r{+`%~$w~~V#Imicib~VD7!V@mu!rvHVg8LMTEj(c<-o<;g UtB_(JUHC(QPbamMKP`Cw|1e58U;qFB literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/filters/WordFilter.java b/src/cx/fbn/nevernote/filters/WordFilter.java new file mode 100644 index 0000000..f81d64b --- /dev/null +++ b/src/cx/fbn/nevernote/filters/WordFilter.java @@ -0,0 +1,86 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.filters; + +import java.util.List; + +import com.trolltech.qt.sql.QSqlDatabase; +import com.trolltech.qt.sql.QSqlQuery; + +import cx.fbn.nevernote.Global; + +public class WordFilter { + private final List wordList; + QSqlDatabase db; + + public WordFilter(QSqlDatabase d, List list) { + wordList = list; + db = d; + QSqlQuery query = new QSqlQuery(db); + QSqlQuery insert = new QSqlQuery(db); + + if (wordList == null) + return; + if (wordList.size() == 0) + return; + query.exec("create temporary table guidList (guid text)"); + query.clear(); + query.exec("delete from guidList"); + query.clear(); + query.prepare("Select guid from words where word like :word and weight>=:weight"); + insert.prepare("insert into guidList (guid) values (:guid)"); + for (int i=0; i= wordList.size()) { + query.clear(); + return true; + } + } + + query.clear(); + return false; + } + +} diff --git a/src/cx/fbn/nevernote/gui/AttributeTreeWidget.class b/src/cx/fbn/nevernote/gui/AttributeTreeWidget.class new file mode 100644 index 0000000000000000000000000000000000000000..76e469c1e9900861ddd2a5db4b20a3cb1d7c6fc8 GIT binary patch literal 2899 zcmbVO>rYc>82>#MdP+Ttq7`v4@rDJ&I)*pOP{147f^t(fr=GS4I9l4;o+3JTclRyX zzW8ZbvSpc{TsD>!GqPpLk}YvrvJd-UvMl=p=9m2gW52g81)+Q~X;0ttywCf4F7NMo zp5FiOyB`2F;{y#V1m5tZZzL4+#mosa8H?MdZ!~TBI&3>>h0?Y;kTlJ+R%Fz)HIxWy z!|`#Sos37LwizDtUA42?XXdp8&NeG%+3f;{w|+=a(iM-GZa7e;qZCdTRtnq&_>>!h zRXSFqT(CN2+9ymSVkQGd$czd+-oRyJ!th0n*r>0c9>qre^+RP?i**_*1TDqA=?JCl zq!G5eZF79cGOum#H=}0Qw&JlMebKQV9vTa#qqbGp5$p>*4w_#DP^n`hssw8oKmk$N z5*+kC9&9emCv;RRXUqE;dekgnYj{$yy|};gccJ2UqXuOzY!PT(Nz<^+h>~p6u^l@o zqr(H{q%GLs?JkyU72Qr9UewbGBN7>iCjul&R6z^smkaJuA9!ajGzv-?MVMTuL6eT% z3erW$t}!bb(XdC*RFsNG=yZWE$1D;rIbejM#POl53{PXPh8EtzlEcTN@sJVKu@CzN z>%zI{JI#@J(#*jKe1RpW6#JJm=~w0s>S$Gn6?w#LP&q)g-KOK2oWU`&){HDPsP+%( zIGj74+h1^8MbxRI3r;~9ZzgwCNssC{rlf943)kqw2_4-^>{7hT<<^H&Is$XLgNcZ` zat%Es=i*Xw;j~~&IBKL)3Bw+1U6Kkb9FL`ZZUoV%YPVd&fM8Q`)^$@?1M9tVv6;>^ z@7GK!m~%RY@hoXKVMNnr?}(soVTJdGF0)Mi^-GE9#vuA!c%Hq&nCnct6R}Yxzo_F9 z4E7x(kuYNs(r6*(T-R8FnRkozJBYB32w1ExJD$@QtoIgmqaS^WzhgQqT+Y>xikyv+ z^|O3tSOMx9Nyc$dSz|lxF~(`p^^ z>{>P&Ys4}cd3nH!nLX+8P`*S+(m*_HM2C!|rAj7SH-xmutdyXkIQa{;HebYkx}0Y_ zuWXq(=hann;1OrSNSZOaTpCs-&h#omohH?kUyEtN10`x-P`!)+m1t^-#c#JjCvolh z*jM%2M)*q5NaTZb_s7%8u&Q)sZ)1_5b}J7E(;bVM$u3m|W=g|*46yh;E}kk(f1w|% zUXLy8l@3l;@Rvcu$)^T5e&O0h;lqY$xEd=dzr@MqVf@8lm_-HiHCf=mHQxGa z_H$q}N>B?oIkFbpP|4~0BzB^XgS83u{4dss7OvVj6}#9cPGApCQaZqSae+Hy*o!3g zV-g4O5)R@PC(yg_<3paf&2jTF+VL63%3XBeK05I`Q6At3{>D)}$t(U zI{6td;3li3MegB6u2!H;zG9>|nZvts2ruIm=I_32#jALY)$|*4^E$KOlugWBZqG!3GmX6_Tz7&x%aTRqF{xt4BHk^9y4)pYAE!mPmC Rc!$60uhCjw!~2J;{s%$801*HH literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/gui/AttributeTreeWidget.java b/src/cx/fbn/nevernote/gui/AttributeTreeWidget.java new file mode 100644 index 0000000..c498119 --- /dev/null +++ b/src/cx/fbn/nevernote/gui/AttributeTreeWidget.java @@ -0,0 +1,171 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.gui; + +import com.trolltech.qt.gui.QAbstractItemView; +import com.trolltech.qt.gui.QIcon; +import com.trolltech.qt.gui.QTreeWidget; +import com.trolltech.qt.gui.QTreeWidgetItem; + +import cx.fbn.nevernote.Global; + +public class AttributeTreeWidget extends QTreeWidget { + + public AttributeTreeWidget() { + setHeaderLabel("Attributes"); + setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection); + + setHeaderLabel("Attributes"); + setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection); + + // Setup the first attribute tree + QTreeWidgetItem created = new QTreeWidgetItem(); + created.setText(0,"Created"); + addTopLevelItem(created); + // Created Since List + QTreeWidgetItem parent = created; + QTreeWidgetItem child; + child = new QTreeWidgetItem(); + child.setText(0,"Since"); + parent.addChild(child); + parent = child; + + Global.createdBeforeFilter = new DateAttributeFilterTable(); + Global.createdSinceFilter = new DateAttributeFilterTable(); + Global.changedBeforeFilter = new DateAttributeFilterTable(); + Global.changedSinceFilter = new DateAttributeFilterTable(); + Global.containsFilter = new ContainsAttributeFilterTable(); + + Global.createdBeforeFilter.setBefore(); + Global.createdBeforeFilter.setCreated(); + Global.createdSinceFilter.setSince(); + Global.createdSinceFilter.setCreated(); + Global.changedBeforeFilter.setBefore(); + Global.changedBeforeFilter.setUpdated(); + Global.changedSinceFilter.setSince(); + Global.changedBeforeFilter.setUpdated(); + + String iconPath = new String("classpath:cx/fbn/nevernote/icons/"); + QIcon icon = new QIcon(iconPath+"attribute.png"); + for (int i=0; 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 z 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 allTags; + private List currentTags; + public NoteSignal noteSignal; + private List notebookList; + private Note currentNote; + private String saveNoteTitle; + private String saveTagList; + private boolean insideList; +// private String selectedText; + private final DatabaseConnection conn; + private final QCalendarWidget createdCalendarWidget; + private final QCalendarWidget alteredCalendarWidget; + private final QCalendarWidget subjectCalendarWidget; + + public final QPushButton undoButton; + public final QPushButton redoButton; + public final QPushButton cutButton; + public final QPushButton copyButton; + public final QPushButton pasteButton; + public final QPushButton boldButton; + public final QPushButton underlineButton; + public final QPushButton italicButton; + public final Signal0 focusLost; + public final NoteResourceSignal resourceSignal; + + public QPushButton rightAlignButton; + public QPushButton leftAlignButton; + public QPushButton centerAlignButton; + + public final QPushButton strikethroughButton; + public final QPushButton hlineButton; + public final QPushButton indentButton; + public final QPushButton outdentButton; + public final QPushButton bulletListButton; + public final QPushButton numberListButton; + + public final QShortcut focusTitleShortcut; + public final QShortcut focusTagShortcut; + public final QShortcut focusNoteShortcut; + public final QShortcut focusUrlShortcut; + public final QShortcut focusAuthorShortcut; + + public final QComboBox fontList; + public final QPushButton fontColor; + private final ColorMenu fontColorMenu; + public final QPushButton fontHilight; +// public final ColorComboBox fontHilight; + private final ColorMenu fontHilightColorMenu; + public final QFileSystemWatcher fileWatcher; + public int cursorPosition; + private boolean forceTextPaste = false; + private String selectedFile; + private String currentHyperlink; + public boolean keepPDFNavigationHidden; + private final ApplicationLogger logger; + + private final HashMap previewPageList; + + + public BrowserWindow(DatabaseConnection c) { + logger = new ApplicationLogger("browser.log"); + logger.log(logger.HIGH, "Setting up browser"); + + fileWatcher = new QFileSystemWatcher(); +// fileWatcher.fileChanged.connect(this, "fileChanged(String)"); + noteSignal = new NoteSignal(); + titleLabel = new QLineEdit(); + titleLabel.setMaxLength(Constants.EDAM_NOTE_TITLE_LEN_MAX); + urlText = new QLineEdit(); + authorText = new QLineEdit(); + urlLabel = new QLabel(); + authorLabel = new QLabel(); + conn = c; + + focusLost = new Signal0(); + + tagEdit = new TagLineEdit(allTags); + tagLabel = new QLabel("Tags:"); + tagEdit.focusLost.connect(this, "modifyTagsTyping()"); + + createdCalendarWidget = new QCalendarWidget(); + createdDate = new QDateEdit(); + createdDate.setDisplayFormat(Global.getDateFormat()); + createdDate.setCalendarPopup(true); + createdDate.setCalendarWidget(createdCalendarWidget); + createdTime = new QTimeEdit(); + createdDate.dateChanged.connect(this, "createdChanged()"); + createdTime.timeChanged.connect(this, "createdChanged()"); + + alteredCalendarWidget = new QCalendarWidget(); + alteredDate = new QDateEdit(); + alteredDate.setDisplayFormat(Global.getDateFormat()); + alteredDate.setCalendarPopup(true); + alteredDate.setCalendarWidget(alteredCalendarWidget); + alteredTime = new QTimeEdit(); + alteredLabel = new QLabel("Altered:"); + alteredDate.dateChanged.connect(this, "alteredChanged()"); + alteredTime.timeChanged.connect(this, "alteredChanged()"); + + subjectCalendarWidget = new QCalendarWidget(); + subjectDate = new QDateEdit(); + subjectDate.setDisplayFormat(Global.getDateFormat()); + subjectDate.setCalendarPopup(true); + subjectDate.setCalendarWidget(subjectCalendarWidget); + subjectTime = new QTimeEdit(); + subjectLabel = new QLabel("Subject Date:"); + subjectDate.dateChanged.connect(this, "subjectDateTimeChanged()"); + subjectTime.timeChanged.connect(this, "subjectDateTimeChanged()"); + authorText.textChanged.connect(this, "authorChanged()"); + urlText.textChanged.connect(this, "sourceUrlChanged()"); + + notebookBox = new QComboBox(); + notebookLabel = new QLabel("Notebook"); + createdLabel = new QLabel("Created:"); + // selectedText = new String(); + + urlLabel.setVisible(false); + urlText.setVisible(false); + authorLabel.setVisible(false); + authorText.setVisible(false); + createdDate.setVisible(false); + alteredLabel.setVisible(false); + //notebookBox.setVisible(false); + notebookLabel.setVisible(false); + createdLabel.setVisible(false); + createdTime.setVisible(false); + alteredDate.setVisible(false); + alteredTime.setVisible(false); + subjectLabel.setVisible(false); + subjectDate.setVisible(false); + subjectTime.setVisible(false); + extendedOn = false; + buttonsVisible = true; + setAcceptDrops(true); + + browser = new ContentView(this); + browser.page().setLinkDelegationPolicy( + QWebPage.LinkDelegationPolicy.DelegateAllLinks); + browser.linkClicked.connect(this, "linkClicked(QUrl)"); + currentHyperlink = ""; + + QVBoxLayout v = new QVBoxLayout(); + QFormLayout notebookLayout = new QFormLayout(); + QGridLayout dateLayout = new QGridLayout(); + titleLabel.setReadOnly(false); + titleLabel.editingFinished.connect(this, "titleEdited()"); + browser.page().contentsChanged.connect(this, "contentChanged()"); + browser.page().selectionChanged.connect(this, "selectionChanged()"); + browser.page().mainFrame().javaScriptWindowObjectCleared.connect(this, + "exposeToJavascript()"); + + notebookBox.activated.connect(this, "notebookChanged()"); + resourceSignal = new NoteResourceSignal(); + + QHBoxLayout tagLayout = new QHBoxLayout(); + v.addWidget(titleLabel, 0); + notebookLayout.addRow(notebookLabel, notebookBox); + tagLayout.addLayout(notebookLayout, 0); + tagLayout.stretch(4); + tagLayout.addWidget(tagLabel, 0); + tagLayout.addWidget(tagEdit, 1); + v.addLayout(tagLayout); + + QHBoxLayout urlLayout = new QHBoxLayout(); + urlLayout.addWidget(urlLabel, 0); + urlLayout.addWidget(urlText, 0); + v.addLayout(urlLayout); + + QHBoxLayout authorLayout = new QHBoxLayout(); + authorLayout.addWidget(authorLabel, 0); + authorLayout.addWidget(authorText, 0); + v.addLayout(authorLayout); + + dateLayout.addWidget(createdLabel, 0, 0); + dateLayout.addWidget(createdDate, 0, 1); + dateLayout.addWidget(createdTime, 0, 2); + dateLayout.setColumnStretch(9, 100); + dateLayout.addWidget(alteredLabel, 0, 3); + dateLayout.addWidget(alteredDate, 0, 4); + dateLayout.addWidget(alteredTime, 0, 5); + dateLayout.addWidget(subjectLabel, 0, 6); + dateLayout.addWidget(subjectDate, 0, 7); + dateLayout.addWidget(subjectTime, 0, 8); + v.addLayout(dateLayout, 0); + + undoButton = newEditorButton("undo", "Undo Change"); + redoButton = newEditorButton("redo", "Redo Change"); + cutButton = newEditorButton("cut", "Cut"); + copyButton = newEditorButton("copy", "Copy"); + pasteButton = newEditorButton("paste", "Paste"); + boldButton = newEditorButton("bold", "Bold"); + underlineButton = newEditorButton("underline", "Underline"); + italicButton = newEditorButton("italic", "Italic"); + + rightAlignButton = newEditorButton("justifyRight", "Right Align"); + leftAlignButton = newEditorButton("justifyLeft", "Left Align"); + centerAlignButton = newEditorButton("justifyCenter", "Center Align"); + + strikethroughButton = newEditorButton("strikethrough", "Strikethrough"); + hlineButton = newEditorButton("hline", "Insert Horizontal Line"); + indentButton = newEditorButton("indent", "Shift Right"); + outdentButton = newEditorButton("outdent", "Shift Left"); + bulletListButton = newEditorButton("bulletList", "Bullet List"); + numberListButton = newEditorButton("numberList", "Number List"); + + + QHBoxLayout buttonLayout; + buttonLayout = new QHBoxLayout(); + buttonLayout.setSpacing(0); + v.addLayout(buttonLayout); + + buttonLayout.addWidget(undoButton); + buttonLayout.addWidget(redoButton); + + buttonLayout.addWidget(newSeparator(), 0); + buttonLayout.addWidget(cutButton); + buttonLayout.addWidget(copyButton); + buttonLayout.addWidget(pasteButton); + + buttonLayout.addWidget(newSeparator(), 0); + buttonLayout.addWidget(boldButton); + buttonLayout.addWidget(italicButton); + buttonLayout.addWidget(underlineButton); + buttonLayout.addWidget(strikethroughButton); + + buttonLayout.addWidget(newSeparator(), 0); + buttonLayout.addWidget(leftAlignButton); + buttonLayout.addWidget(centerAlignButton); + buttonLayout.addWidget(rightAlignButton); + + buttonLayout.addWidget(newSeparator(), 0); + buttonLayout.addWidget(hlineButton); + + buttonLayout.addWidget(indentButton); + buttonLayout.addWidget(outdentButton); + buttonLayout.addWidget(bulletListButton); + buttonLayout.addWidget(numberListButton); + + // Setup the font & font size combo boxes + buttonLayout.addWidget(newSeparator(), 0); + fontList = new QComboBox(); + fontSize = new QComboBox(); + fontList.setToolTip("Font"); + fontSize.setToolTip("Font Size"); + fontList.activated.connect(this, "fontChanged(String)"); + fontSize.activated.connect(this, "fontSizeChanged(String)"); + buttonLayout.addWidget(fontList, 0); + buttonLayout.addWidget(fontSize, 0); + QFontDatabase fonts = new QFontDatabase(); + List fontFamilies = fonts.families(); + for (int i = 0; i < fontFamilies.size(); i++) { + fontList.addItem(fontFamilies.get(i)); + if (i == 0) { + loadFontSize(fontFamilies.get(i)); + } + } + + buttonLayout.addWidget(newSeparator(), 0); + fontColor = newEditorButton("fontColor", "Font Color"); + fontColorMenu = new ColorMenu(this); + fontColor.setMenu(fontColorMenu.getMenu()); + fontColorMenu.getMenu().triggered.connect(this, "fontColorClicked()"); + buttonLayout.addWidget(fontColor); + fontHilight = newEditorButton("fontHilight", "Font Hilight Color"); + fontHilightColorMenu = new ColorMenu(this); + fontHilight.setMenu(fontHilightColorMenu.getMenu()); + fontHilightColorMenu.getMenu().triggered.connect(this, "fontHilightClicked()"); + buttonLayout.addWidget(fontHilight); + + buttonLayout.addWidget(new QLabel(), 1); + v.addWidget(browser, 1); +// v.addLayout(buttonLayout,0); + setLayout(v); + + browser.downloadAttachmentRequested.connect(this, + "downloadAttachment(QNetworkRequest)"); + browser.downloadImageRequested.connect(this, + "downloadImage(QNetworkRequest)"); + setTabOrder(notebookBox, tagEdit); + setTabOrder(tagEdit, browser); + + focusNoteShortcut = new QShortcut(this); + setupShortcut(focusNoteShortcut, "Focus_Note"); + focusNoteShortcut.activated.connect(this, "focusNote()"); + focusTitleShortcut = new QShortcut(this); + setupShortcut(focusTitleShortcut, "Focus_Title"); + focusTitleShortcut.activated.connect(this, "focusTitle()"); + focusTagShortcut = new QShortcut(this); + setupShortcut(focusTagShortcut, "Focus_Tag"); + focusTagShortcut.activated.connect(this, "focusTag()"); + focusAuthorShortcut = new QShortcut(this); + setupShortcut(focusAuthorShortcut, "Focus_Author"); + focusAuthorShortcut.activated.connect(this, "focusAuthor()"); + focusUrlShortcut = new QShortcut(this); + setupShortcut(focusUrlShortcut, "Focus_Url"); + focusUrlShortcut.activated.connect(this, "focusUrl()"); + + browser.page().mainFrame().setTextSizeMultiplier(Global.getTextSizeMultiplier()); + browser.page().mainFrame().setZoomFactor(Global.getZoomFactor()); + + previewPageList = new HashMap(); + + browser.page().microFocusChanged.connect(this, "microFocusChanged()"); + logger.log(logger.HIGH, "Browser setup complete"); + } + + + private void setupShortcut(QShortcut action, String text) { + if (!Global.shortcutKeys.containsAction(text)) + return; + action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text))); + } + + + + + // Getter for the QWebView + public QWebView getBrowser() { + return browser; + } + + // Block signals while loading data or things are flagged as dirty by + // mistake + public void loadingData(boolean val) { + logger.log(logger.EXTREME, "Entering BrowserWindow.loadingData() " +val); + notebookBox.blockSignals(val); + browser.page().blockSignals(val); + browser.page().mainFrame().blockSignals(val); + titleLabel.blockSignals(val); + alteredDate.blockSignals(val); + alteredTime.blockSignals(val); + createdTime.blockSignals(val); + createdDate.blockSignals(val); + subjectDate.blockSignals(val); + subjectTime.blockSignals(val); + urlText.blockSignals(val); + authorText.blockSignals(val); + if (!val) + exposeToJavascript(); + logger.log(logger.EXTREME, "Exiting BrowserWindow.loadingData() " +val); + } + + // Enable/disable + public void setReadOnly(boolean v) { + setEnabled(true); + titleLabel.setEnabled(!v); + notebookBox.setEnabled(!v); + tagEdit.setEnabled(!v); + authorLabel.setEnabled(!v); + urlText.setEnabled(!v); + createdDate.setEnabled(!v); + subjectDate.setEnabled(!v); + alteredDate.setEnabled(!v); + getBrowser().setEnabled(true); + } + + // expose this class to Javascript on the web page + private void exposeToJavascript() { + browser.page().mainFrame().addToJavaScriptWindowObject("jambi", this); + } + + // Custom event queue + @Override + public boolean event(QEvent e) { + if (e.type().equals(QEvent.Type.FocusOut)) { + logger.log(logger.EXTREME, "Focus lost"); + focusLost.emit(); + } + return super.event(e); + } + + // clear out browser + public void clear() { + logger.log(logger.EXTREME, "Entering BrowserWindow.clear()"); + setNote(null); + browser.setContent(new QByteArray()); + tagEdit.setText(""); + urlLabel.setText("Source URL:"); + titleLabel.setText(""); + logger.log(logger.EXTREME, "Exiting BrowserWindow.clear()"); + } + + // get/set current note + public void setNote(Note n) { + currentNote = n; + if (n == null) + n = new Note(); + saveNoteTitle = n.getTitle(); + + } + + public Note getNote() { + return currentNote; + } + + // New Editor Button + private QPushButton newEditorButton(String name, String toolTip) { + QPushButton button = new QPushButton(); + QIcon icon = new QIcon(iconPath + name + ".gif"); + button.setIcon(icon); + button.setToolTip(toolTip); + button.clicked.connect(this, name + "Clicked()"); + return button; + } + + // New Separator + private QLabel newSeparator() { + return new QLabel(" "); + } + + // Set the title in the window + public void setTitle(String t) { + titleLabel.setText(t); + saveNoteTitle = t; + checkNoteTitle(); + } + + // Return the current text title + public String getTitle() { + return titleLabel.text(); + } + + // Set the tag name string + public void setTag(String t) { + saveTagList = t; + tagEdit.setText(t); + } + + // Set the source URL + public void setUrl(String t) { + urlLabel.setText("Source URL:\t"); + urlText.setText(t); + } + + public void setAuthor(String t) { + authorLabel.setText("Author:\t"); + authorText.setText(t); + } + + // Set the creation date + public void setCreation(long date) { + QDateTime dt = new QDateTime(); + dt.setTime_t((int) (date / 1000)); + createdDate.setDateTime(dt); + createdTime.setDateTime(dt); + createdDate.setDisplayFormat(Global.getDateFormat()); + createdTime.setDisplayFormat(Global.getTimeFormat()); + } + + // Set the creation date + public void setAltered(long date) { + QDateTime dt = new QDateTime(); + dt.setTime_t((int) (date / 1000)); + alteredDate.setDateTime(dt); + alteredTime.setDateTime(dt); + alteredDate.setDisplayFormat(Global.getDateFormat()); + alteredTime.setDisplayFormat(Global.getTimeFormat()); + } + + // Set the subject date + public void setSubjectDate(long date) { + QDateTime dt = new QDateTime(); + dt.setTime_t((int) (date / 1000)); + subjectDate.setDateTime(dt); + subjectTime.setDateTime(dt); + subjectDate.setDisplayFormat(Global.getDateFormat()); + subjectTime.setDisplayFormat(Global.getTimeFormat()); + } + + // Toggle the extended attribute information + public void toggleInformation() { + if (extendedOn) { + extendedOn = false; + } else { + extendedOn = true; + } + urlLabel.setVisible(extendedOn); + urlText.setVisible(extendedOn); + authorText.setVisible(extendedOn); + authorLabel.setVisible(extendedOn); + createdDate.setVisible(extendedOn); + createdTime.setVisible(extendedOn); + createdLabel.setVisible(extendedOn); + alteredLabel.setVisible(extendedOn); + alteredDate.setVisible(extendedOn); + alteredTime.setVisible(extendedOn); + //notebookBox.setVisible(extendedOn); + notebookLabel.setVisible(extendedOn); + subjectLabel.setVisible(extendedOn); + subjectDate.setVisible(extendedOn); + subjectTime.setVisible(extendedOn); + } + + public void hideButtons() { + + buttonsVisible = false; + + undoButton.setVisible(false); + redoButton.setVisible(false); + cutButton.setVisible(false); + copyButton.setVisible(false); + pasteButton.setVisible(false); + boldButton.setVisible(false); + underlineButton.setVisible(false); + italicButton.setVisible(false); + + rightAlignButton.setVisible(false); + leftAlignButton.setVisible(false); + centerAlignButton.setVisible(false); + + strikethroughButton.setVisible(false); + hlineButton.setVisible(false); + indentButton.setVisible(false); + outdentButton.setVisible(false); + bulletListButton.setVisible(false); + numberListButton.setVisible(false); + + fontList.setVisible(false); + fontSize.setVisible(false); + fontColor.setVisible(false); + fontHilight.setVisible(false); + + } + + + // Is the extended view on? + public boolean isExtended() { + return extendedOn; + } + + // Listener for when a link is clicked + @SuppressWarnings("unused") + private void openFile() { + logger.log(logger.EXTREME, "Starting openFile()"); + File fileHandle = new File(selectedFile); + URI fileURL = fileHandle.toURI(); + String localURL = fileURL.toString(); + QUrl url = new QUrl(localURL); + QFile file = new QFile(selectedFile); + + logger.log(logger.EXTREME, "Adding to fileWatcher:"+file.fileName()); + fileWatcher.addPath(file.fileName()); + + if (!QDesktopServices.openUrl(url)) { + logger.log(logger.LOW, "Error opening file :" +url); + } + } + + + // Listener for when a link is clicked + @SuppressWarnings("unused") + private void linkClicked(QUrl url) { + logger.log(logger.EXTREME, "URL Clicked: " +url.toString()); + if (url.toString().substring(0,8).equals("nnres://")) { + logger.log(logger.EXTREME, "URL is NN resource"); + if (url.toString().endsWith("/vnd.evernote.ink")) { + logger.log(logger.EXTREME, "Unable to open ink note"); + QMessageBox.information(this, "Unable Open", "This is an ink note.\n"+ + "Ink notes are not supported since Evernote has not\n published any specifications on them\n" + + "and I'm too lazy to figure them out by myself."); + return; + } + String fullName = url.toString().substring(8); + int index = fullName.indexOf("."); + String guid = ""; + String type = ""; + if (index >-1) { + type = fullName.substring(index+1); + guid = fullName.substring(0,index); + } + index = guid.indexOf(Global.attachmentNameDelimeter); + if (index > -1) { + guid = guid.substring(0,index); + } + List resList = currentNote.getResources(); + Resource res = null; + for (int i=0; i fileNames = dialog.selectedFiles(); //gets all selected filenames + if (fileNames.size() == 0) + return; + String sf = fileNames.get(0); + QFile saveFile = new QFile(sf); + mode.set(QFile.OpenModeFlag.WriteOnly); + saveFile.open(mode); + QDataStream saveOut = new QDataStream(saveFile); + saveOut.writeBytes(binData.toByteArray()); + saveFile.close(); + return; + } + } + } + return; + } + logger.log(logger.EXTREME, "Launching URL"); + QDesktopServices.openUrl(url); + } + + // Listener for when BOLD is clicked + @SuppressWarnings("unused") + private void undoClicked() { + browser.page().triggerAction(WebAction.Undo); + browser.setFocus(); + } + + // Listener for when BOLD is clicked + @SuppressWarnings("unused") + private void redoClicked() { + browser.page().triggerAction(WebAction.Redo); + browser.setFocus(); + } + + // Listener for when BOLD is clicked + @SuppressWarnings("unused") + private void boldClicked() { + browser.page().triggerAction(WebAction.ToggleBold); + microFocusChanged(); + browser.setFocus(); + } + + // Listener for when Italics is clicked + @SuppressWarnings("unused") + private void italicClicked() { + browser.page().triggerAction(WebAction.ToggleItalic); + microFocusChanged(); + browser.setFocus(); + } + + // Listener for when UNDERLINE is clicked + @SuppressWarnings("unused") + private void underlineClicked() { + browser.page().triggerAction(WebAction.ToggleUnderline); + microFocusChanged(); + browser.setFocus(); + } + + // Listener for when Strikethrough is clicked + @SuppressWarnings("unused") + private void strikethroughClicked() { + browser.page().mainFrame().evaluateJavaScript( + "document.execCommand('strikeThrough', false, '');"); + browser.setFocus(); + } + + // Listener for when cut is clicked + @SuppressWarnings("unused") + private void cutClicked() { + browser.page().triggerAction(WebAction.Cut); + browser.setFocus(); + } + + // Listener when COPY is clicked + @SuppressWarnings("unused") + private void copyClicked() { + browser.page().triggerAction(WebAction.Copy); + browser.setFocus(); + } + + // Listener when PASTE is clicked + void pasteClicked() { + logger.log(logger.EXTREME, "Paste Clicked"); + if (forceTextPaste) { + pasteWithoutFormattingClicked(); + return; + } + QClipboard clipboard = QApplication.clipboard(); + QMimeData mime = clipboard.mimeData(); + +// String x = mime.html(); + + if (mime.hasImage()) { + logger.log(logger.EXTREME, "Image paste found"); + insertImage(mime); + browser.setFocus(); + return; + } + + if (mime.hasUrls()) { + logger.log(logger.EXTREME, "URL paste found"); + handleUrls(mime); + browser.setFocus(); + return; + } + + String text = mime.html(); + if (text.contains("en-tag") && mime.hasHtml()) { + logger.log(logger.EXTREME, "Intra-note paste found"); + text = fixInternotePaste(text); + mime.setHtml(text); + clipboard.setMimeData(mime); + } + + logger.log(logger.EXTREME, "Final paste choice encountered"); + browser.page().triggerAction(WebAction.Paste); + browser.setFocus(); + + } + + // Paste text without formatting + private void pasteWithoutFormattingClicked() { + logger.log(logger.EXTREME, "Paste without format clipped"); + QClipboard clipboard = QApplication.clipboard(); + QMimeData mime = clipboard.mimeData(); + if (!mime.hasText()) + return; + String text = mime.text(); + clipboard.setText(text); + browser.page().triggerAction(WebAction.Paste); + QApplication.clipboard().setMimeData(mime); + browser.setFocus(); + + } + + // insert date/time + @SuppressWarnings("unused") + private void insertDateTime() { + String fmt = Global.getDateFormat() + " " + Global.getTimeFormat(); + String dateTimeFormat = new String(fmt); + SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat); + Calendar cal = Calendar.getInstance(); + + browser.page().mainFrame().evaluateJavaScript( + "document.execCommand('insertHtml', false, '"+simple.format(cal.getTime())+"');"); + + browser.setFocus(); + + } + + // Listener when Left is clicked + @SuppressWarnings("unused") + private void justifyLeftClicked() { + browser.page().mainFrame().evaluateJavaScript( + "document.execCommand('JustifyLeft', false, '');"); + browser.setFocus(); + } + + // Listener when Center is clicked + @SuppressWarnings("unused") + private void justifyCenterClicked() { + browser.page().mainFrame().evaluateJavaScript( + "document.execCommand('JustifyCenter', false, '');"); + browser.setFocus(); + } + + // Listener when Left is clicked + @SuppressWarnings("unused") + private void justifyRightClicked() { + browser.page().mainFrame().evaluateJavaScript( + "document.execCommand('JustifyRight', false, '');"); + browser.setFocus(); + } + + // Listener when HLINE is clicked + @SuppressWarnings("unused") + private void hlineClicked() { + browser.page().mainFrame().evaluateJavaScript( + "document.execCommand('insertHorizontalRule', false, '');"); + browser.setFocus(); + } + + // Listener when outdent is clicked + private void outdentClicked() { + browser.page().mainFrame().evaluateJavaScript( + "document.execCommand('outdent', false, '');"); + browser.setFocus(); + } + + // Listener when a bullet list is clicked + @SuppressWarnings("unused") + private void bulletListClicked() { + browser.page().mainFrame().evaluateJavaScript( + "document.execCommand('InsertUnorderedList', false, '');"); + browser.setFocus(); + } + + // Listener when a bullet list is clicked + @SuppressWarnings("unused") + private void numberListClicked() { + browser.page().mainFrame().evaluateJavaScript( + "document.execCommand('InsertOrderedList', false, '');"); + browser.setFocus(); + } + + // Listener when indent is clicked + private void indentClicked() { + browser.page().mainFrame().evaluateJavaScript( + "document.execCommand('indent', false, '');"); + browser.setFocus(); + } + + // Listener when the font name is changed + @SuppressWarnings("unused") + private void fontChanged(String font) { + browser.page().mainFrame().evaluateJavaScript( + "document.execCommand('fontName',false,'" + font + "');"); + browser.setFocus(); + } + + // Listener when a font size is changed + @SuppressWarnings("unused") + private void fontSizeChanged(String font) { + String text = browser.selectedText(); + if (text.trim().equalsIgnoreCase("")) + return; + + String selectedText = browser.selectedText(); + String url = ""+selectedText +""; + String script = "document.execCommand('insertHtml', false, '"+url+"');"; + browser.page().mainFrame().evaluateJavaScript(script); +/* browser.page().mainFrame().evaluateJavaScript( + "document.execCommand('fontSize',false,'" + + font + "');"); +*/ + browser.setFocus(); + } + + // Load the font combo box based upon the font selected + private void loadFontSize(String name) { + QFontDatabase db = new QFontDatabase(); + fontSize.clear(); + List points = db.pointSizes(name); + for (int i=0; i"); + browser.page().mainFrame().evaluateJavaScript( + script_start + todo + script_end); + browser.setFocus(); + } + + // Encrypt the selected text + @SuppressWarnings("unused") + private void encryptText() { + String text = browser.selectedText(); + if (text.trim().equalsIgnoreCase("")) + return; + + EnCryptDialog dialog = new EnCryptDialog(); + dialog.exec(); + if (!dialog.okPressed()) { + return; + } + + EnCrypt crypt = new EnCrypt(); + String encrypted = crypt.encrypt(text, dialog.getPassword().trim(), 64); + + if (encrypted.trim().equals("")) { + QMessageBox.information(this, "Error", "Error Encrypting String"); + return; + } + StringBuffer imgPath = new StringBuffer(Global.getDirectoryPath()); + for (int i = 0; i < imgPath.length(); i++) + if (imgPath.charAt(i) == '\\') + imgPath.setCharAt(i, '/'); + StringBuffer buffer = new StringBuffer(encrypted.length() + 100); + buffer.append("\"");"); + + String script_start = new String( + "document.execCommand('insertHtml', false, '"); + String script_end = new String("');"); + browser.page().mainFrame().evaluateJavaScript( + script_start + buffer.toString() + script_end); + } + + + // Insert a hyperlink + public void insertLink() { + logger.log(logger.EXTREME, "Inserting link"); + String text = browser.selectedText(); + if (text.trim().equalsIgnoreCase("")) + return; + + InsertLinkDialog dialog = new InsertLinkDialog(); + if (currentHyperlink != null && currentHyperlink != "") { + dialog.setUrl(currentHyperlink); + } + dialog.exec(); + if (!dialog.okPressed()) { + logger.log(logger.EXTREME, "Insert link canceled"); + return; + } + if (browser.insertLinkAction.text().equalsIgnoreCase("Insert Hyperlink")) { + String selectedText = browser.selectedText(); + logger.log(logger.EXTREME, "Inserting link on text "+selectedText); + logger.log(logger.EXTREME, "URL Link " +dialog.getUrl().trim()); + String url = ""+selectedText +""; + String script = "document.execCommand('insertHtml', false, '"+url+"');"; + browser.page().mainFrame().evaluateJavaScript(script); + return; + } else { + String js = new String( "function getCursorPos() {" + +"var cursorPos;" + +"if (window.getSelection) {" + +" var selObj = window.getSelection();" + +" var selRange = selObj.getRangeAt(0);" + +" var workingNode = window.getSelection().anchorNode.parentNode;" + +" while(workingNode != null) { " + +" if (workingNode.nodeName.toLowerCase()=='a') workingNode.setAttribute('href','" +dialog.getUrl() +"');" + +" workingNode = workingNode.parentNode;" + +" }" + +"}" + +"} getCursorPos();"); + browser.page().mainFrame().evaluateJavaScript(js); + contentChanged(); + } + + } + + // Insert a table + public void insertTable() { + TableDialog dialog = new TableDialog(); + dialog.exec(); + if (!dialog.okPressed()) { + return; + } + + int cols = dialog.getCols(); + int rows = dialog.getRows(); + int width = dialog.getWidth(); + boolean percent = dialog.isPercent(); + + String newHTML = ""; + + for (int i=0; i"; + for (int j=0; j "; + } + newHTML = newHTML +""; + } + newHTML = newHTML+"
    "; + + String script = "document.execCommand('insertHtml', false, '"+newHTML+"');"; + browser.page().mainFrame().evaluateJavaScript(script); + } + + + // Text content changed + @SuppressWarnings("unused") + private void selectionChanged() { + browser.encryptAction.setEnabled(true); + browser.insertLinkAction.setEnabled(true); + String scriptStart = "var selection_text = (window.getSelection()).toString();" + + "var range = (window.getSelection()).getRangeAt(0);" + + "var parent_html = range.commonAncestorContainer.innerHTML;" + + "if (parent_html == undefined) {window.jambi.saveSelectedText(selection_text); return;}" + + "var first_text = range.startContainer.nodeValue.substr(range.startOffset);" + + "var last_text = (range.endContainer.nodeValue).substring(0,range.endOffset);" + + "var start = parent_html.indexOf(first_text);" + + "var end = parent_html.indexOf(last_text,start+1)+last_text.length;" + + "var value = parent_html.substring(start,end);" + + "window.jambi.saveSelectedText(value);" ; + browser.page().mainFrame().evaluateJavaScript(scriptStart); + + } + + public void saveSelectedText(String text) { + boolean enabled = true; + if (text.trim().length() == 0) + enabled=false; + if (text.indexOf("en-tag=\"en-crypt\"") >= 0) + enabled=false; + if (text.indexOf("= 0) + enabled=false; + if (text.indexOf("= 0) + enabled=false; + if (text.indexOf("= 0) + enabled=false; + + browser.encryptAction.setEnabled(enabled); + browser.insertLinkAction.setEnabled(enabled); +// selectedText = text; + } + + // Decrypt clicked text + public void decryptText(String id, String text, String hint) { + EnCrypt crypt = new EnCrypt(); + String plainText = null; + Calendar currentTime = new GregorianCalendar(); + Long l = new Long(currentTime.getTimeInMillis()); + String slot = new String(Long.toString(l)); + + // First, try to decrypt with any keys we already have + for (int i=0; i newTags = tagWindow.getTagList() + .selectedItems(); + for (int i = 0; i < newTags.size(); i++) { + currentTags.add(newTags.get(i).text()); + tagDisplay.append(newTags.get(i).text()); + if (i < newTags.size() - 1) { + tagDisplay.append(Global.tagDelimeter + " "); + } + } + tagEdit.setText(tagDisplay.toString()); + noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags); + } + } + + // Tag line has been modified by typing text + @SuppressWarnings("unused") + private void modifyTagsTyping() { + + String newTags = tagEdit.text(); + List test = tagEdit.tagCompleter.getTagList(); + if (newTags.equalsIgnoreCase(saveTagList)) + return; + + // We know something has changed... + String oldTagArray[] = saveTagList.split(Global.tagDelimeter); + String newTagArray[] = newTags.split(Global.tagDelimeter); + + List newTagList = new ArrayList(); + List oldTagList = new ArrayList(); + + for (int i = 0; i < oldTagArray.length; i++) + if (!oldTagArray[i].trim().equals("")) + oldTagList.add(oldTagArray[i]); + for (int i = 0; i < newTagArray.length; i++) + if (!newTagArray[i].trim().equals("")) + newTagList.add(newTagArray[i]); + + // We now have lists of the new & old. Remove duplicates. If all + // are removed from both then nothing has really changed + for (int i = newTagList.size() - 1; i >= 0; i--) { + String nTag = newTagList.get(i); + for (int j = oldTagList.size() - 1; j >= 0; j--) { + String oTag = oldTagList.get(j); + if (oTag.equalsIgnoreCase(nTag)) { + oldTagList.remove(j); + newTagList.remove(i); + j = -1; + } + } + } + + if (oldTagList.size() != 0 || newTagList.size() != 0) { + currentTags.clear(); + for (int i = 0; i < newTagArray.length; i++) + if (!newTagArray[i].trim().equals("")) + currentTags.add(newTagArray[i].trim()); + + noteSignal.tagsChanged.emit(currentNote.getGuid(), currentTags); + } + + } + + // Tab button was pressed + public void tabPressed() { + if (!insideList) { + String script_start = new String( + "document.execCommand('insertHtml', false, '     ');"); + browser.page().mainFrame().evaluateJavaScript(script_start); + } else + indentClicked(); + } + + public void backtabPressed() { + if (insideList) + outdentClicked(); + } + + public void setInsideList() { + insideList = true; + } + + // The title has been edited + @SuppressWarnings("unused") + private void titleEdited() { + // If we don't have a good note, or if the current title + // matches the old title then we don't need to do anything + if (currentNote == null) + return; + if (currentNote.getTitle().trim().equals(titleLabel.text().trim())) + return; + + // If we have a real change, we need to save it. + noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel.text()); + currentNote.setTitle(titleLabel.text()); + saveNoteTitle = titleLabel.text(); + checkNoteTitle(); + } + + // Set the list of note tags + public void setAllTags(List l) { + allTags = l; + tagEdit.setTagList(l); + } + + // Setter for the current tags + public void setCurrentTags(List s) { + currentTags = s; + } + + // Save the list of notebooks + public void setNotebookList(List n) { + notebookList = n; + loadNotebookList(); + } + + // Load the notebook list and select the current notebook + private void loadNotebookList() { + if (notebookBox.count() != 0) + notebookBox.clear(); + if (notebookList == null) + return; + + for (int i = 0; i < notebookList.size(); i++) { + notebookBox.addItem(notebookList.get(i).getName()); + if (currentNote != null) { + if (currentNote.getNotebookGuid().equals( + notebookList.get(i).getGuid())) { + notebookBox.setCurrentIndex(i); + } + } + } + } + + // Get the contents of the editor + public String getContent() { + return browser.page().currentFrame().toHtml(); + } + + // The note contents have changed + public void contentChanged() { + String content = getContent(); + checkNoteTitle(); + noteSignal.noteChanged.emit(currentNote.getGuid(), content); + + +// noteSignal.noteChanged.emit(currentNote.getGuid(), unicode); + } + + // The notebook selection has changed + @SuppressWarnings("unused") + private void notebookChanged() { + boolean changed = false; + String n = notebookBox.currentText(); + for (int i = 0; i < notebookList.size(); i++) { + if (n.equals(notebookList.get(i).getName())) { + if (!notebookList.get(i).getGuid().equals(currentNote.getNotebookGuid())) { + currentNote.setNotebookGuid(notebookList.get(i).getGuid()); + changed = true; + } + i = notebookList.size(); + } + } + + // If the notebook changed, signal the update + if (changed) + noteSignal.notebookChanged.emit(currentNote.getGuid(), currentNote + .getNotebookGuid()); + } + + // Check the note title + private void checkNoteTitle() { + String text = browser.page().currentFrame().toPlainText(); + if (saveNoteTitle.trim().equals("")) { + int newLine = text.indexOf("\n"); + if (newLine > 0) { + text = text.substring(0, newLine); + if (text.trim().equals("")) + text = "Untitled Note"; + titleLabel.setText(text); + } else { + if (text.length() > 20) + titleLabel.setText(text.substring(0, 20)); + else { + if (text.trim().equals("")) + titleLabel.setText("Untitled Note"); + else + titleLabel.setText(text); + } + } + noteSignal.titleChanged.emit(currentNote.getGuid(), titleLabel + .text()); + } + } + + // Return the note contents so we can email them + public String getContentsToEmail() { + return browser.page().currentFrame().toPlainText().trim(); + /* + * int body = browser.page().currentFrame().toHtml().indexOf(""); + * String temp = browser.page().currentFrame().toHtml(); if (body == -1) + * temp = "Test"; else temp = + * ""+temp.substring(body); return temp; // return + * urlEncode(browser.page().currentFrame().toHtml()); + */ + } + + // Insert an image into the editor + private void insertImage(QMimeData mime) { + logger.log(logger.EXTREME, "Entering insertImage"); + QImage img = (QImage) mime.imageData(); + String script_start = new String( + "document.execCommand('insertHTML', false, '"); + String script_end = new String("');"); + + long now = new Date().getTime(); + String path = Global.getDirectoryPath() + "res/" + + (new Long(now).toString()) + ".jpg"; + + // This block is just a hack to make sure we wait at least 1ms so we + // don't + // have collisions on image names + long i = new Date().getTime(); + while (now == i) + i = new Date().getTime(); + + // Open the file & write the data + QFile tfile = new QFile(path); + tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly)); + img.save(tfile); + tfile.close(); + + Resource newRes = createResource(QUrl.fromLocalFile(path).toString(), 0, "image/jpeg", false); + if (newRes == null) + return; + currentNote.getResources().add(newRes); + + // do the actual insert into the note + StringBuffer buffer = new StringBuffer(100); + buffer.append(""); + browser.page().mainFrame().evaluateJavaScript( + script_start + buffer + script_end); + + return; + } + + // Handle URLs that are trying to be pasted + public void handleUrls(QMimeData mime) { + logger.log(logger.EXTREME, "Starting handleUrls"); + FileNameMap fileNameMap = URLConnection.getFileNameMap(); + + List urlList = mime.urls(); + String url = new String(); + String script_start = new String( + "document.execCommand('createLink', false, '"); + String script_end = new String("');"); + + for (int i = 0; i < urlList.size(); i++) { + url = urlList.get(i).toString(); + // Find out what type of file we have + String mimeType = fileNameMap.getContentTypeFor(url); + + // If null returned, we need to guess at the file type + if (mimeType == null) + mimeType = "application/" + + url.substring(url.lastIndexOf(".") + 1); + + // Check if we have an image or some other type of file + if (url.substring(0, 5).equalsIgnoreCase("file:") + && mimeType.substring(0, 5).equalsIgnoreCase("image")) { + handleLocalImageURLPaste(mime, mimeType); + return; + } + String[] type = mimeType.split("/"); + boolean valid = validAttachment(type[1]); + boolean smallEnough = checkFileAttachmentSize(url); + if (smallEnough && valid + && url.substring(0, 5).equalsIgnoreCase("file:") + && !mimeType.substring(0, 5).equalsIgnoreCase("image")) { + handleLocalAttachment(mime, mimeType); + return; + } + browser.page().mainFrame().evaluateJavaScript( + script_start + url + script_end); + } + return; + } + + // If a URL being pasted is an image URL, then attach the image + private void handleLocalImageURLPaste(QMimeData mime, String mimeType) { + List urlList = mime.urls(); + String url = new String(); + String script_start_image = new String( + "document.execCommand('insertHtml', false, '"); + String script_end = new String("');"); + StringBuffer buffer; + + // Copy the image over into the resource directory and create a new resource + // record for each url pasted + for (int i = 0; i < urlList.size(); i++) { + url = urlList.get(i).toString(); + + Resource newRes = createResource(url, i, mimeType, false); + if (newRes == null) + return; + currentNote.getResources().add(newRes); + buffer = new StringBuffer(100); + + // Open the file & write the data + String fileName = Global.getDirectoryPath()+"res/"+newRes.getGuid(); + QFile tfile = new QFile(fileName); + tfile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly)); + tfile.write(newRes.getData().getBody()); + tfile.close(); + fileName = fileName.replace('\\', '/'); + buffer.append(script_start_image); + buffer.append(""); + buffer.append(script_end); + browser.page().mainFrame().evaluateJavaScript(buffer.toString()); + } + return; + } + + + // If a URL being pasted is a local file URL, then attach the file + private void handleLocalAttachment(QMimeData mime, String mimeType) { + logger.log(logger.EXTREME, "Attaching local file"); + List urlList = mime.urls(); + String script_start = new String( + "document.execCommand('insertHtml', false, '"); + String script_end = new String("');"); + StringBuffer buffer; + + for (int i = 0; i < urlList.size(); i++) { + buffer = new StringBuffer(100); + String url = urlList.get(i).toString(); + + // Start building the HTML + String[] type = mimeType.split("/"); + String icon = findIcon(type[1]); + if (icon.equals("attachment.png")) + icon = findIcon(type[0]); + if (icon.equals("attachment.png")) + icon = findIcon(url.substring(url.lastIndexOf(".")+1)); + StringBuffer imageBuffer = new StringBuffer(); + String whichOS = System.getProperty("os.name"); + if (whichOS.contains("Windows")) + imageBuffer.append("file:///" + Global.getDirectoryPath() + + "images/" + icon); + else + imageBuffer.append("file://" + Global.getDirectoryPath() + + "images/" + icon); + // Fix stupid Windows file separation characters + if (whichOS.contains("Windows")) { + for (int z = imageBuffer.indexOf("\\"); z > 0; z = imageBuffer + .indexOf("\\")) { + int w = imageBuffer.indexOf("\\"); + imageBuffer.replace(w, w + 1, "/"); + } + + } + logger.log(logger.EXTREME, "Creating resource "); + Resource newRes = createResource(url, i, mimeType, true); + if (newRes == null) + return; + logger.log(logger.EXTREME, "New resource size: " +newRes.getData().getSize()); + currentNote.getResources().add(newRes); + + String fileName = newRes.getGuid() + Global.attachmentNameDelimeter+newRes.getAttributes().getFileName(); + // If we have a PDF, we need to setup the preview. + if (icon.equalsIgnoreCase("pdf.png") && Global.pdfPreview()) { + logger.log(logger.EXTREME, "Setting up PDF preview"); + if (newRes.getAttributes() != null && + newRes.getAttributes().getFileName() != null && + !newRes.getAttributes().getFileName().trim().equals("")) + fileName = newRes.getGuid()+Global.attachmentNameDelimeter+ + newRes.getAttributes().getFileName(); + else + fileName = newRes.getGuid()+".pdf"; + QFile file = new QFile(Global.getDirectoryPath() +"res/"+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(newRes.getGuid(), true); + QByteArray binData = new QByteArray(newRes.getData().getBody()); +// resBinary = null; + out.writeBytes(binData.toByteArray()); + file.close(); + + PDFPreview pdfPreview = new PDFPreview(); + if (pdfPreview.setupPreview(Global.currentDir+"res/"+fileName, "pdf",0)); + imageBuffer = new StringBuffer(file.fileName()+".png"); + } + + logger.log(logger.EXTREME, "Generating link tags"); + buffer.append(""); + buffer.append(""); + buffer.append(""); + browser.page().mainFrame().evaluateJavaScript( + script_start + buffer.toString() + script_end); + } + return; + } + private Resource createResource(String url, int sequence, String mime, boolean attachment) { + logger.log(logger.EXTREME, "Inside create resource"); + QFile resourceFile; + url = new QUrl(url).toLocalFile(); + url = url.replace("/", File.separator); + resourceFile = new QFile(url); + resourceFile.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly)); + byte[] fileData = resourceFile.readAll().toByteArray(); + resourceFile.close(); + if (fileData.length == 0) + return null; + MessageDigest md; + try { + md = MessageDigest.getInstance("MD5"); + md.update(fileData); + byte[] hash = md.digest(); + + Resource r = new Resource(); + Calendar time = new GregorianCalendar(); + long prevTime = time.getTimeInMillis(); + while (prevTime == time.getTimeInMillis()) { + time = new GregorianCalendar(); + } + r.setGuid(time.getTimeInMillis()+new Integer(sequence).toString()); + r.setNoteGuid(currentNote.getGuid()); + r.setMime(mime); + r.setActive(true); + r.setUpdateSequenceNum(0); + r.setWidth((short) 0); + r.setHeight((short) 0); + r.setDuration((short) 0); + + Data d = new Data(); + d.setBody(fileData); + d.setBodyIsSet(true); + d.setBodyHash(hash); + d.setBodyHashIsSet(true); + r.setData(d); + d.setSize(fileData.length); + + int fileNamePos = url.lastIndexOf(File.separator); + if (fileNamePos == -1) + fileNamePos = url.lastIndexOf("/"); + String fileName = url.substring(fileNamePos+1); + ResourceAttributes a = new ResourceAttributes(); + a.setAltitude(0); + a.setAltitudeIsSet(false); + a.setLongitude(0); + a.setLongitudeIsSet(false); + a.setLatitude(0); + a.setLatitudeIsSet(false); + a.setCameraMake(""); + a.setCameraMakeIsSet(false); + a.setCameraModel(""); + a.setCameraModelIsSet(false); + a.setAttachment(attachment); + a.setAttachmentIsSet(true); + a.setClientWillIndex(false); + a.setClientWillIndexIsSet(true); + a.setRecoType(""); + a.setRecoTypeIsSet(false); + a.setSourceURL(url); + a.setSourceURLIsSet(true); + a.setTimestamp(0); + a.setTimestampIsSet(false); + a.setFileName(fileName); + a.setFileNameIsSet(true); + r.setAttributes(a); + + conn.getNoteTable().noteResourceTable.saveNoteResource(r, true); + return r; + } catch (NoSuchAlgorithmException e1) { + e1.printStackTrace(); + } + return null; + } + + + // find the appropriate icon for an attachment + private String findIcon(String appl) { + appl = appl.toLowerCase(); + File f = new File(Global.getDirectoryPath()+"images"+File.separator +appl +".png"); + if (f.exists()) + return appl+".png"; + return "attachment.png"; + } + + // Check if the account supports this type of attachment + private boolean validAttachment(String type) { + if (Global.isPremium()) + return true; + if (type.equalsIgnoreCase("JPG")) + return true; + if (type.equalsIgnoreCase("PNG")) + return true; + if (type.equalsIgnoreCase("GIF")) + return true; + if (type.equalsIgnoreCase("MP3")) + return true; + if (type.equalsIgnoreCase("WAV")) + return true; + if (type.equalsIgnoreCase("AMR")) + return true; + if (type.equalsIgnoreCase("PDF")) + return true; + String error = "Non-premium accounts can only attach JPG, PNG, GIF, MP3, WAV, AMR, or PDF files."; + QMessageBox.information(this, "Non-Premium Account", error); + + return false; + } + + // Check the file attachment to be sure it isn't over 25 mb + private boolean checkFileAttachmentSize(String url) { + String fileName = url.substring(8); + QFile resourceFile = new QFile(fileName); + resourceFile.open(new QIODevice.OpenMode( + QIODevice.OpenModeFlag.ReadOnly)); + long size = resourceFile.size(); + resourceFile.close(); + size = size / 1024 / 1024; + if (size < 50 && Global.isPremium()) + return true; + if (size < 25) + return true; + + String error = "A file attachment may not exceed 25MB."; + QMessageBox.information(this, "Attachment Size", error); + return false; + } + + + @SuppressWarnings("unused") + private void createdChanged() { + QDateTime dt = new QDateTime(); + dt.setDate(createdDate.date()); + dt.setTime(createdTime.time()); + noteSignal.createdDateChanged.emit(currentNote.getGuid(), dt); + + } + + @SuppressWarnings("unused") + private void alteredChanged() { + QDateTime dt = new QDateTime(); + dt.setDate(alteredDate.date()); + dt.setTime(alteredTime.time()); + noteSignal.alteredDateChanged.emit(currentNote.getGuid(), dt); + } + + @SuppressWarnings("unused") + private void subjectDateTimeChanged() { + QDateTime dt = new QDateTime(); + dt.setDate(subjectDate.date()); + dt.setTime(subjectTime.time()); + noteSignal.subjectDateChanged.emit(currentNote.getGuid(), dt); + + } + + @SuppressWarnings("unused") + private void sourceUrlChanged() { + noteSignal.sourceUrlChanged.emit(currentNote.getGuid(), urlText.text()); + } + + @SuppressWarnings("unused") + private void authorChanged() { + noteSignal.authorChanged.emit(currentNote.getGuid(), authorText.text()); + } + + // ************************************************************ + // * User chose to save an attachment. Pares out the request * + // * into a guid & file. Save the result. * + // ************************************************************ + public void downloadAttachment(QNetworkRequest request) { + String guid; + QFileDialog fd = new QFileDialog(this); + fd.setFileMode(FileMode.AnyFile); + fd.setConfirmOverwrite(true); + fd.setWindowTitle("Save File"); + fd.setAcceptMode(AcceptMode.AcceptSave); + fd.setDirectory(System.getProperty("user.home")); + String name = request.url().toString(); + + int pos = name.lastIndexOf(Global.attachmentNameDelimeter); + if (pos > -1) { + guid = name.substring(0, pos).replace("nnres://", ""); + name = name.substring(pos +Global.attachmentNameDelimeter.length()); + fd.selectFile(name); + pos = name.lastIndexOf('.'); + if (pos > -1) { + String mimeType = "(*." + name.substring(pos + 1) + + ");; All Files (*)"; + fd.setFilter(tr(mimeType)); + } + } else { + guid = name; + } + guid = guid.replace("nnres://", "").replace(Global.currentDir.replace("\\","/")+"res/", ""); + pos = guid.lastIndexOf('.'); + if (pos > 0) + guid = guid.substring(0,pos); + if (fd.exec() != 0 && fd.selectedFiles().size() > 0) { + name = name.replace('\\', '/'); + Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true); + QFile saveFile = new QFile(fd.selectedFiles().get(0)); + QFile.OpenMode mode = new QFile.OpenMode(); + mode.set(QFile.OpenModeFlag.WriteOnly); + saveFile.open(mode); + QDataStream saveOut = new QDataStream(saveFile); + QByteArray binData = new QByteArray(resBinary.getData().getBody()); + saveOut.writeBytes(binData.toByteArray()); + saveFile.close(); + + } + } + + + // ************************************************************ + // * User chose to save an attachment. Pares out the request * + // * into a guid & file. Save the result. --- DONE FROM downloadAttachment now!!!!! + // ************************************************************ + public void downloadImage(QNetworkRequest request) { + QFileDialog fd = new QFileDialog(this); + fd.setFileMode(FileMode.AnyFile); + fd.setConfirmOverwrite(true); + fd.setWindowTitle("Save File"); + fd.setAcceptMode(AcceptMode.AcceptSave); + fd.setDirectory(System.getProperty("user.home")); + String name = request.url().toString(); + name = name.replace("nnres://", ""); + String dPath = Global.getDirectoryPath() + "res/"; + dPath = dPath.replace('\\', '/'); + name = name.replace(dPath, ""); + int pos = name.lastIndexOf('.'); + String guid = name; + if (pos > -1) { + String mimeType = "(*." + name.substring(pos + 1) + + ");; All Files (*)"; + fd.setFilter(tr(mimeType)); + guid = guid.substring(0,pos); + } + pos = name.lastIndexOf(Global.attachmentNameDelimeter); + if (pos > -1) { + guid = name.substring(0, pos); + fd.selectFile(name.substring(pos+Global.attachmentNameDelimeter.length())); + } + if (fd.exec() != 0 && fd.selectedFiles().size() > 0) { + Resource resBinary = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true); + String fileName = fd.selectedFiles().get(0); + QFile saveFile = new QFile(fileName); + QFile.OpenMode mode = new QFile.OpenMode(); + mode.set(QFile.OpenModeFlag.WriteOnly); + saveFile.open(mode); + QDataStream saveOut = new QDataStream(saveFile); + QByteArray binData = new QByteArray(resBinary.getData().getBody()); + saveOut.writeBytes(binData.toByteArray()); + saveFile.close(); + } + } + + + // ************************************************************* + // * decrypt any hidden text. We could do an XML parse, but + // * it is quicker here just to scan for an " +plainText+" "; + } + + String html = browser.page().mainFrame().toHtml(); + String text = html; + int imagePos = html.indexOf("0; ) { + // Find the end tag + endPos = text.indexOf(">", imagePos); + String tag = text.substring(imagePos-1,endPos); + if (tag.indexOf("id=\""+id+"\"") > -1) { + text = text.substring(0,imagePos) +plainText+text.substring(endPos+1); + + browser.setContent(new QByteArray(text)); + contentChanged(); + } + imagePos = text.indexOf("=0;) { + endPos = text.indexOf(">", startPos+1); + String segment = text.substring(startPos, endPos); + if (segment.indexOf("en-tag") > -1) { + String newSegment = segment; + + int guidStartPos = segment.indexOf("guid=\""); + int guidEndPos = segment.indexOf("\"", guidStartPos+7); + String guid = segment.substring(guidStartPos+6,guidEndPos); + + Calendar currentTime = new GregorianCalendar(); + Long l = new Long(currentTime.getTimeInMillis()); + long prevTime = l; + while (l==prevTime) { + currentTime = new GregorianCalendar(); + l= new Long(currentTime.getTimeInMillis()); + } + + Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true); + if (r==null) + return ""; + String randint = new String(Long.toString(l)); + String extension = null; + if (r.getMime()!= null) { + extension = r.getMime().toLowerCase(); + if (extension.indexOf("/")>-1) + extension = extension.substring(extension.indexOf("/")+1); + } + String newFile = randint; + if (r.getAttributes().getFileName() != null && r.getAttributes().getFileName() != "") + if (!locTag.startsWith("src")) + newFile = newFile+Global.attachmentNameDelimeter+r.getAttributes().getFileName(); + r.setNoteGuid(currentNote.getGuid()); + + r.setGuid(randint); + conn.getNoteTable().noteResourceTable.saveNoteResource(r, true); + QFile f = new QFile(Global.getDirectoryPath() +"res/" +newFile); + QByteArray bin = new QByteArray(r.getData().getBody()); + f.open(QFile.OpenModeFlag.WriteOnly); + f.write(bin); + f.close(); + newSegment = newSegment.replace("guid=\""+guid, "guid=\""+randint); + currentNote.getResources().add(r); + + int startSrcPos = newSegment.indexOf(locTag); + int endSrcPos = newSegment.indexOf("\"",startSrcPos+locTag.length()+1); + String source; + if (locTag.startsWith("src")) { + source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos); + newSegment = newSegment.replace(source, Global.getDirectoryPath().replace("\\", "/")+"res/"+newFile); + } else { + source = newSegment.substring(startSrcPos+locTag.length(),endSrcPos); + newSegment = newSegment.replace(source, newFile); + } + + text = text.substring(0,startPos) + newSegment + text.substring(endPos); + } + startPos = text.indexOf(type, startPos+1); + } + return text; + } + + + public void nextPage(String file) { + logger.log(logger.EXTREME, "Starting nextPage()"); + + Integer pageNumber; + if (previewPageList.containsKey(file)) + pageNumber = previewPageList.get(file)+1; + else + pageNumber = 2; + previewPageList.remove(file); + previewPageList.put(file, pageNumber); + PDFPreview pdfPreview = new PDFPreview(); + boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber); + if (goodPreview) { + +// String html = getContent(); + QWebSettings.setMaximumPagesInCache(0); + QWebSettings.setObjectCacheCapacities(0, 0, 0); +// browser.setContent(new QByteArray()); + browser.setHtml(browser.page().mainFrame().toHtml()); + browser.reload(); +// browser.setContent(new QByteArray(html)); +// browser.triggerPageAction(WebAction.Reload); +// pdfMouseOver(selectedFile); + } + } + + public void previousPage(String file) { + logger.log(logger.EXTREME, "Starting previousPage()"); + + Integer pageNumber; + if (previewPageList.containsKey(file)) + pageNumber = previewPageList.get(file)-1; + else + pageNumber = 1; + previewPageList.remove(file); + previewPageList.put(file, pageNumber); + PDFPreview pdfPreview = new PDFPreview(); + boolean goodPreview = pdfPreview.setupPreview(file, "pdf", pageNumber); + if (goodPreview) { + +// String html = getContent(); + QWebSettings.setMaximumPagesInCache(0); + QWebSettings.setObjectCacheCapacities(0, 0, 0); + browser.setHtml(browser.page().mainFrame().toHtml()); + browser.reload(); +// browser.setContent(new QByteArray(html)); +// browser.triggerPageAction(WebAction.Reload); + } + } + +/* public void pdfMouseOver(String name) { + int pageNumber; + if (previewPageList.containsKey(selectedFile)) + pageNumber = previewPageList.get(selectedFile)+1; + else + pageNumber = 1; + + if (pageNumber <= 1) + browser.previousPageAction.setEnabled(false); + else + browser.previousPageAction.setEnabled(true); + + PDFPreview pdf = new PDFPreview(); + int totalPages = pdf.getPageCount(name); + if (previewPageList.containsKey(selectedFile)) + pageNumber = previewPageList.get(selectedFile)+1; + else + pageNumber = 1; + if (totalPages > pageNumber) + browser.nextPageAction.setEnabled(true); + else + browser.nextPageAction.setEnabled(false); + } + + + public void pdfMouseOut() { +// browser.nextPageAction.setVisible(false); +// browser.previousPageAction.setVisible(false); + } +*/ +} \ No newline at end of file diff --git a/src/cx/fbn/nevernote/gui/ColorMenu.java b/src/cx/fbn/nevernote/gui/ColorMenu.java new file mode 100644 index 0000000..91ed0a0 --- /dev/null +++ b/src/cx/fbn/nevernote/gui/ColorMenu.java @@ -0,0 +1,72 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.gui; + +import java.util.List; + +import com.trolltech.qt.core.QSize; +import com.trolltech.qt.gui.QAction; +import com.trolltech.qt.gui.QColor; +import com.trolltech.qt.gui.QIcon; +import com.trolltech.qt.gui.QMenu; +import com.trolltech.qt.gui.QPixmap; +import com.trolltech.qt.gui.QWidget; + +public class ColorMenu extends Object { + + private final QMenu menu; + QWidget parent; + QColor currentColor; + + public ColorMenu(QWidget b) { + menu = new QMenu(); + parent = b; + populateList(); + currentColor = new QColor("black"); + } + + + private void populateList() { + List colorNames = QColor.colorNames(); + for(int i=0; i table; + + public ContainsAttributeFilterTable() { + table = new ArrayList(); + table.add(new AttributeFilter("Images")); + table.add(new AttributeFilter("Audio")); + table.add(new AttributeFilter("Ink")); + table.add(new AttributeFilter("Encrypted Text")); + table.add(new AttributeFilter("To-Do Items")); + table.add(new AttributeFilter("Unfinished to-do items")); + table.add(new AttributeFilter("Finished to-do items")); + table.add(new AttributeFilter("Attachment")); + table.add(new AttributeFilter("PDF")); + + + + + + } + + public void reset() { + for (int i=0; i=0 ; pos=content.indexOf("", pos); + String segment = content.substring(pos, endPos); + boolean currentState = false; + if (segment.indexOf("checked=\"true\"") > -1) + currentState = true; + if (currentState == checked) + return true; + } + + + return false; + + } + + private boolean checkText(String content, String text) { + if (content.indexOf(text) > -1) + return true; + else + return false; + } + // Get the name of a particular attribute check + public String getName(int i) { + return table.get(i).getName(); + } +} diff --git a/src/cx/fbn/nevernote/gui/ContentView.java b/src/cx/fbn/nevernote/gui/ContentView.java new file mode 100644 index 0000000..2bba156 --- /dev/null +++ b/src/cx/fbn/nevernote/gui/ContentView.java @@ -0,0 +1,342 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ +package cx.fbn.nevernote.gui; + +import com.trolltech.qt.core.QEvent; +import com.trolltech.qt.core.QMimeData; +import com.trolltech.qt.core.Qt; +import com.trolltech.qt.gui.QAction; +import com.trolltech.qt.gui.QContextMenuEvent; +import com.trolltech.qt.gui.QDropEvent; +import com.trolltech.qt.gui.QKeyEvent; +import com.trolltech.qt.gui.QKeySequence; +import com.trolltech.qt.gui.QMenu; +import com.trolltech.qt.gui.QShortcut; +import com.trolltech.qt.gui.QKeySequence.StandardKey; +import com.trolltech.qt.network.QNetworkRequest; +import com.trolltech.qt.webkit.QWebPage; +import com.trolltech.qt.webkit.QWebView; + +import cx.fbn.nevernote.Global; + +public class ContentView extends QWebView { + + BrowserWindow parent; + QMenu contextMenu = new QMenu(this); + QMenu tableMenu = new QMenu(this); + QAction cutAction; + QShortcut cutShortcut; + QAction copyAction; + QShortcut copyShortcut; + QAction pasteAction; + QShortcut pasteShortcut; + QAction pasteWithoutFormatAction; + QShortcut pasteWithoutFormatShortcut; + QAction todoAction; + QShortcut todoShortcut; + QAction encryptAction; + QShortcut encryptShortcut; + QAction downloadAttachment; + QShortcut downloadAttachmentShortcut; + QAction downloadImage; + QShortcut downloadImageShortcut; + QAction rotateImageRight; + QShortcut rotateImageRightShortcut; + QAction rotateImageLeft; + QShortcut rotateImageLeftShortcut; + QAction insertLinkAction; + QShortcut insertLinkShortcut; + QAction insertTableAction; + QShortcut insertTableShortcut; + QAction insertTableRowAction; + QShortcut insertTableRowShortcut; + QAction deleteTableRowAction; + QShortcut deleteTableRowShortcut; + QAction openAction; + + QAction redBackgroundColor; + + QShortcut insertDateTimeShortcut; + + Signal1 downloadAttachmentRequested; + Signal1 downloadImageRequested; + + public ContentView(BrowserWindow p) { + parent=p; + contextMenu = new QMenu(this); + + openAction = new QAction(tr("Open"), this); + openAction.setText(tr("Open")); + contextMenu.addAction(openAction); + openAction.triggered.connect(parent, "openFile()"); + + cutAction = new QAction(tr("Cut"), this); + cutAction.triggered.connect(parent, "cutClicked()"); + contextMenu.addAction(cutAction); + contextMenu.insertSeparator(cutAction); + setupShortcut(cutAction, "Edit_Cut"); + cutShortcut = new QShortcut(this); + cutShortcut.activated.connect(parent, "cutClicked()"); + setupShortcut(cutShortcut, "Edit_Cut"); + + copyAction = new QAction(tr("Copy"), this); + copyAction.triggered.connect(parent, "copyClicked()"); + contextMenu.addAction(copyAction); + setupShortcut(copyAction, "Edit_Copy"); + copyShortcut = new QShortcut(this); + copyShortcut.activated.connect(parent, "copyClicked()"); + setupShortcut(copyShortcut, "Edit_Copy"); + + pasteAction = pageAction(QWebPage.WebAction.Paste); + pasteAction.disconnect(); + pasteAction.triggered.connect(parent, "pasteClicked()"); + + contextMenu.addAction(pasteAction); + setupShortcut(pasteAction, "Edit_Paste"); + pasteShortcut = new QShortcut(this); + pasteShortcut.activated.connect(parent, "pasteClicked()"); + setupShortcut(pasteShortcut, "Edit_Paste"); + + pasteWithoutFormatAction = new QAction(tr("Paste Without Formatting"), this); + pasteWithoutFormatAction.triggered.connect(parent, "pasteWithoutFormattingClicked()"); + contextMenu.addAction(pasteWithoutFormatAction); + setupShortcut(pasteWithoutFormatAction, "Edit_Paste_Without_Formatting"); + pasteWithoutFormatShortcut = new QShortcut(this); + pasteWithoutFormatShortcut.activated.connect(parent, "pasteWithoutFormattingClicked()"); + setupShortcut(pasteWithoutFormatShortcut, "Edit_Paste_Without_Formatting"); + + contextMenu.addSeparator(); + QMenu colorMenu = new QMenu(tr("Background Color")); + contextMenu.addMenu(colorMenu); + + colorMenu.addAction(setupColorMenuOption("White")); + colorMenu.addAction(setupColorMenuOption("Red")); + colorMenu.addAction(setupColorMenuOption("Blue")); + colorMenu.addAction(setupColorMenuOption("Green")); + colorMenu.addAction(setupColorMenuOption("Yellow")); + colorMenu.addAction(setupColorMenuOption("Black")); + colorMenu.addAction(setupColorMenuOption("Grey")); + colorMenu.addAction(setupColorMenuOption("Purple")); + colorMenu.addAction(setupColorMenuOption("Brown")); + colorMenu.addAction(setupColorMenuOption("Orange")); + colorMenu.addAction(setupColorMenuOption("Powder Blue")); + + + contextMenu.addSeparator(); + todoAction = new QAction(tr("To-do"), this); + todoAction.triggered.connect(parent, "todoClicked()"); + contextMenu.addAction(todoAction); + setupShortcut(todoAction, "Edit_Insert_Todo"); + contextMenu.insertSeparator(todoAction); + todoShortcut = new QShortcut(this); + todoShortcut.activated.connect(parent, "todoClicked()"); + setupShortcut(todoShortcut, "Edit_Insert_Todo"); + + encryptAction = new QAction(tr("Encrypt Selected Text"), this); + encryptAction.triggered.connect(parent, "encryptText()"); + contextMenu.addAction(encryptAction); + contextMenu.insertSeparator(encryptAction); + setupShortcut(encryptAction, "Edit_Encrypt_Text"); + encryptAction.setEnabled(false); + encryptShortcut = new QShortcut(this); + encryptShortcut.activated.connect(parent, "encryptText()"); + setupShortcut(encryptShortcut, "Edit_Encrypt_Text"); + + insertLinkAction = new QAction(tr("Insert Hyperlink"), this); + insertLinkAction.triggered.connect(parent, "insertLink()"); + setupShortcut(insertLinkAction, "Edit_Insert_Hyperlink"); + contextMenu.addAction(insertLinkAction); + insertLinkAction.setEnabled(false); + insertLinkShortcut = new QShortcut(this); + setupShortcut(insertLinkShortcut, "Edit_Insert_Hyperlink"); + insertLinkShortcut.activated.connect(parent, "insertLink()"); + + contextMenu.addMenu(tableMenu); + tableMenu.setTitle("Table"); + insertTableAction = new QAction(tr("Insert Table"), this); + insertTableAction.triggered.connect(parent, "insertTable()"); + setupShortcut(insertTableAction, "Edit_Insert_Table"); + tableMenu.addAction(insertTableAction); + insertTableShortcut = new QShortcut(this); + setupShortcut(insertTableShortcut, "Edit_Insert_Table"); + insertTableShortcut.activated.connect(parent, "insertTable()"); + + insertTableRowAction = new QAction(tr("Insert Row"), this); + insertTableRowAction.triggered.connect(parent, "insertTableRow()"); + setupShortcut(insertTableRowAction, "Edit_Insert_Table_Row"); + tableMenu.addAction(insertTableRowAction); + insertTableRowShortcut = new QShortcut(this); + setupShortcut(insertTableRowShortcut, "Edit_Insert_Table_Row"); + insertTableRowShortcut.activated.connect(parent, "insertTableRow()"); + + deleteTableRowAction = new QAction(tr("Delete Row"), this); + deleteTableRowAction.triggered.connect(parent, "deleteTableRow()"); + setupShortcut(deleteTableRowAction, "Edit_Delete_Table_Row"); + tableMenu.addAction(deleteTableRowAction); + deleteTableRowShortcut = new QShortcut(this); + setupShortcut(deleteTableRowShortcut, "Edit_Delete_Table_Row"); + deleteTableRowShortcut.activated.connect(parent, "deleteTableRow()"); + + insertDateTimeShortcut = new QShortcut(this); + insertDateTimeShortcut.activated.connect(parent, "insertDateTime()"); + setupShortcut(insertDateTimeShortcut, "Insert_DateTime"); + + QMenu imageMenu = new QMenu(); + imageMenu.setTitle("Image"); + contextMenu.addMenu(imageMenu); + downloadImage = pageAction(QWebPage.WebAction.DownloadImageToDisk); + downloadImage.setText(tr("Save Image")); + imageMenu.addAction(downloadImage); +// contextMenu.insertSeparator(downloadImage); +// page().downloadRequested.connect(this, "downloadImage(QNetworkRequest)"); + downloadImageRequested = new Signal1(); + + rotateImageRight = new QAction(tr("Rotate Right"), this); + imageMenu.addAction(rotateImageRight); + rotateImageRight.triggered.connect(parent, "rotateImageRight()"); + rotateImageRightShortcut = new QShortcut(this); + setupShortcut(rotateImageRightShortcut, "Edit_Image_Rotate_Right"); + rotateImageRightShortcut.activated.connect(parent, "rotateImageRight()"); + + rotateImageLeft = new QAction(tr("Rotate Left"), this); + imageMenu.addAction(rotateImageLeft); + rotateImageLeft.triggered.connect(parent, "rotateImageLeft()"); + rotateImageLeftShortcut = new QShortcut(this); + setupShortcut(rotateImageLeftShortcut, "Edit_Image_Rotate_Left"); + rotateImageLeftShortcut.activated.connect(parent, "rotateImageLeft()"); + + downloadAttachment = pageAction(QWebPage.WebAction.DownloadLinkToDisk); + downloadAttachment.setText(tr("Save Attachment")); + contextMenu.addAction(downloadAttachment); + page().downloadRequested.connect(this, "downloadAttachment(QNetworkRequest)"); + downloadAttachmentRequested = new Signal1(); + + } + + private void setupShortcut(QAction action, String text) { + if (!Global.shortcutKeys.containsAction(text)) + return; + action.setShortcut(Global.shortcutKeys.getShortcut(text)); + } + + private void setupShortcut(QShortcut action, String text) { + if (!Global.shortcutKeys.containsAction(text)) + return; + action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text))); + } + + private QAction setupColorMenuOption(String color) { + QAction backgroundColor = new QAction(tr(color), this); + color = color.replace(" ", ""); + backgroundColor.triggered.connect(this, "setBackground"+color+"()"); + return backgroundColor; + } + + @Override + public boolean event(QEvent event) + { + if (event.type().equals(QEvent.Type.KeyPress)) { + QKeyEvent ke = (QKeyEvent) event; + if (ke.key() == Qt.Key.Key_Tab.value()) { + parent.tabPressed(); + return true; + } + if (ke.key() == Qt.Key.Key_Backtab.value()) { + parent.backtabPressed(); + return true; + } + } + return super.event(event); + } + + + @Override + public void keyPressEvent(QKeyEvent e) { + + // This is done because if we set the content editable, the scroll keys are + // ignored by webkit. + if (e.key() == Qt.Key.Key_PageUp.value() || e.key() == Qt.Key.Key_PageDown.value()) { + int bottom = page().mainFrame().geometry().bottom(); + int top = page().mainFrame().geometry().top(); + int scrollValue = top-bottom; + if (e.key() == Qt.Key.Key_PageDown.value()) + scrollValue = -1*scrollValue; + page().mainFrame().scroll(0, scrollValue); + } + + // This is done to allow proper pasting of resources, otherwise it messes up multiple pastes + if (e.matches(StandardKey.Paste)) { + parent.pasteClicked(); + e.accept(); + return; + } + super.keyPressEvent(e); + } + +// public void downloadImage(QNetworkRequest req) { +// System.out.println(req.url().toString()); +// downloadImageRequested.emit(req); +// } + public void downloadAttachment(QNetworkRequest req) { + downloadAttachmentRequested.emit(req); + } + + + @Override + public void dropEvent(QDropEvent e) { + setFocus(); + QMimeData mime = e.mimeData(); + parent.handleUrls(mime); + parent.contentChanged(); +// triggerPageAction(WebAction.Reload); + } + + @Override + public void contextMenuEvent(QContextMenuEvent event) { + if (event != null) + contextMenu.exec(event.globalPos()); + } + + + + @SuppressWarnings("unused") + private void setBackgroundWhite() {parent.setBackgroundColor("white");} + @SuppressWarnings("unused") + private void setBackgroundRed() {parent.setBackgroundColor("red");} + @SuppressWarnings("unused") + private void setBackgroundBlue() {parent.setBackgroundColor("blue");} + @SuppressWarnings("unused") + private void setBackgroundGreen() {parent.setBackgroundColor("green");} + @SuppressWarnings("unused") + private void setBackgroundYellow() {parent.setBackgroundColor("yellow");} + @SuppressWarnings("unused") + private void setBackgroundBlack() {parent.setBackgroundColor("black");} + @SuppressWarnings("unused") + private void setBackgroundPurple() {parent.setBackgroundColor("purple");} + @SuppressWarnings("unused") + private void setBackgroundBrown() {parent.setBackgroundColor("brown");} + @SuppressWarnings("unused") + private void setBackgroundGrey() {parent.setBackgroundColor("grey");} + @SuppressWarnings("unused") + private void setBackgroundOrange() {parent.setBackgroundColor("orange");} + @SuppressWarnings("unused") + private void setBackgroundPowderBlue() {parent.setBackgroundColor("powderblue");} + + +} diff --git a/src/cx/fbn/nevernote/gui/DateAttributeFilterTable.class b/src/cx/fbn/nevernote/gui/DateAttributeFilterTable.class new file mode 100644 index 0000000000000000000000000000000000000000..3e2dd136e3b82b85225d94ddfaddf188d0066b62 GIT binary patch literal 5589 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 table; + boolean checkSince; + boolean checkCreated; + + public void setSince() { + checkSince = true; + } + + public void setBefore() { + checkSince = false; + } + + public void setCreated() { + checkCreated = true; + } + + public void setUpdated() { + checkCreated = false; + } + + public DateAttributeFilterTable() { + checkSince = true; + checkCreated = true; + table = new ArrayList(); + table.add(new AttributeFilter("Today")); + table.add(new AttributeFilter("Yesterday")); + table.add(new AttributeFilter("This Week")); + table.add(new AttributeFilter("Last Week")); + table.add(new AttributeFilter("This Month")); + table.add(new AttributeFilter("Last Month")); + table.add(new AttributeFilter("This Year")); + table.add(new AttributeFilter("Last Year")); + } + + public void reset() { + for (int i=0; i 0; + } + + // Check if it was within the last two days + private boolean checkYesterday(QDateTime noteDate, QDateTime current) { + if (checkSince) + return noteDate.daysTo(current) <= 1; + else + return noteDate.daysTo(current) > 1; + } + + + // Check if it was within the last two days + private boolean checkWeek(QDateTime noteDate, QDateTime current) { + if (checkSince) + return noteDate.daysTo(current) <= 7; + else + return noteDate.daysTo(current) > 7; + } + + + + + // Check if it was within the last two weeks + private boolean checkLastWeek(QDateTime noteDate, QDateTime current) { + if (checkSince) + return noteDate.daysTo(current) <= 14; + else + return noteDate.daysTo(current) > 14; + } + + + + // Check if it was within the last month + private boolean checkMonth(QDateTime noteDate, QDateTime current) { + if (checkSince) + return noteDate.date().month() - current.date().month() == 0; + else + return noteDate.date().month() - current.date().month() != 0; + } + + + + + // Check if it was within the last two months + private boolean checkLastMonth(QDateTime noteDate, QDateTime current) { + int ny = noteDate.date().year(); + int cy = current.date().year(); + int nm = noteDate.date().month(); + int cm = current.date().month(); + + while (cy-ny >= 1) { + cm = cm+12; + cy--; + } + if (checkSince) + return cm-nm <=1; + else + return cm-nm > 1; + } + + + + // Check if it was within the last two days + private boolean checkYear(QDateTime noteDate, QDateTime current) { + int ny = noteDate.date().year(); + int cy = current.date().year(); + if (checkSince) + return ny-cy == 0; + else + return ny-cy < 0; + } + + + + // Check if it was within the last two days + private boolean checkLastYear(QDateTime noteDate, QDateTime current) { + int ny = noteDate.date().year(); + int cy = current.date().year(); + if (checkSince) + return cy-ny <=1; + else + return cy-ny > 1; + } + + + // Get the name of a particular attribute check + public String getName(int i) { + return table.get(i).getName(); + } +} diff --git a/src/cx/fbn/nevernote/gui/FbnMenuBar.class b/src/cx/fbn/nevernote/gui/FbnMenuBar.class new file mode 100644 index 0000000000000000000000000000000000000000..fb3e1e960ffa18e3de15105623195ce05767e062 GIT binary patch literal 15492 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 MQd_7?C`MiW4_l^g5C8xG literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/gui/FbnWebView.class b/src/cx/fbn/nevernote/gui/FbnWebView.class new file mode 100644 index 0000000000000000000000000000000000000000..b8d508ca9f36b59bbd02a33e5ed18f0d858d8989 GIT binary patch literal 6725 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 Increase"), this); + indentAction.setText(tr(">> Increase")); + indentAction.triggered.connect(parent.browserWindow, "indentClicked()"); + setupShortcut(indentAction, "Format_Indent_Increase"); + //indentAction.setShortcut("Ctrl+M"); + + outdentAction = new QAction(tr("<< Decrease"), this); + outdentAction.setText(tr("<< Decrease")); + outdentAction.triggered.connect(parent.browserWindow, "outdentClicked()"); + setupShortcut(outdentAction, "Format_Indent_Decrease"); + //outdentAction.setShortcut("Ctrl+Shift+M"); + + notebookAddAction = new QAction(tr("Add"), this); + notebookAddAction.triggered.connect(parent, "addNotebook()"); + setupShortcut(notebookAddAction, "File_Notebook_Add"); + + notebookEditAction = new QAction(tr("Edit"), this); + notebookEditAction.setEnabled(false); + notebookEditAction.triggered.connect(parent, "editNotebook()"); + setupShortcut(notebookEditAction, "File_Notebook_Edit"); + + notebookDeleteAction = new QAction(tr("Delete"), this); + notebookDeleteAction.setEnabled(false); + notebookDeleteAction.triggered.connect(parent, "deleteNotebook()"); + setupShortcut(notebookDeleteAction, "File_Notebook_Delete"); + + notebookCloseAction = new QAction(tr("Open/Close Notebooks"), this); +// if (!Global.mimicEvernoteInterface) { + notebookCloseAction.setEnabled(true); + notebookCloseAction.triggered.connect(parent, "closeNotebooks()"); + setupShortcut(notebookCloseAction, "File_Notebook_Close"); +// } else { +// notebookCloseAction.setEnabled(false); +// } + + tagAddAction = new QAction(tr("Add"),this); + tagAddAction.triggered.connect(parent, "addTag()"); + //tagAddAction.setShortcut("Ctrl+Shift+T"); + setupShortcut(tagAddAction, "File_Tag_Add"); + + tagEditAction = new QAction(tr("Edit"), this); + tagEditAction.triggered.connect(parent, "editTag()"); + tagEditAction.setEnabled(false); + setupShortcut(tagEditAction, "File_Tag_Edit"); + + tagDeleteAction = new QAction(tr("Delete"), this); + tagDeleteAction.triggered.connect(parent, "deleteTag()"); + tagDeleteAction.setEnabled(false); + setupShortcut(tagDeleteAction, "File_Tag_Delete"); + + savedSearchAddAction = new QAction(tr("Add"),this); + savedSearchAddAction.triggered.connect(parent, "addSavedSearch()"); + setupShortcut(savedSearchAddAction, "File_SavedSearch_Add"); + + savedSearchEditAction = new QAction(tr("Edit"), this); + savedSearchEditAction.triggered.connect(parent, "editSavedSearch()"); + savedSearchEditAction.setEnabled(false); + setupShortcut(savedSearchEditAction, "File_SavedSearch_Edit"); + + savedSearchDeleteAction = new QAction(tr("Delete"), this); + savedSearchDeleteAction.triggered.connect(parent, "deleteSavedSearch()"); + savedSearchDeleteAction.setEnabled(false); + setupShortcut(savedSearchDeleteAction, "File_SavedSearch_Delete"); + + + connectAction = new QAction(tr("Connect"), this); + connectAction.setToolTip("Connect to Evernote"); + connectAction.triggered.connect(parent, "remoteConnect()"); + setupShortcut(connectAction, "Online_Connect"); + + synchronizeAction = new QAction(tr("Synchronize with Evernote"), this); + synchronizeAction.setToolTip("Delete all local data & get a fresh copy"); + synchronizeAction.triggered.connect(parent, "evernoteSync()"); + synchronizeAction.setEnabled(false); + setupShortcut(synchronizeAction, "Online_Synchronize"); + //synchronizeAction.setShortcut("F9"); + + noteOnlineHistoryAction = new QAction(tr("Note History"), this); + noteOnlineHistoryAction.triggered.connect(parent, "viewNoteHistory()"); + noteOnlineHistoryAction.setEnabled(false); + setupShortcut(noteOnlineHistoryAction, "Online_Note_History"); + + + + + + accountAction = new QAction(tr("Account Information"), this); + accountAction.setToolTip(tr("Account Information")); + accountAction.triggered.connect(parent, "accountInformation()"); + setupShortcut(accountAction, "Tools_Account_Information"); + +// compactAction = new QAction(tr("Compact Database"), this); +// compactAction.setToolTip(tr("Free unused database space")); +// compactAction.triggered.connect(parent, "compactDatabase()"); +// setupShortcut(compactAction, "Tools_Compact_Database"); + + databaseStatusAction = new QAction(tr("Database Status"), this); + databaseStatusAction.setToolTip(tr("Show current database information")); + databaseStatusAction.triggered.connect(parent, "databaseStatus()"); + setupShortcut(databaseStatusAction, "Tools_Database_Status"); + + + disableIndexing = new QAction(tr("Disable Note Indexing"), this); + disableIndexing.setToolTip("Manually Stop Note Indexing"); + disableIndexing.triggered.connect(parent, "toggleNoteIndexing()"); + disableIndexing.setCheckable(true); + disableIndexing.setChecked(false); + setupShortcut(disableIndexing, "Tools_Disable_Note_Indexing"); + + + folderImportAction = new QAction(tr("Automatic Folder Importing"), this); + folderImportAction.setToolTip("Import Files Automatically"); + folderImportAction.triggered.connect(parent, "folderImport()"); + setupShortcut(folderImportAction, "Tools_Folder_Import"); + + + loggerAction = new QAction(tr("Log"), this); + loggerAction.setToolTip("Show the detailed application log"); + loggerAction.triggered.connect(parent, "logger()"); + setupShortcut(loggerAction, "About_Log"); + + releaseAction = new QAction(tr("Release Notes"), this); + releaseAction.setToolTip("Release notes"); + releaseAction.triggered.connect(parent, "releaseNotes()"); + setupShortcut(releaseAction, "About_Release_Notes"); + + aboutAction = new QAction(tr("About"), this); + aboutAction.setToolTip("About NeverNote"); + aboutAction.triggered.connect(parent, "about()"); + setupShortcut(aboutAction, "About_About"); + + setupMenuBar(); + } + + public void setupMenuBar() { + fileMenu = addMenu(tr("&File")); + + noteMenu = fileMenu.addMenu(tr("&Note")); + notebookMenu = fileMenu.addMenu(tr("Notebook")); + tagMenu = fileMenu.addMenu(tr("Tag")); + savedSearchMenu = fileMenu.addMenu(tr("Saved Searches")); + fileMenu.addSeparator(); + fileMenu.addAction(emailAction); + fileMenu.addAction(printAction); + fileMenu.addSeparator(); + fileMenu.addAction(noteImportAction); + fileMenu.addAction(noteExportAction); + fileMenu.addAction(backupAction); + fileMenu.addAction(restoreAction); + fileMenu.addSeparator(); + fileMenu.addAction(emptyTrashAction); + fileMenu.addAction(exitAction); + + editMenu = addMenu("&Edit"); + editMenu.addAction(editFind); + editMenu.addSeparator(); + editMenu.addAction(editUndo); + editMenu.addAction(editRedo); + editMenu.addSeparator(); + editMenu.addAction(editCut); + editMenu.addAction(editCopy); + editMenu.addAction(editPaste); + editMenu.addAction(editPasteWithoutFormat); + editMenu.addSeparator(); + editMenu.addAction(settingsAction); + + viewMenu = addMenu("&View"); + viewMenu.addAction(noteAttributes); + viewMenu.addSeparator(); + viewMenu.addAction(thumbnailView); + viewMenu.addSeparator(); + viewMenu.addAction(hideNoteList); + viewMenu.addAction(hideNotebooks); + viewMenu.addAction(hideTags); + viewMenu.addAction(hideAttributes); + viewMenu.addAction(hideSavedSearches); + viewMenu.addAction(hideTrash); + viewMenu.addAction(showEditorBar); + viewMenu.addAction(hideLeftSide); + + formatMenu = addMenu("&Format"); + formatMenu.addAction(formatBold); + formatMenu.addAction(formatUnderline); + formatMenu.addAction(formatItalic); + formatMenu.addSeparator(); + formatMenu.addAction(formatStrikethrough); + formatMenu.addAction(horizontalLineAction); + formatMenu.addSeparator(); + formatMenu.addAction(formatSuperscript); + formatMenu.addAction(formatSubscript); + formatMenu.addSeparator(); + + alignMenu = formatMenu.addMenu(tr("Alignment")); + alignMenu.addAction(alignLeftAction); + alignMenu.addAction(alignCenterAction); + alignMenu.addAction(alignRightAction); + + listMenu = formatMenu.addMenu(tr("Lists")); + listMenu.addAction(formatBulletList); + listMenu.addAction(formatNumberList); + indentMenu = formatMenu.addMenu(tr("Indent")); + indentMenu.addAction(indentAction); + indentMenu.addAction(outdentAction); + + noteAttributes.setCheckable(true); + noteMenu.addAction(noteAdd); + noteMenu.addAction(noteDelete); + noteMenu.addAction(noteReindex); + noteMenu.addSeparator(); + noteMenu.addAction(noteTags); + noteMenu.addAction(noteRestoreAction); + noteMenu.addSeparator(); + noteMenu.addAction(noteDuplicateAction); + noteMenu.addAction(noteMergeAction); + + + notebookMenu.addAction(notebookAddAction); + notebookMenu.addAction(notebookEditAction); + notebookMenu.addAction(notebookDeleteAction); +// if (!Global.mimicEvernoteInterface) { + notebookMenu.addSeparator(); + notebookMenu.addAction(notebookCloseAction); +// } + + tagMenu.addAction(tagAddAction); + tagMenu.addAction(tagEditAction); + tagMenu.addAction(tagDeleteAction); + + savedSearchMenu.addAction(savedSearchAddAction); + savedSearchMenu.addAction(savedSearchEditAction); + savedSearchMenu.addAction(savedSearchDeleteAction); + + onlineMenu = addMenu(tr("&Online")); + onlineMenu.addAction(synchronizeAction); + onlineMenu.addAction(connectAction); + onlineMenu.addSeparator(); + onlineMenu.addAction(noteOnlineHistoryAction); + + toolsMenu = addMenu(tr("&Tools")); + toolsMenu.addAction(accountAction); + toolsMenu.addAction(fullReindexAction); + toolsMenu.addAction(disableIndexing); +// toolsMenu.addAction(compactAction); + toolsMenu.addAction(databaseStatusAction); + toolsMenu.addSeparator(); + toolsMenu.addAction(folderImportAction); + + helpMenu = addMenu(tr("&Help")); + helpMenu.addAction(releaseAction); + helpMenu.addAction(loggerAction); + helpMenu.addSeparator(); + helpMenu.addAction(aboutAction); + + addMenu(fileMenu); + addMenu(editMenu); + addMenu(viewMenu); + addMenu(formatMenu); + addMenu(onlineMenu); + addMenu(toolsMenu); + addMenu(helpMenu); + + } + + + private void setupShortcut(QAction action, String text) { + if (!Global.shortcutKeys.containsAction(text)) + return; + action.setShortcut(Global.shortcutKeys.getShortcut(text)); + } + +} diff --git a/src/cx/fbn/nevernote/gui/NotebookTreeWidget.class b/src/cx/fbn/nevernote/gui/NotebookTreeWidget.class new file mode 100644 index 0000000000000000000000000000000000000000..0c63c06f38d1bcf68e3b7ad37ad1b13a7c3c7896 GIT binary patch literal 9471 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 literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/gui/NotebookTreeWidget.java b/src/cx/fbn/nevernote/gui/NotebookTreeWidget.java new file mode 100644 index 0000000..bb53f91 --- /dev/null +++ b/src/cx/fbn/nevernote/gui/NotebookTreeWidget.java @@ -0,0 +1,289 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.gui; + +import java.util.ArrayList; +import java.util.List; + +import com.evernote.edam.type.Notebook; +import com.trolltech.qt.core.QByteArray; +import com.trolltech.qt.core.QMimeData; +import com.trolltech.qt.core.Qt; +import com.trolltech.qt.core.Qt.SortOrder; +import com.trolltech.qt.gui.QAbstractItemView; +import com.trolltech.qt.gui.QAction; +import com.trolltech.qt.gui.QBrush; +import com.trolltech.qt.gui.QColor; +import com.trolltech.qt.gui.QContextMenuEvent; +import com.trolltech.qt.gui.QDragEnterEvent; +import com.trolltech.qt.gui.QDragMoveEvent; +import com.trolltech.qt.gui.QHeaderView; +import com.trolltech.qt.gui.QIcon; +import com.trolltech.qt.gui.QMenu; +import com.trolltech.qt.gui.QTreeWidget; +import com.trolltech.qt.gui.QTreeWidgetItem; + +import cx.fbn.nevernote.Global; +import cx.fbn.nevernote.filters.NotebookCounter; +import cx.fbn.nevernote.signals.NoteSignal; + +public class NotebookTreeWidget extends QTreeWidget { + private QAction deleteAction; + private QAction addAction; + private QAction editAction; + public NoteSignal noteSignal; +// private final QTreeWidgetItem previousMouseOver; +// private boolean previousMouseOverWasSelected; + + public void setAddAction(QAction a) { + addAction = a; + } + + public void setDeleteAction(QAction d) { + deleteAction = d; + } + + public void setEditAction(QAction e) { + editAction = e; + } + + public NotebookTreeWidget() { + noteSignal = new NoteSignal(); + List labels = new ArrayList(); + labels.add("Notebooks"); + labels.add(""); + setAcceptDrops(true); + setDragEnabled(true); + setColumnCount(2); + header().setResizeMode(0, QHeaderView.ResizeMode.ResizeToContents); + header().setResizeMode(1, QHeaderView.ResizeMode.Stretch); + header().setMovable(false); + setHeaderLabels(labels); + setDragDropMode(QAbstractItemView.DragDropMode.DragDrop); + // If we want to mimic Evernote's notebook selection + if (Global.mimicEvernoteInterface) { + setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection); + } else + setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection); + +// int width = Global.getColumnWidth("notebookTreeName"); +// if (width>0) +// setColumnWidth(0, width); +// previousMouseOver = new QTreeWidgetItem(); + } + + public void selectNotebook(QTreeWidgetItem item) { + QTreeWidgetItem root = invisibleRootItem(); + QTreeWidgetItem child; + + for (int i=0; i books, List localBooks) { + Notebook book; + QTreeWidgetItem child; + clear(); + String iconPath = new String("classpath:cx/fbn/nevernote/icons/"); + QIcon blueIcon = new QIcon(iconPath+"notebook-blue.png"); + QIcon greenIcon = new QIcon(iconPath+"notebook-green.png"); + QIcon redIcon = new QIcon(iconPath+"notebook-red.png"); + QIcon yellowIcon = new QIcon(iconPath+"notebook-yellow.png"); +// QIcon icon = new QIcon(iconPath+"nevernote.png"); + if (books == null) + return; + Qt.Alignment ra = new Qt.Alignment(Qt.AlignmentFlag.AlignRight); + for (int i=0; i books, List counts) { + QTreeWidgetItem root = invisibleRootItem(); + QTreeWidgetItem child; + + QBrush blue = new QBrush(); + QBrush black = new QBrush(); + black.setColor(QColor.black); + if (Global.tagBehavior().equalsIgnoreCase("ColorActive") && !Global.mimicEvernoteInterface) + blue.setColor(QColor.blue); + else + blue.setColor(QColor.black); + int total=0; + +// for (int i=0; i 0) { + child.setForeground(0, blue); + child.setForeground(1, blue); + } + } +// if (guid.equals("") && Global.mimicEvernoteInterface) { +// child.setText(1, new Integer(total).toString()); +// } + } + } + } + + for (int i=0; i getNotebookGuids() { + List names = new ArrayList(); + QTreeWidgetItem root = invisibleRootItem(); + QTreeWidgetItem child; + for (int i=0; i_08W}xTS_7plLR|8cD%#}Iku5;uv^-UMlbRt;~6m; z87D1;7TVIi=>lESg>H0TQX&(4PEUXCztnR|zc(Yxj+Puwf6y%N-S@qFzx&-gPyhb! z`~L*+7~aB}wqE~8M`dXAs59LpaT zi1zg_3dF|Tf=nQaT{^muNI+nZj=i{7V0T$^M^l#kanCK4Y1_Blzo;zs>9}vpV%#%| z6ONI$WuX%XxGD&B+(NBPD!I6y{wU!w!r?r>}6xk$k>Kc%;bE}a*9L! zi(NQ`2Q@q(FwiEY^oII+|m&0W~uWM#n?w#%c2~3^ z6~GZ4AH`9Dy=0`0sP+opnvaUNk&Qz1Id~{)$ER zk7Yl+swjb7^mSr~W)8P?G+-{^otxev1U~OD2$({8x zG)x=~40GT1;!)2tuBtr}7{o4>w_zPmAtBIV+AKQ_qfB9=;5soTaM-ksa=B#qD}zlW zTc+!jGYO1fLX}95hI0Zvt(7@VTMg3!2OGCJTd`~kU%@=1Ba0aUZOyPNa`uwI!#nF> zHh-C79_nu{jRdAJ(TO>BgL2SDPL!OY8hlnq4hsTtqg0X(X+ORbaI3JI0Bb%`;!{}E zaRJW@boy>+FK}O9OCKgNaSuL;7c_i|RklsPVqV9m@fo%jHa1n=(>nobacQ7Bjwt%> zo?;EAz|qz;Z#PEO0usopbYH|J9Yqy`#_i7=t88m|SUN7_3dbnc1-VYQ4)jeoF+nvc z<5e9F+|XF1lAW2xt$k4Q!Lo~ZQHQs+@41RqQ1p?7+e+}VlIXgQtGLEu zquqjA%90dY1trkmu3+zso<6AkKBwble4cezwyv?N*xaYP@G8Ej;R`jo@A$r$t|v3| z{?VN4`LiB{spB=g&U}uRO)7|uI2dIHn!|5e8}!I8>-Y-ZU~QKPsUl#@>TAVb^K#V^ zI=P~xB*YR8(^GEgT};gj9BK|yeX!?) z9J3i({IRGz%oP?f%e9SpLt-ekJKH&%Sgoa>YzXl~_B?^pEf?OA+Q9P$SB4quuAFa} zS7wY-&4;}V-DgG2NT)KfCLJ=LZYR012GgMX{T?f*mEv**UQe;v^dn=oNGBg1$zU3(D6t7 zi5igWlC5UAg^xRzv_K4)uAjL&s7gg*3!K2P(QhTcRT9-+eu_p~C30@XGv%bEP6$0M zPmw2-w)sV#b{y%Asc)GqYq-UuR~s7WXIH)UHN4lB?a_wQkW}f- z6Cm^>hGWDyj@`)c==lil$D??d^LmJdkE4%oY??^b_8I0r5st-E>03x|BPN2;0s8tx zfN&tRsv#(Ej|UzLoM?@eX~a53tkZ3<9<5aMyx?%4Yk2~qK0)6r|9!(#umYo zic_)9Rh@jlzKOx54V*cjs^Sxy7+LB*yMgh+*d`{IHZir7jJ=1aH*mgtwu<>Gp4-6E zU`O<1{2ffD_s4HzIf8%T;>;%UL@5kvNiBM;3R%SppOPI_*hwwMkrGFaC$-xsM{psP z)T(&t^|;s{Pv6F81>XMPRw{ZEuT=3R6r-^|ER!~dgBZsECV5gj$Lkbk zF^wfW4Fk{M3eQJAW^j!&Z*b;2mFL?Bj4m$l=#>1 zEqt5158wqNTqi}RFpuxzd!%s|X?!0)pitkWSD^$H+FL{mF@8vlA93yhL_VOCng*fq zGs~Zb5e<`+@P8PJz>o2hn&MvO5>*N5P25rvEcGrPui|ZWPuK1lb?3{ks`&kd z?evF2e~uzw#JxOOq3f}y@n`&n8+YLd{))db_6S0>oA?Kv=;r&Y Qco)@?B>zrr;Py!Je^lMoJpcdz literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/gui/SavedSearchTreeWidget.java b/src/cx/fbn/nevernote/gui/SavedSearchTreeWidget.java new file mode 100644 index 0000000..76d6326 --- /dev/null +++ b/src/cx/fbn/nevernote/gui/SavedSearchTreeWidget.java @@ -0,0 +1,120 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.gui; + +import java.util.ArrayList; +import java.util.List; + +import com.evernote.edam.type.SavedSearch; +import com.trolltech.qt.core.Qt.SortOrder; +import com.trolltech.qt.gui.QAbstractItemView; +import com.trolltech.qt.gui.QAction; +import com.trolltech.qt.gui.QContextMenuEvent; +import com.trolltech.qt.gui.QIcon; +import com.trolltech.qt.gui.QMenu; +import com.trolltech.qt.gui.QTreeWidget; +import com.trolltech.qt.gui.QTreeWidgetItem; + +public class SavedSearchTreeWidget extends QTreeWidget { + private QAction editAction; + private QAction deleteAction; + private QAction addAction; + + + public SavedSearchTreeWidget() { +// setAcceptDrops(true); +// setDragEnabled(true); + setAcceptDrops(false); + setDragEnabled(false); +// setDragDropMode(QAbstractItemView.DragDropMode.DragDrop); + setHeaderLabel("Saved Searches"); + setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection); + } + + public void setEditAction(QAction e) { + editAction = e; + } + public void setDeleteAction(QAction d) { + deleteAction = d; + } + public void setAddAction(QAction a) { + addAction = a; + } + + public void load(List tempList) { + SavedSearch search; + List index = new ArrayList(); + + //Clear out the tree & reload + clear(); + String iconPath = new String("classpath:cx/fbn/nevernote/icons/"); + QIcon icon = new QIcon(iconPath+"search.png"); + + for (int i=0; i2T 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 OC}Szl(c8*_cm4^pN~=-; literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/gui/ShortcutKeys.java b/src/cx/fbn/nevernote/gui/ShortcutKeys.java new file mode 100644 index 0000000..8adc9a8 --- /dev/null +++ b/src/cx/fbn/nevernote/gui/ShortcutKeys.java @@ -0,0 +1,362 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.gui; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.HashMap; +import java.util.Scanner; +import java.util.Vector; + +import cx.fbn.nevernote.Global; + +public class ShortcutKeys { + public String File_Note_Add; // Add a new note + public String File_Note_Reindex; // Reindex the current note + public String File_Note_Modify_Tags; // Change current note tags + public String File_Note_Delete; // Delete a tag + public String File_Note_Restore; // Undelete a note + public String File_Note_Duplicate; // duplicate a note + public String File_Notebook_Add; // Add a notebook + public String File_Notebook_Edit; // Edit an existing notebook + public String File_Notebook_Delete; // Delete the existing notebook + public String File_Notebook_Open; // Open a closed (i.e. archived) notebook + public String File_Notebook_Close; // Close (i.e. archive) a notebook + public String File_Tag_Add; // Add a notebook + public String File_Tag_Edit; // Edit an existing notebook + public String File_Tag_Delete; // Delete the existing notebook + public String File_SavedSearch_Add; // Add a notebook + public String File_SavedSearch_Edit; // Edit an existing notebook + public String File_SavedSearch_Delete; // Delete the existing notebook + public String File_Email; // Email note + public String File_Print; // Print + public String File_Backup; // Backup the database + public String File_Restore; // Restore the database + public String File_Empty_Trash; // Purge all delete notes + public String File_Exit; // I'm outahere + + public String Edit_Find_In_Note; // Search only within the current note + public String Edit_Undo; // Undo last change + public String Edit_Redo; // Redo the last undone change + public String Edit_Cut; // Cut current selection to the clipboard + public String Edit_Copy; // Copy the current selection to the clipboard + public String Edit_Paste; // Paste + public String Edit_Paste_Without_Formatting; // Paste as plain text + public String Edit_Preferences; // Settings dialog box + public String Edit_Insert_Hyperlink; // Encrypt selected text + public String Edit_Insert_Table; // Insert table into note + public String Edit_Insert_Table_Row; // Insert row into table + public String Edit_Delete_Table_Row; // Delete a table row + public String Edit_Insert_Todo; // Insert todo + public String Edit_Encrypt_Text; // Encrypt selected text + public String Edit_Rotate_Image_Right; // Rotate an image right + public String Edit_Rotate_Image_Left; // Rotate an image left + + public String View_Extended_Information; // View details on the current note + public String View_Thumbnail; // View Image Thumbnail + public String View_Show_Note_List; // Show current notes + public String View_Show_Notebooks; // Show notebooks + public String View_Show_Tags; // Show the tags window + public String View_Show_Attribute_Searches; // Show the attribute selection tree + public String View_Show_SavedSearches; // Show the saved search tree + public String View_Show_Trash; // Show the trash window + public String View_Show_Editor_Button_Bar; // Hide the editor button bar + public String View_Show_Left_Side; // Hide all left hand windows + + public String Format_Bold; // Bold (duh) + public String Format_Underline; // Underline + public String Format_Italic; // Italic + public String Format_Strikethrough; // Strikethrough + public String Format_Horizontal_Line; // Href line + public String Format_Superscript; // Set superscript + public String Format_Subscript; // Subscript + public String Format_Alignment_Left; // Left align text + public String Format_Alignment_Center; // Center text + public String Format_Alignment_Right; // Right align text + public String Format_List_Bullet; // Bullet list + public String Format_List_Numbered; // Numbered list + public String Format_Indent_Increase; // Increase the indentation + public String Format_Indent_Decrease; // Decrease the indent + + public String Online_Note_History; // Synchronize with Evernote + + public String Online_Synchronize; // Synchronize with Evernote + public String Online_Connect; // Connect to Evernote + public String Tools_Account_Information; // Show account information + public String Tools_Reindex_Database; // Reindex the entire database + public String Tools_Disable_Note_Indexing; // Disable note indexing + public String Tools_Compact_Database; // Free unused database space + public String Tools_Database_Status; // Current database information + + public String About_Release_Notes; // Current version's release notes + public String About_Log; // Message log + public String About_About; // About dialog box + + public String Focus_Title; // Switch focus to the title bar + public String Focus_Tag; // Switch focus to the tag edit + public String Focus_Note; // Switch focus to the note + public String Focus_Author; // Switch focus to the author + public String Focus_Url; // Switch focus to the URL + + public String Insert_DateTime; // Insert the current date/time + + HashMap actionMap; + HashMap shortcutMap; + + public ShortcutKeys() { + File_Note_Add = new String("Ctrl+N"); // Add a new note + File_Note_Reindex = new String(); // Reindex the current note + File_Note_Modify_Tags = new String(); // Change current note tags + File_Note_Delete = new String(); // Delete a tag + File_Note_Restore = new String(); // Undelete a note + File_Note_Duplicate = new String(); // Duplicate a note + File_Notebook_Add = new String(); // Add a notebook + File_Notebook_Edit = new String(); // Edit an existing notebook + File_Notebook_Delete = new String(); // Delete the existing notebook + File_Notebook_Open = new String(); // Open a closed (i.e. archived) notebook + File_Notebook_Close = new String(); // Close (i.e. archive) a notebook + File_Tag_Add = new String("Ctrl+Shift+T"); // Add a notebook + File_Tag_Edit = new String(); // Edit an existing notebook + File_Tag_Delete = new String(); // Delete the existing notebook + File_SavedSearch_Add = new String(); // Add a notebook + File_SavedSearch_Edit = new String(); // Edit an existing notebook + File_SavedSearch_Delete = new String(); // Delete the existing notebook + File_Email = new String("Ctrl+Shift+E"); // Email note + File_Print = new String("Ctrl+P"); // Print + File_Backup = new String(""); // Backup + File_Restore = new String(""); // Restore + File_Empty_Trash = new String(); // Purge all delete notes + File_Exit = new String("Ctrl+Q"); // I'm outahere + + Edit_Find_In_Note = new String("Ctrl+F"); // Search only within the current note + Edit_Undo = new String("Ctrl+Z"); // Undo last change + Edit_Redo = new String("Ctrl+Y"); // Redo the last undone change + Edit_Cut = new String("Ctrl+X"); // Cut current selection to the clipboard + Edit_Copy = new String("Ctrl+C"); // Copy the current selection to the clipboard + Edit_Paste = new String("Ctrl+V"); // Paste + Edit_Paste_Without_Formatting = new String("Ctrl+Shift+P"); // Paste as plain text + Edit_Preferences = new String(); // Settings dialog box + + Edit_Insert_Hyperlink = new String("Ctrl+K"); // Insert a hyperlink + Edit_Insert_Table = new String(); // Insert a table + Edit_Insert_Table_Row = new String(); // Insert a table row + Edit_Delete_Table_Row = new String(); // Delete a table row + Edit_Insert_Todo = new String(); + Edit_Encrypt_Text = new String(); + Edit_Rotate_Image_Right = new String(); + Edit_Rotate_Image_Left = new String(); + + View_Extended_Information = new String("F8"); // View details on the current note + View_Thumbnail = new String(); // View the thumbnail + View_Show_Note_List = new String("F10"); // Show current notes + View_Show_Notebooks = new String(); // Show notebooks + View_Show_Tags = new String(); // Show the tags window + View_Show_Attribute_Searches = new String(); // Show the attribute selection tree + View_Show_SavedSearches = new String(); // Show the saved search tree + View_Show_Trash = new String(); // Show the trash window + View_Show_Editor_Button_Bar = new String(); // Hide the editor button bar + View_Show_Left_Side = new String("F11"); // Hide all left hand windows + + Format_Bold = new String("Ctrl+B"); // Bold (duh) + Format_Underline = new String("Ctrl+U"); // Underline + Format_Italic = new String("Ctrl+I"); // Italic + Format_Strikethrough = new String("Ctrl+-"); // Strikethrough + Format_Horizontal_Line = new String(); // Href line + Format_Superscript = new String("Ctrl+="); // Set superscript + Format_Subscript = new String("Ctrl++Shift+="); // Subscript + Format_Alignment_Left = new String("Ctrl+L"); // Left align text + Format_Alignment_Center = new String("Ctrl+C"); // Center text + Format_Alignment_Right = new String("Ctrl+R"); // Right align text + Format_List_Bullet = new String("Ctrl+Shift+B"); // Bullet list + Format_List_Numbered = new String("Ctrl+Shift+N"); // Numbered list + Format_Indent_Increase = new String("Ctrl+M"); // Increase the indentation + Format_Indent_Decrease = new String("Ctrl+Shift+M"); // Decrease the indent + + Online_Note_History = new String(); + + Online_Synchronize = new String("F9"); // Synchronize with Evernote + Online_Connect = new String(); // Connect to Evernote + Tools_Account_Information = new String(); // Show account information + Tools_Reindex_Database = new String(); // Reindex the entire database + Tools_Disable_Note_Indexing = new String(); // Disable note indexing + Tools_Compact_Database = new String(); // Free unused database space + Tools_Database_Status = new String(); // Current database information + + About_Release_Notes = new String(); // Current version's release notes + About_Log = new String(); // Message log + About_About = new String(); // About dialog box + + Insert_DateTime = new String("Ctrl+;"); + + Focus_Title = new String(); + Focus_Tag = new String("Ctrl+Shift+T"); + Focus_Note = new String(); + Focus_Author = new String(); + Focus_Url = new String(); + + // Setup value Array + shortcutMap = new HashMap(); + actionMap = new HashMap(); + + // Load the defaults + loadKey("File_Note_Add", File_Note_Add); + loadKey("File_Tag_Add", File_Tag_Add); + loadKey("File_Email", File_Email); + loadKey("File_Print", File_Print); + loadKey("File_Backup", File_Backup); + loadKey("File_Restore", File_Restore); + loadKey("File_Exit", File_Exit); + + loadKey("Edit_Find_In_Note", Edit_Find_In_Note); + loadKey("Edit_Undo", Edit_Undo); + loadKey("Edit_Redo", Edit_Redo); + loadKey("Edit_Cut", Edit_Cut); + loadKey("Edit_Copy", Edit_Copy); + loadKey("Edit_Paste", Edit_Paste); + loadKey("Edit_Paste_Without_Formatting", Edit_Paste_Without_Formatting); + loadKey("Edit_Insert_Hyperlink", Edit_Insert_Hyperlink); + loadKey("Edit_Insert_Table_Row", Edit_Insert_Table_Row); + loadKey("Edit_Insert_Table_Row", Edit_Delete_Table_Row); + loadKey("Edit_Insert_Todo", Edit_Insert_Todo); + loadKey("Edit_Rotate_Image_Right", Edit_Rotate_Image_Right); + loadKey("Edit_Rotate_Image_Left", Edit_Rotate_Image_Left); + + loadKey("View_Extended_Information", View_Extended_Information); + loadKey("View_Thumbnail", View_Thumbnail); + loadKey("View_Show_Note_List", View_Show_Note_List); + loadKey("View_Show_Left_Side",View_Show_Left_Side); + + loadKey("Format_Bold", Format_Bold); + loadKey("Format_Underline", Format_Underline); + loadKey("Format_Italic", Format_Italic); + loadKey("Format_Strikethrough", Format_Strikethrough); + loadKey("Format_Superscript", Format_Superscript); + loadKey("Format_Subscript", Format_Subscript); + loadKey("Format_Alignment_Left", Format_Alignment_Left); + loadKey("Format_Alignment_Center", Format_Alignment_Center); + loadKey("Format_Alignment_Right", Format_Alignment_Right); + loadKey("Format_List_Bullet", Format_List_Bullet); + loadKey("Format_List_Numbered", Format_List_Numbered); + loadKey("Format_Indent_Increase", Format_Indent_Increase); + loadKey("Format_Indent_Decrease", Format_Indent_Decrease); + loadKey("Tools_Synchronize", Online_Synchronize); + + + loadKey("Focus_Title", Focus_Title); + loadKey("Focus_Tag", Focus_Tag); + loadKey("Focus_Note", Focus_Note); + loadKey("Focus_Author", Focus_Author); + loadKey("Focus_Url", Focus_Url); + + loadKey("Insert_DateTime", Insert_DateTime); + + loadCustomKeys(); + + } + + // Read in the custom keys (if they exist) + private void loadCustomKeys() { + File file = new File(Global.getDirectoryPath()+"shortcuts.txt"); + try { + Scanner scanner = new Scanner(file); + while ( scanner.hasNextLine() ){ + String line = scanner.nextLine(); + line = line.replace("\t", " "); // Replace tab characters + line = line.replace("\n", " "); // replace newline + line = line.replace("\r", " "); // replace carrage return + line = line.trim(); // compress the line + String split[] = line.split(" "); + Vector keyVector = new Vector(); + for (int i=0; i=2) + loadKey(keyVector.get(0), keyVector.get(1)); + + } + } catch (FileNotFoundException e) { + return; + } + } + + + // Load a key value into the map for later use + public void loadKey(String action, String shortcut) { + shortcut = shortcut.trim().toLowerCase(); + action = action.trim().toLowerCase(); + + // If we have an existing one, remove it. + if (actionMap.containsKey(action)) + removeByAction(action); + if (shortcutMap.containsKey(shortcut)) + removeByShortcut(shortcut); + + if (shortcut.equals("")) { + removeByShortcut(shortcut); + return; + } + + // Add the new value + actionMap.put(action.toLowerCase(), shortcut); + shortcutMap.put(shortcut.toLowerCase(), action); + } + + // Remove a shortcut by the Shortcut key + public void removeByShortcut(String shortcut) { + String action = shortcutMap.get(shortcut.toLowerCase()); + shortcutMap.remove(shortcut.toLowerCase()); + if (action != null) + actionMap.remove(action.toLowerCase()); + } + + // Remove a shortcut by the action itself + public void removeByAction(String action) { + String shortcut = actionMap.get(action.toLowerCase()); + actionMap.remove(action.toLowerCase()); + if (shortcut != null) + shortcutMap.remove(shortcut.toLowerCase()); + } + + // Check if a shortcut key exists + public boolean containsShortcut(String shortcut) { + return shortcutMap.containsKey(shortcut.toLowerCase()); + } + + // Check if an action exists + public boolean containsAction(String action) { + return actionMap.containsKey(action.toLowerCase()); + } + + // Get a key based upon the action + public String getShortcut(String action) { + return actionMap.get(action.toLowerCase()); + } + + // Get an action based upon the key + public String getAction(String shortcut) { + return shortcutMap.get(shortcut.toLowerCase()); + } + +} diff --git a/src/cx/fbn/nevernote/gui/TableView.class b/src/cx/fbn/nevernote/gui/TableView.class new file mode 100644 index 0000000000000000000000000000000000000000..94b8b6a04dc060b4db0e7e6a39e9204476dfaff0 GIT binary patch literal 13663 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 rXE3P2krsGYXa3c4QGChnkB^bl@G{D3-e znzIHc6l>{ST8AC_)7V8D*h8oDFkD@zq%(OEoz2r|Ber4vd=zzZ0|od*3UV8D@ha-( z_0+>QE)Kj6s(g+{&|m3q_=0ZGJJ1p~Z|_1E6-HFj-{~LFRHpZ6j-yK@3g0C}t};hz z?~7n=b)B%AYNP>whb8IX)eqChiXLZIl1q|YwoP$$s^?)I#WE`ZfZp0jS7I#_+%!S{rtsoaj{LHxAWJwau@I`B0wpQ&Gt<^}ut zm=mgZP&w459rzkY^TM2_O-|E^IZa`wX;DtonNCwvPE)7T)ST1Q?KCaUX*%C&T9VT= z;504GX}ZK|Iw_}VyEK8<8K64J%N80&PFditbl*zDq{#8V7ny8{7f6@U;oBIfQQm^;sd z`4WZU%6s8}Be)zFrCE3`q&^t^Cfr$y(HXc^6NP~%s2|r*2Iv~vj4K{n=qB1qJMp}q z&Z7tD0{T8(M9SVfCt*84`knUGu zdO)2|d(;*5E%iBiNPUHp>Mq)+9-#f|F?vKjMF-Tg^lkMAdQ`nlkE!?RahHp}=kkC{ zaYcOyc5oEu7M*JSET3$nqb;oID8+S>V1WdO1-^76L}4v zicNtD{0^^`vHT)Vq1NHeg>8!?_%yt^;Rp%0|0aDzBf0t@9HQI8o`prfhgi!$r1Fnw z5|?|b)#0Pk|30QE%u`bT0E+`C#~-@A@P;E0V;ib(rV5zKb+a6wcYrsn-_K|4=d<^* zJ({8Lq5a&8-z4|7AK;Da>-KTH!F_-e>#N-Rc%Y#~d<_O~ZYY(pRV8>oe?MQGh|+j8_KIZ=~rD<#H-m7) z!go~-D}Wo$L2yG#4-FXt$CB#VH>3xvxJx8~agQYVJ41TmDt1+Qr4d1?p~6>HkqS!- zhVP~kzDfx)CNK?W^DePx=fSr!4kVQ?Jb}pkBW!{`Nwew4w1A#M*6>qg2hY$(`Wf8D zFW?TIrK^w)d=>8DPI{j1q2JOIxNY$hdI4|G!;oHrqj;H_USW;0e;mEaN78HDg3Aya z>5tq`e}W@;lkcQI^JDZD|Cav3|E9N_G$hp-ZanQXYi(R_&$|? zhPPp$eWq~}6>1Vyn-Rl}sdtfQ_(3?=GMKrAV+D&hn*Ry&yTRfOL?6*OJU=Ec+PF>~ z50em0&>j&cDfKm|oNR0p$Ck!8+D~%3v+U+ExGuL*@l>y)YEl zN5J)Q5nR7d;d-esu9t`40y8DhLD8N(x{z%;bYbf@#pB(Oi14_4)*gN>$$y4768``r z*+JTu#^)2q53Aef&w*u6$BcaS3_36gNLD8jq|Q z9-d~vI_4sKKAJ0V+%}Sy@u(bXmuIB79KshFO4x9dnlueXu~L#3qq?G-LAR{*`~%93 z8bFn{?NMb22D5z+@yki2cT>5%{syn|d_kVGlBy!9#;nWII2rapJQmyLII}hFm z0W2G>+774{>t`p`s(os8Qgxv5G?9qgSj$5AK;pw;>(giy9|4I>M-;AwM0`jLX3-*^ zP3=g0*7F>Say@NE`*tK@x1jdff%q(Xx7uMjBeB~dvC|=ta=Kofq0WT9O`z@SEOjHtI$wv1i)pUoWkFb!e8o}m{gmFI3|>e1x-~YjAK%&AB-zCpf=;# z48gvxwy5)v<*rues|y!Z(d~F%gy#ZvvAPt`r}4ZD&wKH_9M2@4+ZI*v>uS5Ya#7X) E0t&PPvH$=8 literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/gui/TableView.java b/src/cx/fbn/nevernote/gui/TableView.java new file mode 100644 index 0000000..b30237b --- /dev/null +++ b/src/cx/fbn/nevernote/gui/TableView.java @@ -0,0 +1,503 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ +package cx.fbn.nevernote.gui; + +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.SortedMap; + +import com.evernote.edam.type.Note; +import com.trolltech.qt.core.QByteArray; +import com.trolltech.qt.core.QDateTime; +import com.trolltech.qt.core.QModelIndex; +import com.trolltech.qt.core.Qt; +import com.trolltech.qt.core.Qt.SortOrder; +import com.trolltech.qt.gui.QAbstractItemView; +import com.trolltech.qt.gui.QAction; +import com.trolltech.qt.gui.QApplication; +import com.trolltech.qt.gui.QColor; +import com.trolltech.qt.gui.QContextMenuEvent; +import com.trolltech.qt.gui.QDragEnterEvent; +import com.trolltech.qt.gui.QDropEvent; +import com.trolltech.qt.gui.QFontMetrics; +import com.trolltech.qt.gui.QHeaderView; +import com.trolltech.qt.gui.QKeyEvent; +import com.trolltech.qt.gui.QMenu; +import com.trolltech.qt.gui.QStandardItemModel; +import com.trolltech.qt.gui.QTableView; +import com.trolltech.qt.gui.QKeySequence.StandardKey; + +import cx.fbn.nevernote.Global; +import cx.fbn.nevernote.filters.NoteSortFilterProxyModel; +import cx.fbn.nevernote.signals.NoteSignal; +import cx.fbn.nevernote.utilities.ApplicationLogger; +import cx.fbn.nevernote.utilities.ListManager; + +public class TableView extends QTableView { +// private final ListManager runner; + private final ApplicationLogger logger; + public QStandardItemModel model; // Standard item model + public NoteSortFilterProxyModel proxyModel; // note sort model + private QAction deleteAction; + private QAction addAction; + private QAction restoreAction; + private QAction noteHistoryAction; + private QAction duplicateAction; + private QAction mergeNotesAction; + + // Note title colors + private QAction noteTitleColorWhite; + private QAction noteTitleColorRed; + private QAction noteTitleColorBlue; + private QAction noteTitleColorGreen; + private QAction noteTitleColorYellow; + private QAction noteTitleColorBlack; + private QAction noteTitleColorGray; + private QAction noteTitleColorCyan; + private QAction noteTitleColorMagenta; + + + + public QHeaderView header; + int fontHeight; + public Signal1 rowChanged; + public Signal0 resetViewport; + public NoteSignal noteSignal; + + public TableView(ApplicationLogger l) { + logger = l; + header = horizontalHeader(); + header.setMovable(true); + + noteSignal = new NoteSignal(); + setAcceptDrops(true); + setDragEnabled(true); + setDragDropMode(QAbstractItemView.DragDropMode.DragDrop); + setDropIndicatorShown(false); + + model = new QStandardItemModel(0,Global.noteTableColumnCount, this); + + model.setHeaderData(Global.noteTableCreationPosition, Qt.Orientation.Horizontal, "Date Created"); + model.setHeaderData(Global.noteTableTagPosition, Qt.Orientation.Horizontal, "Tags"); + model.setHeaderData(Global.noteTableGuidPosition, Qt.Orientation.Horizontal, "Guid"); + model.setHeaderData(Global.noteTableNotebookPosition, Qt.Orientation.Horizontal, "Notebook"); + model.setHeaderData(Global.noteTableTitlePosition, Qt.Orientation.Horizontal, "Title"); + model.setHeaderData(Global.noteTableChangedPosition, Qt.Orientation.Horizontal, "Date Changed"); + model.setHeaderData(Global.noteTableAuthorPosition, Qt.Orientation.Horizontal, "Author"); + model.setHeaderData(Global.noteTableSourceUrlPosition, Qt.Orientation.Horizontal, "Source Url"); + model.setHeaderData(Global.noteTableSubjectDatePosition, Qt.Orientation.Horizontal, "Subject Date"); + model.setHeaderData(Global.noteTableSynchronizedPosition, Qt.Orientation.Horizontal, "Synchronized"); + header.sortIndicatorChanged.connect(this, "resetViewport()"); + + proxyModel = new NoteSortFilterProxyModel(this); + proxyModel.setSourceModel(model); + + setAlternatingRowColors(false); + setModel(proxyModel); + + setSortingEnabled(true); + int sortCol = proxyModel.sortColumn(); + SortOrder sortOrder = proxyModel.sortOrder(); + sortByColumn(sortCol, sortOrder); + + setSelectionBehavior(SelectionBehavior.SelectRows); + setSelectionMode(SelectionMode.SingleSelection); + verticalHeader().setVisible(false); + hideColumn(Global.noteTableGuidPosition); // Hide the guid column + setShowGrid(false); + setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers); + + QFontMetrics f = QApplication.fontMetrics(); + fontHeight = f.height(); + rowChanged = new Signal1(); + resetViewport = new Signal0(); + } + + // This should rescroll to the current item in the list when a column is + // sorted. Somehow I can't get this to work, but this part is correct. + @SuppressWarnings("unused") + private void resetViewport() { +// if (currentIndex() == null) +// return; + +// resetViewport.emit(); + } + + + public void load(ListManager runner, boolean reload) { + + proxyModel.clear(); + setSortingEnabled(true); + for (int i=0; i0) setColumnWidth(Global.noteTableCreationPosition, width); + width = Global.getColumnWidth("noteTableChangedPosition"); + if (width>0) setColumnWidth(Global.noteTableChangedPosition, width); + width = Global.getColumnWidth("noteTableTitlePosition"); + if (width>0) setColumnWidth(Global.noteTableTitlePosition, width); + width = Global.getColumnWidth("noteTableTagPosition"); + if (width>0) setColumnWidth(Global.noteTableTagPosition, width); + width = Global.getColumnWidth("noteTableGuidPosition"); + if (width>0) setColumnWidth(Global.noteTableGuidPosition, width); + width = Global.getColumnWidth("noteTableNotebookPosition"); + if (width>0) setColumnWidth(Global.noteTableNotebookPosition, width); + width = Global.getColumnWidth("noteTableSourceUrlPosition"); + if (width>0) setColumnWidth(Global.noteTableSourceUrlPosition, width); + width = Global.getColumnWidth("noteTableAuthorPosition"); + if (width>0) setColumnWidth(Global.noteTableAuthorPosition, width); + width = Global.getColumnWidth("noteTableSubjectDatePosition"); + if (width>0) setColumnWidth(Global.noteTableSubjectDatePosition, width); + width = Global.getColumnWidth("noteTableSynchronizedPosition"); + if (width>0) setColumnWidth(Global.noteTableSynchronizedPosition, width); + + int from = header.visualIndex(Global.noteTableCreationPosition); + int to = Global.getColumnPosition("noteTableCreationPosition"); + if (to>=0) header.moveSection(from, to); + + from = header.visualIndex(Global.noteTableTitlePosition); + to = Global.getColumnPosition("noteTableTitlePosition"); + if (to>=0) header.moveSection(from, to); + + from = header.visualIndex(Global.noteTableTagPosition); + to = Global.getColumnPosition("noteTableTagPosition"); + if (to>=0) header.moveSection(from, to); + + from = header.visualIndex(Global.noteTableNotebookPosition); + to = Global.getColumnPosition("noteTableNotebookPosition"); + if (to>=0) header.moveSection(from, to); + + from = header.visualIndex(Global.noteTableChangedPosition); + to = Global.getColumnPosition("noteTableChangedPosition"); + if (to>=0) header.moveSection(from, to); + + from = header.visualIndex(Global.noteTableSourceUrlPosition); + to = Global.getColumnPosition("noteTableSourceUrlPosition"); + if (to>=0) header.moveSection(from, to); + + from = header.visualIndex(Global.noteTableAuthorPosition); + to = Global.getColumnPosition("noteTableAuthorPosition"); + if (to>=0) header.moveSection(from, to); + + from = header.visualIndex(Global.noteTableSubjectDatePosition); + to = Global.getColumnPosition("noteTableSubjectDatePosition"); + if (to>=0) header.moveSection(from, to); + + from = header.visualIndex(Global.noteTableSynchronizedPosition); + to = Global.getColumnPosition("noteTableSynchronizedPosition"); + if (to>=0) header.moveSection(from, to); + + proxyModel.filter(); + + QFontMetrics f = QApplication.fontMetrics(); + fontHeight = f.height(); + for (int i=0; i model.rowCount()) + model.insertRow(0); + + if (row < 0) { + row = model.rowCount(); + model.insertRow(row); +// row = model.rowCount()-1; + } + + QColor backgroundColor = new QColor(QColor.white); + QColor foregroundColor = new QColor(QColor.black); + + if (runner.titleColors != null && runner.titleColors.containsKey(tempNote.getGuid())) { + int color = runner.titleColors.get(tempNote.getGuid()); + backgroundColor.setRgb(color); + } + if (backgroundColor.rgb() == QColor.black.rgb() || backgroundColor.rgb() == QColor.blue.rgb()) + foregroundColor.setRgb(QColor.white.rgb()); + + + QDateTime created = QDateTime.fromString(creationDate.toString(), fmt); + QDateTime changed = QDateTime.fromString(changedDate.toString(), fmt); + QDateTime subjectDateFormat = QDateTime.fromString(subjectDate.toString(), fmt); + model.setData(model.index(row, Global.noteTableCreationPosition), created.toString(fmt)); + model.setData(model.index(row, Global.noteTableChangedPosition), changed.toString(fmt)); + model.setData(model.index(row, Global.noteTableTitlePosition), tempNote.getTitle()); + model.setData(model.index(row, Global.noteTableTagPosition), tagNames); + model.setData(model.index(row, Global.noteTableGuidPosition), tempNote.getGuid()); + model.setData(model.index(row, Global.noteTableSubjectDatePosition), subjectDateFormat.toString(fmt)); + model.setData(model.index(row, Global.noteTableAuthorPosition), tempNote.getAttributes().getAuthor()); + model.setData(model.index(row, Global.noteTableSourceUrlPosition), tempNote.getAttributes().getSourceURL()); + model.setData(model.index(row, Global.noteTableNotebookPosition), runner.getNotebookNameByGuid(tempNote.getNotebookGuid())); + model.setData(model.index(row, Global.noteTableSynchronizedPosition), sync); + + for (int i=0; i 0) { + clearSelection(); + selectRow(0); + } + } + if (e.matches(StandardKey.MoveToEndOfDocument)) { + if (model.rowCount() > 0) { + clearSelection(); + selectRow(model().rowCount()-1); + } + } + super.keyPressEvent(e); + } + + @Override + public void contextMenuEvent(QContextMenuEvent event) { + QMenu menu = new QMenu(this); + if (Global.showDeleted) { + menu.addAction(restoreAction); + } else { + menu.addAction(addAction); + } + menu.addAction(deleteAction); + menu.addSeparator(); + menu.addAction(duplicateAction); + menu.addAction(noteHistoryAction); + menu.addAction(mergeNotesAction); + + QMenu titleColorMenu = new QMenu(); + titleColorMenu.setTitle("Title Color"); + menu.addMenu(titleColorMenu); + noteTitleColorWhite = new QAction(titleColorMenu); + noteTitleColorRed = new QAction(titleColorMenu); + noteTitleColorBlue = new QAction(titleColorMenu); + noteTitleColorGreen = new QAction(titleColorMenu); + noteTitleColorYellow = new QAction(titleColorMenu); + noteTitleColorBlack = new QAction(titleColorMenu); + noteTitleColorGray = new QAction(titleColorMenu); + noteTitleColorCyan = new QAction(titleColorMenu); + noteTitleColorMagenta = new QAction(titleColorMenu); + + noteTitleColorWhite.setText("White"); + noteTitleColorRed.setText("Red"); + noteTitleColorBlue.setText("Blue"); + noteTitleColorGreen.setText("Green"); + noteTitleColorYellow.setText("Yellow"); + noteTitleColorBlack.setText("Black"); + noteTitleColorGray.setText("Gray"); + noteTitleColorCyan.setText("Cyan"); + noteTitleColorMagenta.setText("Magenta"); + + titleColorMenu.addAction(noteTitleColorWhite); + titleColorMenu.addAction(noteTitleColorRed); + titleColorMenu.addAction(noteTitleColorBlue); + titleColorMenu.addAction(noteTitleColorGreen); + titleColorMenu.addAction(noteTitleColorYellow); + titleColorMenu.addAction(noteTitleColorBlack); + titleColorMenu.addAction(noteTitleColorGray); + titleColorMenu.addAction(noteTitleColorCyan); + titleColorMenu.addAction(noteTitleColorMagenta); + + noteTitleColorWhite.triggered.connect(this, "titleColorWhite()"); + + noteTitleColorWhite.triggered.connect(this, "titleColorWhite()"); + noteTitleColorRed.triggered.connect(this, "titleColorRed()"); + noteTitleColorBlue.triggered.connect(this, "titleColorBlue()"); + noteTitleColorGreen.triggered.connect(this, "titleColorGreen()"); + noteTitleColorYellow.triggered.connect(this, "titleColorYellow()"); + noteTitleColorBlack.triggered.connect(this, "titleColorBlack()"); + noteTitleColorGray.triggered.connect(this, "titleColorGray()"); + noteTitleColorCyan.triggered.connect(this, "titleColorCyan()"); + noteTitleColorMagenta.triggered.connect(this, "titleColorMagenta()"); + + menu.exec(event.globalPos()); + } + + + @SuppressWarnings("unused") + private void titleColorWhite() {noteSignal.titleColorChanged.emit(QColor.white.rgb());} + @SuppressWarnings("unused") + private void titleColorRed() {noteSignal.titleColorChanged.emit(QColor.red.rgb());} + @SuppressWarnings("unused") + private void titleColorBlue() {noteSignal.titleColorChanged.emit(QColor.blue.rgb());} + @SuppressWarnings("unused") + private void titleColorGreen() {noteSignal.titleColorChanged.emit(QColor.green.rgb());} + @SuppressWarnings("unused") + private void titleColorYellow(){noteSignal.titleColorChanged.emit(QColor.yellow.rgb());} + @SuppressWarnings("unused") + private void titleColorBlack() {noteSignal.titleColorChanged.emit(QColor.black.rgb());} + @SuppressWarnings("unused") + private void titleColorGray() {noteSignal.titleColorChanged.emit(QColor.gray.rgb());} + @SuppressWarnings("unused") + private void titleColorCyan() {noteSignal.titleColorChanged.emit(QColor.cyan.rgb());} + @SuppressWarnings("unused") + private void titleColorMagenta() {noteSignal.titleColorChanged.emit(QColor.magenta.rgb());} + + + + @Override + public void dragEnterEvent(QDragEnterEvent event) { + StringBuffer guid = new StringBuffer(1000); + + showColumn(Global.noteTableGuidPosition); + List selections = selectionModel().selectedRows(); + hideColumn(Global.noteTableGuidPosition); + + if (selections.size() > 0) { + QModelIndex index; + for (int i=0; i ix = proxyModel.itemData(index); + guid.append((String)ix.values().toArray()[0]); + guid.append(" "); + } + } + event.mimeData().setData("application/x-nevernote-note", new QByteArray(guid.toString())); + event.accept(); + + } + + @Override + public void dropEvent(QDropEvent event) { + if (event.source() == this) + event.ignore(); + } + + // Return a column width + public int getColumnWidth(int col) { + return columnWidth(col); + } + +/* + @Override + public void scrollTo(final QModelIndex index, ScrollHint hint) { + QRect area = viewport().rect(); + QRect rect = visualRect(index); + + if (rect.top() < area.top()) + verticalScrollBar().setValue( + verticalScrollBar().value() + rect.top() - area.top()); + else if (rect.bottom() > area.bottom()) + verticalScrollBar().setValue( + verticalScrollBar().value() + Math.min( + rect.bottom() - area.bottom(), rect.top() - area.top())); + update(); + } + + @Override + protected void updateGeometries() { + verticalScrollBar().setPageStep(viewport().height()); + verticalScrollBar().setRange(0, Math.max(0, viewport().height())); + } + @Override + protected int verticalOffset() { + return verticalScrollBar().value(); + } +*/ + +} diff --git a/src/cx/fbn/nevernote/gui/TagLineCompleter.class b/src/cx/fbn/nevernote/gui/TagLineCompleter.class new file mode 100644 index 0000000000000000000000000000000000000000..c4fb8eec4d51991467b794bc221d9b7bb7e1d284 GIT binary patch literal 3239 zcma)8X?GJ<7=CV+hK7McOF;@{ZE2GN0cEwdQYuI!l%qvG?w*M zp*?jvHacR(EMwfTt-NEzGDS1CU(X~=%jnPN#m4EMXR$ZiV_mGh^va(KZxTR~`2x#Bn9Qk=7aJ%$Olr zbocV*>8YY^8l8?ncY%Rwg#+*rw&Z6wKw*MpmK2^>eHx}Owx&!9V!3}K-{(*wx+Y+FAgg@v&IO%h?ThI-UVgrypmVYxz> z5nPfB4AInC1u31@qa7U~tWfBz37^W_Mr^Os)~^?gLBlGTjyY~RXEbyoqR=4QajQ^1 zAmP#43Z`(;Eje~+Scz2%jm)tsgu<#x;F!vppxz)l9w_EU412#ml4UlHiF``WCUx7C zb$K)395bmcisk>b1L;@v6ed9x5F0xq)hH^gsM+lCjH=aIR~$?04t-Kh514eDr}hP@ zYjd^Tq>d+hS0H{`LpRnb%p572*|ggLo?sN7(a?)$DGEW~>whzE?Xitf^Rz;9Iqbyz zBgruO&>zB9wtjUlYIqLYWHQ)hPGQb{JSM(B4bLk;e8e@pfSuBbCyRQPd^{9x_sDT0 z<#b05Nd>z!3`i4AqdMIgMM@~;y0LPijkTq-(;lXtGp0=cj6p|Fo!F(1mDeGUS!S^2 ze#Vt)_Ly-c{Whc_==Iw{4byQ*VI|#6(MNqF1;^G?PTVna-Y5#;ungu&yS{2{Nwk+F zh8D&!ngkhL!w6DDh6K9)9@R9p!G+CX7#c>A;Uuz+Tz=fxmp?@gJL7`=FiZ`{ae@)- z{HgwY(IW1gW%23AAs>Q8Sv@Ra4P!V-8+V>H)5`>I%A|%stXrhy$?t(MY!o$&iJ^-8wGx>?L@h#(2rSXHKgdoiW(yWdvtgY?Lsq5nXCV(q^q~W6InSe8> zG@~T;iH1*QH<-#AI&Y@%V7_RljP0fjvSv4h3AglWfn7n1Tb5z>XZ1qCD1`7O@0A)Y zl}BcIT2C0_SjuGl{DTmHPejaBh$|na@xx1`vJP`i+3~DVt}p(Ec-DYf{GQF#IePK& zHx|8t#%R}dG)JR9qq&56(OB`k^lgtii*Kk^kHR`Yw28+bVrX=C7a zI_5-Cgp?6*%V;5H zV0uBO6vlcYw1L<1Ml8lAH|7%0U!{a4*zKas7}$fojJJ>Pdzs0Zh-HvFeyGKK+&`ht z12uIftLyBZq)wmQ1(iBou+(?-A7qp}QC9QfEev1B5#n~_Hs+GEVbXV0c4VuBm;F80 z&>+tXN=Oe~P-=m9aO~>6zsh7M{LfrN#^3AT5V%H7kb>sGO=Nwzg+5}(jpV}e+AhH< z;nZaW1HBglsyQImH*rqkTZCFK-}|HW3R=3V-?)j_d>FdmQw!z9HNSfA5}%KBmGDNF z0O1ibfF?d~p?Lc!-K}UvKh?F3irP+!wsCg{;=G3ju#*HNki;&IivgVH^A{xK8xrz8 z&ws}O+~%q1u-7H|PMO3GwBQ2XCOdJ?m3Le^cfxV^eDrw~@8UfIJjht@(=Je<*t5S+ zaT~(zfAgRB^m~{GKiew=-l6yhA*DKfcQN}eT6~Pce{>c4K5#Xlb1lu+ATmvo!Vg`k ziYooCDjOLTI7E(z*<6R&G)LV+yoPG1sIj4}#s?adooNiJWM1)mHvMdJ*Sy0$rao4X kNM3)*oB(g6dZZ?3FI tags; + private List currentTags; + private QStringListModel model; + private final TagLineEdit editor; + + public TagLineCompleter(TagLineEdit e) { + editor = e; + setWidget(editor); +// editor.setCompleter(this); + currentTags = new ArrayList(); + setTagList(new ArrayList()); + setCaseSensitivity(CaseSensitivity.CaseInsensitive); + } + + public List getTagList(){ + return currentTags; + } + + public void update(List t, String prefix) { + currentTags = t; + + buildModelList(); + + setCompletionPrefix(prefix); + if (!prefix.trim().equals("")) + complete(); + } + + public List getTags() { + return tags; + } + + private List buildModelList() { + + model = (QStringListModel) model(); + if (model == null) { + model = new QStringListModel(); + setModel(model); + } + for (int i=0; i newTagList = new ArrayList(); + + for (int i=0; i t) { + tags = t; + resetList(); + buildModelList(); +// model = new QStringListModel(buildModelList(), this); +// setModel(model); + } + + public void resetList() { + currentTags.clear(); + } + + +} diff --git a/src/cx/fbn/nevernote/gui/TagLineEdit.class b/src/cx/fbn/nevernote/gui/TagLineEdit.class new file mode 100644 index 0000000000000000000000000000000000000000..5a7df302d84203e96eb258a47a0e156b8fa7524b GIT binary patch literal 4222 zcma)9iC+}w8GeR6h8+e)1Qdc12~}9d1sX}RARfenhzG%7&@?#g4lrieU3X^@+otJZ z)5IR>t?7{_z3h=5v9g%h*!xQF<6r21(O>QJ&g`zhQsMWLo$veRJ)ie^-*0^9zi-_J z(1m}gC{xfBn~hA2Cn5=R#!M%Yjv1NET9K2+55z4;g6$po`>K@u+RE#Prax zHJLE%1Jjn{nCTX8*F{4icj;u)rUGNNdc9sqS;w*?gI31L?-z#H*HapHAN}c$G1;G- zPT3~oP_S+AURV_cCD4gvESnijW(dh@6YQW~u-8ghPM?DHtxKZrX&X_{x%9Nx1)*3u zGj6a-7gMIxucyz|@%Ja=rUoDCbgaV$1-{m{5f$}JXO+Nf*ogZ?xlut&>q@ZGX$T~Y zju12zO{@0Pp=7ev$v%JRcc!e2g65UuCX9w{lcN-`T1s>U zb&IW&&v_3!m&mR_e+AluOfr2U znXw!znQ(h&K*KPeP;ru>FP(KdMsSMwX0qcMcla@v)`5Yx(&-{bMs=LV85x~vYno+f zT}Cd1_h3xL(+W0}u;GxM95-woXA$&9)uX0uP0Oef>*G3N;K;48jf^vph?}#=C;m_N z1Lfc=h}M*(V2RvvQLA`{?c`?dj?;bVv~f|mrr{jwL_eV;iIjpsCS_Yoo1}pDnNmC| zkOprW@?p(g^I};?7Bd9ih%=W(wad3$+i96kvpO!~y~NVwrLkgf7F0P>6-sMfna5H| z`d0>6K*yX;jmg;HI$l7P<2jW!C#+f0H(_4z=vzVEw3%?co!@52glL%zsbt#bG(|Z@ zOL)ALNgUn^Du*2-_RLWu<u(PJHW9!1+D1cO2EDbN=i!!E;$m*(&m+>WnW291Mf&sKIv{I;f ziIsdH9MNAP=uKkj6&+ubhA4NEo|+{1nvSpI2&2rHjtnSC^_x1rCH)z+&BUZLC1Tff zdbqr`TQWx1k)Z=3&?B6k$D1l{DrhXZg%?Qbcnh~= zLU0Dkm9Wgsw?Mk(B*l6{cpE=cahqY>%d{)3#4FMK}c~Y$0oW{16VHOy)jU)pFhO z$?|d-k}zDCLFbD1t9#DR5W6Z8L>4y?4Oj0LDc>CSyg{oz?BnlNMkc?0 zG&7PGG-4Zft^Am8!ybe&$j_P~?7)6X)p^mNACGd!xNram8TlcuB`5FXFjoo&@ECt3 zi-@}?Dhy-K>pUoP9ZSmcQVe^_fxO`|25`hvR^}OIB_*zgx6ffPoWrr*G&AUH%;E84 z?KwPo9Z%(8bo;B#XrR{r3f8yR`u%5fnB==?;2J_A6b;38$l z?-uew7Je5?-Obb=LK7Y)q>m8FD1UniXde#qcL;lV3-99%wI9#%`67Y5LKp>$32HOn zBFI-EYYjMC47KqKH8t9{Qa*HMf_2i!~%0Ex}k1>MX@ZVw3K^2OM;ldxwc!!LrTzsk`?f!cK3I$*A znDSz=h>tNql_oEH^~>S1S3hnqvyhWfe|x@+f!aXXtI!*}1J&lSYtY+$jsCcly58?f ze4;y88>EEh>khKwep3FW(e|78%sjrZJ%=l<(3R>hb6M}_PYz$r;ni?sZ6Gera`?vC z0Lk&~yZrCte+)w2pN5f5>FD?)3|^$EZb9V z$qswj6-##6?S2k#LhY4oEsOX)LhPgc^Y}hj(r;6Eoy7~#_CfrBtDp;fBYbzzxe$24 zA1MD1>ZG%HFR*OhB=P3N)7+Oaiz;$+R}Mdt2hq5GH_J8j42&_(v&_6qlCoS&H7SF3m%1w~8QwzK{ z6uma!4|s>Rg>pV9H8lT6F3a#I{F%>Y0<{@`!QVI@xAXaTJ~#6D4?f@KjrY&J_5TA$ Crx>RI literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/gui/TagLineEdit.java b/src/cx/fbn/nevernote/gui/TagLineEdit.java new file mode 100644 index 0000000..f35cc92 --- /dev/null +++ b/src/cx/fbn/nevernote/gui/TagLineEdit.java @@ -0,0 +1,106 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.gui; + +import java.util.ArrayList; +import java.util.List; + +import com.evernote.edam.type.Tag; +import com.trolltech.qt.core.QEvent; +import com.trolltech.qt.gui.QLineEdit; + +import cx.fbn.nevernote.Global; + +public class TagLineEdit extends QLineEdit { + private String text; + private final boolean changed; + public Signal2, String> text_changed = new Signal2, String>(); + public TagLineCompleter tagCompleter; + public Signal0 focusLost = new Signal0(); + + public TagLineEdit(List allTags) { + textChanged.connect(this, "textChanged(String)"); + tagCompleter = new TagLineCompleter(this); + text_changed.connect(tagCompleter, "update(List, String)"); + tagCompleter.activated.connect(this, "completeText(String)"); + changed = false; + } + + public boolean hasChanged() { + return changed; + } + + @SuppressWarnings("unused") + private void textChanged(String t) { + text = t; + int cursor_pos = cursorPosition(); + String temp_text = text.substring(0,cursor_pos); + int delimeter = temp_text.trim().lastIndexOf(Global.tagDelimeter); + String prefix = ""; + if (delimeter > 0) + prefix = temp_text.substring(delimeter+1).trim(); + else + prefix = temp_text.trim(); + + List newTags = new ArrayList(); + List currentTags = new ArrayList(); + String list[] = text.split(Global.tagDelimeter); + for (String element : list) { + currentTags.add(element.trim()); + } + + text_changed.emit(currentTags, prefix.trim()); + + } + + @SuppressWarnings("unused") + private void completeText(String text){ + int cursor_pos = cursorPosition(); + String before_text = text().substring(0,cursor_pos); + String after_text = text().substring(cursor_pos); + int prefix_len = before_text.lastIndexOf(Global.tagDelimeter); + if (prefix_len == -1) { + prefix_len = cursor_pos; + before_text = ""; + } else { + before_text = before_text.substring(0,cursor_pos-1); + } + int nextTagPos = after_text.indexOf(Global.tagDelimeter); + if (nextTagPos == -1) { + nextTagPos = 0; + after_text = ""; + } + setText(before_text +text +Global.tagDelimeter +" " +after_text); + setCursorPosition(cursor_pos - prefix_len + text().length() +2); + } + + public void setTagList(List t) { + tagCompleter.resetList(); + tagCompleter.setTagList(t); + } + + @Override + public boolean event(QEvent e) { + if (e.type().equals(QEvent.Type.FocusOut)) { + focusLost.emit(); + } + return super.event(e); + } +} diff --git a/src/cx/fbn/nevernote/gui/TagTreeWidget.class b/src/cx/fbn/nevernote/gui/TagTreeWidget.class new file mode 100644 index 0000000000000000000000000000000000000000..2c3ccc7dfed784653cb0ac6cd97cc52bc6aba409 GIT binary patch literal 11407 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 literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/gui/TagTreeWidget.java b/src/cx/fbn/nevernote/gui/TagTreeWidget.java new file mode 100644 index 0000000..8ae338d --- /dev/null +++ b/src/cx/fbn/nevernote/gui/TagTreeWidget.java @@ -0,0 +1,343 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.gui; + +import java.util.ArrayList; +import java.util.List; + +import com.evernote.edam.type.Tag; +import com.trolltech.qt.core.QByteArray; +import com.trolltech.qt.core.QMimeData; +import com.trolltech.qt.core.Qt; +import com.trolltech.qt.core.Qt.MatchFlag; +import com.trolltech.qt.core.Qt.MatchFlags; +import com.trolltech.qt.core.Qt.SortOrder; +import com.trolltech.qt.gui.QAbstractItemView; +import com.trolltech.qt.gui.QAction; +import com.trolltech.qt.gui.QBrush; +import com.trolltech.qt.gui.QColor; +import com.trolltech.qt.gui.QContextMenuEvent; +import com.trolltech.qt.gui.QDragEnterEvent; +import com.trolltech.qt.gui.QDragMoveEvent; +import com.trolltech.qt.gui.QHeaderView; +import com.trolltech.qt.gui.QIcon; +import com.trolltech.qt.gui.QMenu; +import com.trolltech.qt.gui.QTreeWidget; +import com.trolltech.qt.gui.QTreeWidgetItem; + +import cx.fbn.nevernote.Global; +import cx.fbn.nevernote.filters.TagCounter; +import cx.fbn.nevernote.signals.NoteSignal; +import cx.fbn.nevernote.signals.TagSignal; +import cx.fbn.nevernote.sql.DatabaseConnection; + +public class TagTreeWidget extends QTreeWidget { + private QAction editAction; + private QAction deleteAction; + private QAction addAction; + public TagSignal tagSignal; + public NoteSignal noteSignal; + private boolean showAllTags; + private final DatabaseConnection db; + + + public TagTreeWidget(DatabaseConnection d) { + List headers = new ArrayList(); + if (Global.tagBehavior().equalsIgnoreCase("HideInactiveCount")) + headers.add("Tags"); + else + headers.add("Tags"); + headers.add(""); + showAllTags = true; + setAcceptDrops(true); + setDragEnabled(true); + setColumnCount(2); + header().setResizeMode(0, QHeaderView.ResizeMode.ResizeToContents); + header().setResizeMode(1, QHeaderView.ResizeMode.Stretch); + header().setMovable(false); + db = d; + tagSignal = new TagSignal(); + noteSignal = new NoteSignal(); + setDragDropMode(QAbstractItemView.DragDropMode.DragDrop); + setHeaderLabels(headers); + setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection); + + int width = Global.getColumnWidth("tagTreeName"); + if (width>0) + setColumnWidth(0, width); + + } + + public void setEditAction(QAction e) { + editAction = e; + } + public void setDeleteAction(QAction d) { + deleteAction = d; + } + public void setAddAction(QAction a) { + addAction = a; + } + + public void load(List tags) { + Tag tag; + List index = new ArrayList(); + QTreeWidgetItem child; + + //Clear out the tree & reload + clear(); + String iconPath = new String("classpath:cx/fbn/nevernote/icons/"); + QIcon icon = new QIcon(iconPath+"tag.png"); + + Qt.Alignment ra = new Qt.Alignment(Qt.AlignmentFlag.AlignRight); + + // Create a copy. We delete them out as they are found + List tempList = new ArrayList(); + for (int i=0; i 0) { + for (int i=0; i children = findItems("*", flags); + for (int i=0; i counts) { + + MatchFlags flags = new MatchFlags(); + flags.set(MatchFlag.MatchWildcard); + flags.set(MatchFlag.MatchRecursive); +// List children = new ArrayList(); + List children = findItems("*", flags); + + QBrush black = new QBrush(); + black.setColor(QColor.black); + QBrush blue = new QBrush(); + blue.setColor(QColor.blue); + if (!Global.tagBehavior().equalsIgnoreCase("ColorActive")) + blue.setColor(QColor.black); + + for (int i=0; i 0 || children.get(j).isSelected()) { + children.get(j).setForeground(0, blue); + children.get(j).setForeground(1, blue); + QTreeWidgetItem parent = children.get(j); + while (parent != null) { + parent.setForeground(0, blue); + parent.setForeground(1, blue); + parent.setHidden(false); + parent = parent.parent(); + } + } + } + } + } + } + + + public boolean selectGuid(String guid) { + MatchFlags flags = new MatchFlags(); + flags.set(MatchFlag.MatchWildcard); + flags.set(MatchFlag.MatchRecursive); +// List children = new ArrayList(); + List children = findItems("*", flags); + + for (int i=0; i children = findItems("*", flags); + + for (int j=0; j finished; + public String guid; + + public Thumbnailer(String g, QSize s) + { + guid = g; + finished = new Signal1(); + page = new QWebPage(); + painter = new QPainter(); + + page.mainFrame().setScrollBarPolicy(Orientation.Horizontal, ScrollBarPolicy.ScrollBarAlwaysOff); + page.mainFrame().setScrollBarPolicy(Orientation.Vertical, ScrollBarPolicy.ScrollBarAlwaysOff); + page.loadFinished.connect(this, "loadFinished(Boolean)"); + } + + public void setContent(String content) { + QFile file = new QFile(Global.currentDir+"res/thumbnail-"+guid+".html"); + file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.WriteOnly)); + file.write(new QByteArray(content)); + file.close(); + page.mainFrame().load(new QUrl(QUrl.fromLocalFile(file.fileName()).toString())); + } + + + + public void loadFinished(Boolean ok) + { + if (!ok) + return; + + QSize size = page.currentFrame().contentsSize(); + if (size.height() > 2000) + size.setHeight(800); + if (size.width() < 600) + size.setWidth(600); + if (size.width() > 2000) + size.setWidth(600); + + page.setViewportSize(size); + image = new QImage(size, QImage.Format.Format_RGB32); + painter.begin(image); + + page.mainFrame().render(painter); //<<<< THIS CAN LOCKUP if height too big!!!! + painter.end(); + + image.save(Global.currentDir+"res/thumbnail-"+guid+".png"); + finished.emit(guid); + } +} diff --git a/src/cx/fbn/nevernote/gui/TrashTreeWidget.class b/src/cx/fbn/nevernote/gui/TrashTreeWidget.class new file mode 100644 index 0000000000000000000000000000000000000000..01fea6d2cce20905a39320ecb040973c766a990e GIT binary patch literal 2986 zcma)8`BxKH6#gEI32|JS;)bH2Kp_y*TI+^V5m0FpghH|DKAAkj*vU+sOc1)+ec#)E zq&+qClymwA^pEQ4_hw>%kWqig%e%})g1M+J75r8l+tMDO6kj|?pev`sj9*#R2U(2gAfd(x&YXDY>Bn)H;Dj!)bqb$dOm_~fxV62qc|qeYgl@@ zT++Rz3){e&hGUmgF&sg!!qOGN34yNWL{C#Tf_{Mmjb^S?Op7>`nx`}jVn`setXma% z;}$8}4Esjzwluuaq3xc;(1+eAMg%%Ml`bbsc0s*6sUd}@NuFLRNjoo)+^p{b4cqk9 zAdM;&r!+i^(*jY?3FHMj2b)4Tj@}5)sx*E?a!z})7{eKKs^x-)QCy_YOh82vlY4MF zB=yvHMok?X)9^el2gerViYKt2#~Qh%a1>VrpmJkU!xXMEN%eew!6~I#WtM^>Fcg;S z8wI5VsjUOo@j?XC0;ijMIi4#s0*0sL7fpG$Z(dpq8jCQ)TG8+#(#+0G#q!Mh7lAV& z4nJHQ<0CMm;Ra@zzT~g2QP~nWALiC0)T+9Os^p$!+N%=YM(cw-3j%f|1ic@wx~R`I zOa3vEgC)P0<~_zWBkju6va}iC;V^e58bleV2wn{>MWr%^EM8Yd`vyxqOmEO|{e;Wn zEe&rYN^h7wLD!5S2euA_RodLCMqC;sSkoN^%gO21tiu-A!&2II*l=8#nwxb@+hd5c zSkhqPHruUSk+e3}1n=e}O*E=GGFR{Q?aX{dXcIlYU?XmZqpe8N1i~V%C{;rw@9Kpq z#?7sTEVQsDw+Q+ayWngiB_Zu&>j@1NEHg`sW>HS+9_Pb}a3(V~q0uN-1iIM^Ez{6d zO{P|o^JHW-@~wvN z5LffVFl31k!|HcybeIaUd8gtU@~WvW0iFJQ-XP$lYA6EQv~5dwLJe41j^LNjLTc<+ z0=u@fI`lFgt-MJIw5W>+pW68xL6mC;cVm3t!v7tK;rodF&Zib=Tx0&*eo7Bu7x()E zDeT4`?kJDF{P6;!t{OF6mng%Df}M#qJei2^tKz_h!reZMA+#Y$<)?h5S|DCiDsZ^2 z>OKv(QB`IgN3!vwYv@U@<9K!*ec9o^FtCP1e7K5a70;~UISQT0uHoEFvUQ}2^T}3a z`cfi3P5=qYOeFrmwJI_jU*YiL E1BPfKrvLx| literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/gui/TrashTreeWidget.java b/src/cx/fbn/nevernote/gui/TrashTreeWidget.java new file mode 100644 index 0000000..c05d923 --- /dev/null +++ b/src/cx/fbn/nevernote/gui/TrashTreeWidget.java @@ -0,0 +1,105 @@ +/* + * This file is part of NeverNote + * Copyright 2009 Randy Baumgarte + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * +*/ + +package cx.fbn.nevernote.gui; + +import java.util.ArrayList; +import java.util.List; + +import com.trolltech.qt.core.QByteArray; +import com.trolltech.qt.core.Qt; +import com.trolltech.qt.gui.QAbstractItemView; +import com.trolltech.qt.gui.QAction; +import com.trolltech.qt.gui.QBrush; +import com.trolltech.qt.gui.QColor; +import com.trolltech.qt.gui.QContextMenuEvent; +import com.trolltech.qt.gui.QDragEnterEvent; +import com.trolltech.qt.gui.QHeaderView; +import com.trolltech.qt.gui.QIcon; +import com.trolltech.qt.gui.QMenu; +import com.trolltech.qt.gui.QTreeWidget; +import com.trolltech.qt.gui.QTreeWidgetItem; + +public class TrashTreeWidget extends QTreeWidget { + private QAction emptyAction; + private QTreeWidgetItem trashItem; + private Integer trashCount; + + public void setEmptyAction(QAction a) { + emptyAction = a; + } + + + public TrashTreeWidget() { + trashCount = 0; + } + + public void updateCounts(Integer cnt) { + QBrush gray = new QBrush(); + gray.setColor(QColor.gray); + QBrush black = new QBrush(); + black.setColor(QColor.black); + + trashCount = cnt; + trashItem.setText(1, trashCount.toString()); + header().resizeSection(1, 0); + if (trashCount > 0) { + trashItem.setForeground(0, black); + trashItem.setForeground(1, black); + } else { + trashItem.setForeground(0, gray); + trashItem.setForeground(1, gray); + } + } + + public void load() { + String iconPath = new String("classpath:cx/fbn/nevernote/icons/"); + QIcon trashIcon = new QIcon(iconPath+"trash.png"); + trashItem = new QTreeWidgetItem(); + trashItem.setIcon(0, trashIcon); + trashItem.setText(0, "Trash"); + Qt.Alignment ra = new Qt.Alignment(Qt.AlignmentFlag.AlignRight); + trashItem.setTextAlignment(1, ra.value()); + List headers = new ArrayList(); + headers.add(""); + headers.add(""); + setHeaderLabels(headers); + setColumnCount(2); + header().setResizeMode(0, QHeaderView.ResizeMode.ResizeToContents); + header().setResizeMode(1, QHeaderView.ResizeMode.Stretch); + header().setMovable(false); + setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection); + addTopLevelItem(trashItem); + + } + + @Override + public void contextMenuEvent(QContextMenuEvent event) { + QMenu menu = new QMenu(this); + menu.addAction(emptyAction); + menu.exec(event.globalPos()); + } + + + @Override + public void dragEnterEvent(QDragEnterEvent event) { + event.mimeData().setData("application/x-nevernote-trash", new QByteArray(currentItem().text(1))); + event.accept(); + } +} diff --git a/src/cx/fbn/nevernote/icons/appearance.jpg b/src/cx/fbn/nevernote/icons/appearance.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2dc797b55454a9718047afab30b218341e6956f1 GIT binary patch literal 3696 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 literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/attribute.png b/src/cx/fbn/nevernote/icons/attribute.png new file mode 100644 index 0000000000000000000000000000000000000000..7f6a51a39d429152fa01e1983c30bdece9ea8352 GIT binary patch literal 41307 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 Ubf>H7uOa||iJ=9q66+H4e=$78`2YX_ literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/back.png b/src/cx/fbn/nevernote/icons/back.png new file mode 100644 index 0000000000000000000000000000000000000000..fd13531da30f58c253a859a82af76e4228c4a596 GIT binary patch literal 25627 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 SE#EEu0H`RukS~=r@&6z1I>HJ7 literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/bold.gif b/src/cx/fbn/nevernote/icons/bold.gif new file mode 100644 index 0000000000000000000000000000000000000000..8711be21583eabfd233e4a25c21eb5bd3acde3fa GIT binary patch literal 104 zcmZ?wbhEHb6lD-)n8*ME5AHt((+oNw3MB5p;mE+uA>*-O!NFz*Aub<|2MZ3j3n)9K z>D1Q$*KOMR%SMKMkWTJq>TUr zBQrA-6EinAD@2-+iJ66gRgg_l$WYiZQAsVZu(+{l@y1OTjhtLULQ5u2TDa(-vZ`}X z5m2`zBgkl&u^^g}1t`J_lu{OCU}9oqWlZAvIPj2tMOlE`SNqrU8|}HC{`t>PT7U7ot4`3W2OP@6H9KmP zzo|crh)UOsFITZU2mn`T6?Y!rL1RaK{8(5E3`GZ{3Rqc&pm1} ze*D31-(=3zRBkO#iLl$e+n-scwKF*t%FT5xk@xzV`6I|Svu@}9CGXDc)QsWodK4lw zWx29+Ph;rG@8L^qkDR)8IXR_eMN_q}^y<)iSI@sY{VgmrX{W_kqjeV(6{@D+bt)_a zIZ~_i$hKD9qbv)RRlO`2DtwKuq>FdT_3zR)x^8^AP%kQa!nT>Yo-a>Xu6a{YUD zX0>r^%#5?8roF8_c~L79Cg!GUdHiS4KJeg2gTmuu?p>?GWs}R&9*RB)*D{jfE}izf z#bVwTR`tU9e14j9Uhay!o7>Cha&^^%TR}Vpx4NVxZfhMcDeOJ@_Q2BqDJwoIG)>;2 zG`Tv~&*$~!Wy`K;?2&)jvHoT3^q>KGobaWfzw{tenntUn+Xdi8N_h zk(39@i#?A=NPqHwc+2zh3R!jKcz0(FzhWJo9kQ9)%redv=d~(Vi{86?`rYeqp=w%r zlVr1GJb9;!6m40!cY@WYMfF`fvo_y*di;d;O?RK!j)teZS#}&!Jnn zyn6hOwI14ermco!I{U74r%Nx73r(sE(@>3@6SCxZ>b!?q4=ta$vhqDPeCfL+x!Lvt z=c~ncqO~VqFbQg%5c0ZHy79sJz@^_N-nw&a))$Uk=k4#mdFmU>8s1`1S6)_7VSoL2 z%;rVj+r@LgeVMAEQ!r^w+vVOr5sPvsq}-h=sN3=4@q+&hfuBz*|FmDZx^=eS=CoPy zU9V1s9cNzX{&cl+O=;;r)2*R}&5w%ow{G=|{ZrL`E4Sy?;{x-$R%`DRd=C5(uxoAX zyE`>aD;G`m{2H|T-i}Jq;0T5U2L@q>tLox6?b>%~+g+9Ay}M;|kK*PjR+f`*-h8_{ zZvBH`CIq$wA@$839Mxsd1t2{p5;spZsUIl&vi~vtSw9-M-7s zn#Q?r4>%P1r?Rh>P}`Y!dHucR>%3RSRB$p{9^-CKZv6E=oPFJ_*vr#ZqQ%^!ns~iR zRj2T9&xxsY3|%*OpAW;0`^ssuLdF8gN;YAaZhJ^DRQu;v1+9$Qsyh3v#{D@VSy!gz zZ(01WD!DV`s@IZROJm=k|D?7rZ1Lv5i;h2ATGjS5XL8z%)54L_-8n5wwC6gd%>REA E040n*NB{r; literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/delete.png b/src/cx/fbn/nevernote/icons/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..93e171f25296242c50707687cff5d936924f0725 GIT binary patch literal 42797 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 GoBsjJ44*at literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/down.png b/src/cx/fbn/nevernote/icons/down.png new file mode 100644 index 0000000000000000000000000000000000000000..4f26b0d2a76c66b9f3c96a2d10272e491fc9b4af GIT binary patch literal 25128 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 literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/encrypt.png b/src/cx/fbn/nevernote/icons/encrypt.png new file mode 100644 index 0000000000000000000000000000000000000000..d555dea63edb24466a82443ceb917c8a021a9ebd GIT binary patch literal 2071 zcmV+y2;voZL=IOonJOW;~gg=xt7u8NuKht(M0R#;eA9c>T-(6wvV%FdlT0WuCeyLRome)QZ{{8z> zTU#q<&z_YhPo5OH$A$Oq-Kz&b1+<``z`)FLa>0ZN6SAgFnFUlXHR+l{J8=}Z_%QK2j|9( z8wxVd1`i&rdcb@4?w#scv_ppuUaqUFlOaQf$eTBBRIaM3lCfjQ%Inv!Rj#b8l!+53 z%BxqezDqgU-vC>fi=gxW}oC4i} ztRTUz4I4H{W@e_$ojX@%&YUUv`T446a@Y&d9XodPGNA#OIEQ@U!UY*OZk)V)`BLRG zXU@o^Nt2Yp-=j=O2mQTv?V5rKxX6%%y|!=PUck<^Ux@V3rcImDx_9qhv1G{-dG_p? z593y?T6vo9-Md$I?ARg2#l@16k|LKbU6OU{*2(JCs})$l=P+2D#zKAi^pT>XB25P{ zo-ncY@Zm$*x^=5Oefm`P?AfEBGu|40;OLq)YgFF8eY-dxBlOr4IoQZ2Nq=D3mMvSF^#}X5ZQDw2Zf=v2$o~Te4#?xjk5lm=ck<-P2p-JV zty`;;Cd010ygZpPV}?$Wot-T=Z{Cz+$Byab#b$q1@PZ?b>C-MvPImY12j*HDgYOhSPx5rArre z0w)>cDgu8PfY+~IKV_h8c=+()5t~a*O;vlwatMP44bl^)5mv*74f8C3F-b{Dny0b3 ze*L;6Cnx*)YHDiKFVYJ(%!|D>><0`Opn4kmQKLph=&?6{@RzVQf0#e$5B~P;+t)`T zW5CBib}cK`<%9%diUT(SdE{lwmMI&#(HO`Hk~;yO+kgK2`LcWWZq1>#IT~ODZ+8+r zU?4LGhXNDGRXhvoX_qfw7Sa$5!T#dKi@JH!S65f-p`tf={P^)+&*2dXb|>Huw{^7M z{NchGF=B+AK7CrBk=96WW)B8AIXOCy0Zc>~UX7(?eAsdx01-YcZlw=06LDhXoE|-T zs8dt|$UMJw>y~FGn`1mD4inAU^XJd&1;u~*xpU{#dBPu?Q>RWv=-Cv^qTXXZ##2?8 zo(lw-vFP!EnmIT>%;!Hg%oFq{sHc^5Y#iCvFKr5 zaQyM($31hfF=iTgCr+I3OsCszZT>{-kvUBCtjA#)_;goiYK}F3APeAHPKBwY%*H#U zHtcS*zsOw%CO`$jCA_&A`Hk-O+`wcU&cbSBa!~N3NgKR@nRA>x%rJdfS((=xGcqzV zBJ|`yli4hK)k3S|`B-mk^o=7qo2E%MiBcwU-f~h=n?eDN- z;;*p9l#~bz26@;A`sB*yx)uH~nvFOdpU zEv>lryS^!H+_-Vq)TvYR0naWZLYqOZ6p(`l5BlUBY=8+vC~UbMVXD=2Y~H>Bz_ck- zrua7y!py>uTnHF!#`GqamzVoDl&q{Qf4c_li7vvF8Zmmj$-K!dT)5EJsZFhizc9He zfAF8u5(ZoKf}K@2FxN$6v3vdeS>NT|ZJFZOR!MkLP*WN)h{iKY1=twf0G^8o%G+%V z!(j%usNKHv=FO9deAqLe$uN^@1W+k6*|)oQ^z)r- z_4Wxg;(KTlADA;6KQRAj|27hPY48Jc5Wjx}7y#C`KdL)g&e;F}002ovPDHLkV1k3Y B2pa$Z literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/fontColor.gif b/src/cx/fbn/nevernote/icons/fontColor.gif new file mode 100644 index 0000000000000000000000000000000000000000..a69bf0d366e1d5f321d0440958bacc6ae2e16524 GIT binary patch literal 149 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 J&5Vo;)&Q^sB#Zz6 literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/italic.gif b/src/cx/fbn/nevernote/icons/italic.gif new file mode 100644 index 0000000000000000000000000000000000000000..2bc70b9e2c5d7f21f197535beb06cee510a0f084 GIT binary patch literal 98 zcmZ?wbhEHb6lD-)n8*ME)z#H4EiDi3Kh^>9K;jM@)(q?%G9DWi9BgK0W?*R8u<&rZ xfS^{2#KuKOyP3tawpd(TbgWmxxl6`V=;0v-3IAm*4WAaBnq-j7$HT#34FGL<9~1xp literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/justify.gif b/src/cx/fbn/nevernote/icons/justify.gif new file mode 100644 index 0000000000000000000000000000000000000000..768010008b0b2ebc644ed5e4e16018dc3cf921e2 GIT binary patch literal 93 zcmZ?wbhEHb6lD-)n8*ME5AHt((+oNw3MB5pVaCABA>*-O!NFz@VXc@G8x|gJ7f|+^ oDzfNY?w1dwewrGMq=xBSUG zTi7}q?lDxSv??7fc($_khKAFNm8;&g?v2$so0GZNV#(?qRV(Lze4zm}<)6QEenDkX zW_m`6f{}rNfkINHLU3uGf^TMWQGRh{aY<@!v5tagUb3EoV@{4j5J+LMLQraPYEfBg aiXJbQmyer*dyqm{YLSAWo&hfxgEatqv_7o> literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/justifyFull.gif b/src/cx/fbn/nevernote/icons/justifyFull.gif new file mode 100644 index 0000000000000000000000000000000000000000..768010008b0b2ebc644ed5e4e16018dc3cf921e2 GIT binary patch literal 93 zcmZ?wbhEHb6lD-)n8*ME5AHt((+oNw3MB5pVaCABA>*-O!NFz@VXc@G8x|gJ7f|+^ o*-O!NFz@VXc@G8x|gJ7f|+^ p*-O!NFz@VXc@G8x|gJ7f|+^ n*-O!NFz@VXc@G8x|gJ7f|+^ psflnOf%Lf*}Vpf&El>g_SLfe%zZ>oPAh z;m4^NqP^YjTcsXmpSNsy12S{=W^=(ODHWqJ}sW0%6)&*;6)par{2u1V2d-3~t zUI_@CS@ZO^3!)hpi-SCWts_=4w{CXS*mSO6W)~*0FIxBqrKLD$ZPhPJZ^f){*v724 zJ5e>1XDmzmyLk$KRehwo^Nr>?zw`a@@uRu5HJY%nFc~&XK4D{gb91xWiK?R5_O_Nu zf#!?m3njKEUGys46}H035aG1}Qdo(Muw&Ka#i+gau@9}lbX`>)`6?f2UD3y5g@&yx z?_r+a;l}bi^evw>o=dkrr)lGvhx9E^JnyV}Dk%8Z(qW<*S>D7>&cu$XnHl)2Dw?LE z<8XWtTaqS79q~m|iVc+>3L+j4!BR`7bzSuEYo*I(oIx1mmw{cDWh{n}steyguYfLq3Qx*hmnq$g2(e)(z@ysF|*j}8qz-piU%VVbL zZ>_sgb!!8FpnFJ0lFf5co` zw}V(vYu7vI`G-Cy$D312k*h^#kHMCE1=dUFr^~jtCd>AQs-3MoNcYyWuP0r2;`=wP zvDVqX&j9Pf^UyP$p_1y~;(ijOyw>@3h)^||E8p9sZl}3nYg1{?+WIH+-VHlZ?|^r- zI!W_bguBfu=KlPHSMipo=bX_SELC7f5`vZ-S|^;Sm=pq8BXg3Zh-LAmOf4)>-jo}4 zlvcDxnpC7HsQ|lD&)B#J@TkbhKpL6_Hee;5$Ov$64Q>bX12YwG-$v$ryDG2Vg(O9~ zFjkMS{?3ACnS)Xvub5IhpUwz#l74l$E;(aiVGSrLDa8V=V`B!+&e)F2%C8r}__K3! zlEo7px3@wx2_6#2i4x~c@R<{(`V$ws$`Kietz$)RJ z^7b*imidLEd0JwLW3ve%T%xm{C7CjV{NMR{Pc8Vejd9O>S)B8ZYTKrg)W`XU?q*B0 zijVKlM%E{%inBBoAAYwz&DUZPML3dvGY5UNwL_)xJs-PXY;^uB(0YOsY?kV5vV5f^ z_ZN2IxIbH!Y4+pC4^wAnB4D)_78cYM%`7cZ`(miOc6Zs6G!fpH`*Rl;uIG0ThXW6f zY`c!O>8(pitwu9L%t?1g*63aMSzEbNb{($94dqe52Z3k5HoQKk6;GNx)=uCW1xb2F zM%`;`48i!oZVS_qttyJrk4Rf!4~((dfrJ{@bQOryA0gSJyibWS;SxtYB;MLI3=-pgsWJ|J;slhUDd_mD zyF|)sh1LX#1$&$4@mZ3dwvo1qx&bpE8lbdEwhJlBcxG5i2wQ~v&p_U{X zodbMr5rjEYLZs6&qPv?GNl96hFs>_=oSZH6j#zefeqO3#W}pmYn;x?*{*CJV>t&Vx zi(Mmrp|J|VwNy)5z*+Q)8iBJDsbjEc2PfH@yK~DU&%3%IFIIAm_u1Cc-kUT!~P6zldFk8 z@c+Hv6ev~mznwTjIc{S7dJIyJ0^g4~h@BK9+22oyKM)y|>2`>i6X^iqEFMJmX@l3E z?Ii^=P+oSh(+W1JZ@>0ZR&MQwRWT3c^nP3&VZ6}GEh>eC4MxU@g-zFL=QN`w&U$=? zC&s|aiR~HUw4rXzL4=wEH z>Px9mtG^bVtslFzFVmq8LAMEW_5E2EhF_FnipzSJTrSyv!j+j{@jRPgm+W`ScmbTF zw{KITtLoQTd62|pw%XNWJ5*#bfiB9&B6z^gZCH;HKIQ*zIuWY6^GbOj;Oj>|#thq} zG`gWXWm=F{kV6J|fd8TOC{~`?N|5x~v&x#9V81psF;I9O>+?l^m9f2x%Bm`jZ+zd0 zyl4qTJ~PNPbd!av54~c$qXFG4@}UO?;w(HC*6q7B0Wr))Z01UYTL5jGpAK94x;0yg zYO_Ah<+ZKl5zo`$*o;q%!baW4j$yt-QD~ERN^)|)w5yW86BX%g&=R*jb)cXQBUaqf z8_-G!sfoJ#qEp|g^N47ee$FNFN{hAD{RPR_rH|-|D%mzS)`$d&6gpN9woqg+~>?biZU}lkYUCaBzLr>^WE1Vyze5D=^=hnaYnAnr?f0 zyOwfXX59*8ejqxZ4A!@XOik&?XauuHe%ds3v+J$de5&eOMxSx|&m}WU-rQ8f9ejU! zoe+n=_CC5aEk&E*6LAQA)VPg{e>Q>s>dZ>W>6bHO*)hLx8K>G86ApW$+tl}(iuZ>{ zkB765Eme*Bb4UI+DgKS0ZWs41tnBPd9AGsUxH;cM7!_88NnfmlY?-t_7dv^r?ILvj`{?0O4^sC;F^RTCb+vRg(tCMi zk@lzV$8w5_T=aU{tJk8iILJz(EEg~MWvb|KmSE6&pXy5PjCk}x$FLdcRxM6ry_o6* zLhFqc9OQSh)*~wFPceD*S0g`N&(!7bEF3x4`R=!-f;?N!co7aRG0DW_FFH$Zl{6Kl zWX;GSO@@qqqEV=AlnN?_Z44!qNaR}nv<_A*bJ*vQ=sU9HPI-%)lQJ2V3qS$os$5yBeQ z!FQ9Es%q8k+FD57KI{c@a~fu3ZSBiNJ;N@p`o%zwH|06?wIPNMO*m#`YlSH$fk&Qt zdPXvB%YCIY73;HA7V03x9#~yZ)a}Erd%CeqN%VDYVF2d(zxRZIRY3NaixWhMKAcY+ z`_e9bB%LWYmM)#@?CpiAW{N~`R5S;gRD?AhwF+M~9S4D)t7WFzrmZ7j>gVKDB)ip} z<*uOixNDW_$)Q1ziQkQ-$kY9qd;%0t?3xa=l4hL+24y0gAXk6g-|qNcExFSY^P`;m z($;5+V0_`}nJ8A3#@>@gr* z+1spbZ58e$8@w3;j3v}p!z+%J0 zY&i?)yB(Q4_kIG#9tTI%&YQ0GRrFJ6*p9++jzdQi>yBRrA@` zqwZvmH^A#20@w-ycTuShV$r$q?Lp-eWHR|HI0$->(SjT|2gyY)Cbb-m>pz{NArB7hWt^f_i}U43hO1gyzAku{RQEWE?0a~J?1&cs zbWT%16(|A0$*@QJ!{>%}hh2>UuSj$Izlh*x4n`6~fOYNb?~hb{hpmYY6eyfrT(%X$ zGqQwz+ip#s`zZaC`)@KPpjxtSAzn(sv^ z!g*8Kvh`mwN%L_hR`@zu{gM|4G4k_goR%Ecv%MpiCSbWMnoltS@E1rYLnzlY4vvmK zl>*{v>)l-fUIXHbx{TlYFqZHv^0W zy_QiU`VZ3*BY|H6m4rum6o1AR*y~+>uPYVWk}4Xz((<9bN(acM3@JwWlDuTU&C6aw z3!jVko3uMdk&XPD3X`6~l()S>cw*tYr6FZyTm`lUdh)LUU+HbTfwynOkpxcuuC6cD z_!g>W_B!waQSS3Tbvqg9sjB?qbAGw~1CEN4YE=1?IY)qq#%G(}sM&*nqqG#^y@{Q` z)G_sb1_Y{4aS@{|!fiLgx8DQJA6%-VIiAWK2vw8fj7fBmEme^2n0A7A-%WabMt(ua zty5CLX#DS;j9R=%+?QNQb#>oVePIL9`rn`UcvZdy3=7Lc$+1ze;>2=RIE$YGM|ZvN zcsy!+0fh1wzIoc^(9B>UGMEDH0q_(D2M2I|R$dPV=$0l&GvND$`pQJqOm~x@p9prZ1MZFMs(=)N^#AOP7w5lM^U8 z>7NfyO-)selY)SK$2e1lhzWW$MYdm^#o2*AVMw3{6c!dPV$a&u{$(Zz`|DL zs=2k0T{JIoDc`?;zisbe!90NyM~ghVYxwj}@er*Nz_AA=cmO01+Vc$0BU@My%}j@* z>0n-;rnE(K14tCWq|3MhSlg?OH1lQnQCP;*CC?-AWuwTj8H^geNHY0;a8{T)RYmER z;*3nh+W~MH9u7k|4RBriKkfPVgkX^#i$BiBS}L!o!+MPKXZCXITW|!NfBbSEJ_0dvx~D5RDJ(Nfis_n4%1B`kT5bz@OH!?GRsczcy@qURq70KiULyKMFZJb zlJtxfE8GKc?gF}=d;FC&tFPs1sqM(JZGF*GVTF8gZlp<9KBw_gR19dx4 z$AEer_vWfS4PNL_LF)5s`2aYz+BG=#RFnzfA7woQE>3s8bPe{%imk1sY`pYptE{a} zmV?a;5LpIQ(RCJo8>};Y;N(F?`L>x<$DGsgxL)SqO(}NsN4$@;?fA)T)E`APTj=Wz zwWH%9g9_1y3pb#i0Cu*D$Z2R;N6x{vQ>IinO%9SZrn0drfFtE?ht|_EUW3y*% z|GrY(;ZQ;oN$q@$&WAivl?Z+qMf)%83Vd87^Yu<+)ReugVO<#e?L;LrcE~{P`TE_v zz-!%*hRI9@Qnv4?}r5OfFi3DhmQD_b9jg3>qq)F z|BUZuMGX?!d)Ts`9_^pg%cK(t=Kw%3=24Y)YdCvkFOCP6g_?ElLu*Dx7l|TIAEpru zj$<=a7(%Zp@+VegV=c+y%@FT_Z7kBGtf9A_bz<4n8m9S~%HPMV=PiBgxI%f)75K_~ zvqS45Y-8r*_f#YrI^Ss}b>E2%JD6)WB-339iPPr<6mUv2pqd40Y-Z$`X$}j2?k|{N+OuPG;NL zuqZ03Jv{RJ&7;{i_)-?*+Ta+B_+@H3_d-;XEblAJTqq+?lD7Oi$R-?N#6W^1Cd^~f zt|PBfP%O#bK^&vdmhX|}PT-vxZlM%yJB$y!?T^0;!wyT zj*BF=Wr&mEA)G-?)Qq}j*2oB!k7x19mSjCZIkNIb@%UI*-$C!c)!hCiVZZT7)xNNNvBeK zJ(5Enu_t)k0&1mgcUl_Eoc(Yj#*vCCk$7!gCY=@u)+Qt-%*asCOjSs1f9?l=Cjj6~gPw(ndImq6gin58T;$Obre$nE? zacp&7f!Fi%*Sz#o-BkiVN^p`rxtqF;3rK)G)KE`}^FK+xQNK=T$N;%qTws}VgIZ50cei#FrLzZw+e#EwR*iq>GobQi%Z z?DlmjurTRvi(1~+O~2@b0?I2}^5#>|ZL0CP0|n<0*O5y7fxh`0jevoeKC}6cx+Elp ziLk>K#Dk-MDh)9|M33Wah63opXQM0UQOmq_0?Pi(Wyi;;AR59eq%+Nm*I&u~eqpoESsz>pF zRhE6I7Y0xfXzth*CcS6zCPW`D3+RgnvQ2u4f6Khw#auM4e^|(LOa6Q-AggWaOm4v! zn~4)TC}sB=xyssQ1nUM_V-Jocef)Kq&R2q%RzAlt zHJ79mNBV+QA|Cfg!~)(_v_&3yk9a!{a22~;u%jM2Hn0T|LYy+`4&}lVq1ebRTP@m~ zJC4FQCXDIn>Ek!qkNkD@-q-DFkHlZTeECGsCaJQY>!0CA0Xj7fM9%$!(C&|xVT$9p zfi-{l-fCq_5f^)$R|(`z*)ghI7~Hv)hD`lq&P4c8S&w9Oes%vF<9*bE24qvcWxWxG zhX$aK0-8|mol>MRUGxR*zE{h5Gk7NsPb+xQqI-BZK@Kd++sisT8>yDKIaZEw`sQ{p z(`TO;itS*DqCu~phRRfa{D_W?X`=iu$$K}2@srHK@^R39NtxPn_T0neibSt#e3QHn$K(un(o~TV+w5J;q)X*a?%sZGm`N=&KN`ySSF0O;3@aNNQWr`?2)D0@ z&fUFc|NiaRqxFK%%*ts5vKoXX5e7-pW>97{_}q~A9F$b7O;=l=)YZ2=#I>EU$R0cz zD+@e4Mv#y8x9eM|`GJyWSa`5rWf5%4a_770p;BMkW$Dr;=xsOP{#Wx-iMttbqo@*g zD`3O7Z6rLCqf71wgTEz7k%a=ll}2_J(-9$Ag-e_1d_bx3sq9N&)2V^%Q{A||II?Sd zM(YU6G=uX4yf+lvAtk?U+938>SvlkAEI(sQKY_erTF*?zI01Uk!B~GLGIaj!uX4KJ z!OZusC9&JjjIJe-bm(yfC9T{l@o==oKW<-02z9(s*bC{Baml1crrtvqeN=_YC-{2L zbb^ZBO3bxbVi}#jzwNws-gd=WWEmzGf~a(d|9U5+lha5wtIQWPF$`(Sg3MAVE0%u2 z|CpuGiygyL_B>~4wa*hW9f5&f$;l8G2FJ#)mtwL_MinxXwJfEOf^1C8L^=#J`r8#gbBF zGL=u{f6`L-BF*7vvq>w&m)C5G2-7Cabb_|#Gh(3%v8xjiIV!R)K-H((I)hj zKbWRGU`MD1xtr}yqSvhzjE@oy7s>Ld@vrgO;Ngtj8jyH8}R4Ua5Gxt#~Ux zaW3Gu| zGd}S%huwF7T}v}2KocqCWa;u@7ZwCQ>z{tTS0|=3hqP`nq8r%MqFlG)ai5#k z?K>NL1fVVBo#G%wmxI=SHMX>LxO|&w8rF`LTKW}H{OUQo@TZs8(mT_SIjeZv>Ls+`4#MfA1s`5QLl6jfb0!Y@@R-R~! zGZ|rY0I;sT#j*R+0Wu%ta(*6h3eQj`n*LZvFX~w~C4d;5gn)LKwrcaXXV)d%^s)ZKC zF?avA^#BVlm|10uC)&)0)U<2x+=M%MEGd?*W2D|mBsIX)_Aq8Y*7qfg4HOGM)6!3M zJPbI~3%kFhYREEVx?i+#*xv7g`wSyKI5^OLe{Q;JYmwT$n*SX*-5Fwhnu?q+Uc`tD zoryFASYemJgV%-dOC4lO27g&S% zb2BjO{P5Af<4PpB3?FL=6?kslT3vI`>I0_Atv&;-P}G+vX(=RrtipAuxxDdB9UgJd zmp3)^9aSsicK2X#S=m_v%f^CWGRCDJSUoC3G9?p{5fi$BT% zH9Ow@hT7V&@X?^`9qdBA*gvH(;|>Dkb6}X+?IdCjq1rz`J}n&ZdI+NgtZF_V9{{F( zbM+3XQW$!FdHP9FaLT~{3jVtM{H3mVbaz#v=8Nh6_dzIA)caZevRkPMq7xy+Rdzy} z7uC~)N+sSJ*g@9`^v)30dio}kP1FFc={hr#XRE5J3YfAey?*q+;Xc{t8(A9>JHhZd zmZt5`o205Lxrh&$mwlosN`y*eA+w+Ew@zZ*oAcwmy}cSrRy?I_o$q))iq zE$0m7CM|)I{z#^XcnW6^%=Xn^<*zI}O`f?((W_{6I|X)_B7wV|-h5`_x5EsKVf=7n z#cscSSxYa`_nq8b{*P$8)3>XB3%8q9y(81qer$^h1OY~F#i)$|A4FJEzv@P zDqM)x0q%VYcO!b2xmO8}9*JKhUdIMGXscO!k!wQpjo>}HM)ap9%8a(J*3-gti4zGi zs4Hf+wixbN;<1na4I_a8-#eZ+^ddz*GmbX! z7jw2shD@lXF$s@JYpRU3^__bg`d`lYKg?YBziB<43=_X!EzUW(N@i((XwRA(Y(Q8| zDJGnZR_*o&1x{Z=&znCTNiZJy2|{$fCZ<_?c-lNo&4ici)bLYV!illFuY93%n629K zAWR05@c4~+Z)&1A$ehct?5OU6~ z+7bF)c3aB}GTrgFN6?djp@Nf0D{brS1;|EI#|ABWnf|9Z0z z06pVBy2eeb$ry&I+IVLcxr8lM``}+&t`wNgoS7G7m~higO=65Ft~|}Q+>nGwePpkT zPG-`MUO^MR#1~A+O1J5liVII;$FK~6YDLxzv&pc#sN-9cS$!~)uY_Y?ZD3rdqiWUO zy6bzTb!Mg(9o+$$Jzn^*VO==$%(?Btur0)`>GQ|>C^&XiWhD}hO%O^C3kski3zR@} z$LLaQ3uNE-ddc}YUWHEE^e>^f z^(m`&t+9X^s>MM{DZ7oBM+3tWjAw-k(*>U7%$FElsYsemI+hcp4Km%9H{!iUMCoMps+fv*W6kHVkr$OKzsEhHNiaR_P5%CeMc4`T>2!7RgY=&;9 zU?!Egq6l2ntOBniaZpUD02zj%LGHGtQW$v|v7O@zU5}u|!S`5|BDm2NJ!Tckhv)^J zZwm)&hfPN`hF`p}k&^FIa7GF{rN1k)=sc9H5;O%)x1K4lPDtSg9~%nw<27KxzZ_uU zOJZWM@ja(!-EKiOq9){=Jb^y6hsovp6Oq01QeJ4Qb`gdm#*zdp=i`HhPz^2f{dMlX ziuro&KcCcsuoLrB7G7QlT2*i3!9OjUz8T%SNsfVT*vcxUv#dnQNJX&5fIZ+UZtv_S zCeU%i_ENzy6ZlVu9lI9*?DWPu<}C#YqT$phaPUIU#B#_oCc3%mGkb5&wm91IXi!Y^ z2ZuAGQma6}%Z)FiVcuc5pgcNiG$fihI(-K{J-uegtQrB7$0#KzV9Q>P(ri3NLWs3`cU36;!5M#Sr|=CnZoLhg4yOX z6vby;<;rz-=K7gHs6YB5uJv>@iqj#p<(1m_KXo>3wOfsUDe9yN7CE7Y#;ayJv5&MZ zc|g7-Ien6c1MCiW{B$U6Llv>Oz9JQddbWt(y58X`BK@a3SJZwe&a{hFGBK`*jZFF@ zOTpE&D|B8b9L{J@G1A^VqP$M8r}>&Lv8Fd|jQDaB(+2qkHRFh7ma+9f+%(0rCUaN1 z?V-YNPim^E_!L@$qLNOl9%-x_lXTi17}zN^fzLPg;^oS5sqWu%y}eL|0l z;ti$vg%<7gY=cNG8Pc2;3N1OkrF6x3oqxX|H;XN;NI~-RV2=8LFf-#EvpW{Dx`#W{ z4P7L1n`XYTb9^0v*50Oc*C(SCdr5SGek4xg>h;M+LJi0nLpHN$O&b~ABx#~Gu zyIa09XBGX>ryFeib;G z44Di8!WtN`mhahQKXI~{Qpq7a2NXn3iUiiX|7cx100uSx<8laC2E0sCR0Dc;&LSgR zw}!_``lQ4Z>6<^Oagu75>s`Hhw!{PPP# zepkpwqxO56Imh7noK&QP@1EgFvHxxH^Kn?aI{{&+PY# z)fbR`9tl8q3}*;sQUHbs5tK7;d$is@pcyqg5*&Fi$MW-luZUhE0tMGH%>6ghZss~n zk8ywbt@nOD?NhO-5K>&4$3{|i+Yi509S~9c7XX8 zDi&6h0g%*xYtt*3e{i^}Y-tIaX?yI*)W@Qy@1~2wK(zPX3MC+V87usu4qj_2dd5pr ze&^0n5t|(t&VjiKZt}vHKUZ4v4*7P4A>=joFHAs@mw$SbYW(Te+>J=Hif4}GG~z0V zmDb4A2h|zk8I^C&k~GyrtFaqV&w3dh*(*gOE8PlM0|$%Dy=!}wrGtPo^De(zWet-$ zW3yu^Fw@#4|^`d%<7LMj2ourH=%y-9HLfc8JU-sNktH zq_8h=spkdgkZaKw!3p%0CDi($$_6}Z2(VI~(H<=`)nI&FNnjknv`ob{oU^O)QIkaN z74+$o#E*`}uqhfze7+)Su2(F5lFjo4%|0zO?uy+>O%xR_$1-k|z;XQk>vaIb$=0}p zF6sK9m}1G`aF!F2y`&IopzXeTH5xCiI$1|4_!2=KM(81b+CC^JV1xK!B|pN_Cv2!IS4G7=AWGyw|tXrT6NI<~H_O zG3om9AMydWdklOSPcVLXKABTyAV)wdmV9BHA{WWG54*WZgIiw|o{@)JK7vi2*)5(m zYYI%l(9kfi73ezxG?wN$)%|(YBc9qCpUo*}2*Y7k+t}ZWpue2hNZYYD1I$LZPv5-5 z3h`N%o3)dCcag<}k$?!1XC~GPUnh1-dN<}DX3wO_^%w-s+Os-AmA>`^&0M6n)A0o- z9(0)+jM=)B7FOhJ6K1 ztU%k;G>ut8Qikw^PBNi8Jde6e*}V5Y+Z-Z<+pyPp;Ue$2e71rZ+7?$zWfZ+2(jrV{ z-YtU#_q*tJsoFO|MiOaqFfF|T`kSLAH^-5=lw{SN$`uE1j*akmUyL zs0dZ+foU%!=UksRfbA6;b?+me=#$Mxam|Pkg)uh2z;D)cusRc1ITd%Ce%a<2!wAVk z-LDje{sz7CS;6?n=0F7|#k}O26+}-CU8b!l#F}bxDnK$L6&Z%&EZ8EbuH7?-ke|$g zAXq;=_r|QGrBRk6@mwcPa-&Fuykh-C!yfDk3yl%4!3fS02@a@z_=IsT-;twjMRN`* z(4?1V))are=6%yiXgEj}nGNKfu0XcOjKTIrM_1i%e?aQT7Io`j^;Hmx=FzzA(5d=8-hvX86l*KynXoNceQfa-iQiVBo12Z9 z4JXuossIG-A=Ky}cFmg+alX%a6i4*}ruuDP$%q{B;0pmoqno|7axq|dA>$wQ^^DJc zWa$GLkU5u}9Q@22Vr{!0xcHUk5Zs82AYojpB00C7C_{JW-qUc&^tkHc63AB-oZSY# zGbq!Jvr!hOZ$%ce7HF#yS_T#VNwsEEm{}zMW>W{ZNJ6Q;$Zsu)b1h%INJ-F8-4IfG zDf^5GHG%5XkT|XfdXC_Zo)yd`3+CoaS!JP`UF}GM;#xf7Df6Jho0t{AOpgLA?I*v7 zf{L_3@2uMY>m@0v2|uebrJba&#}xwW>wHw(AgT@zxy?9o7aMJQ5tD8I<_$i+|ky7F%J=f9Lmiu_4=6I3!qO=L2&?f#j0 z`G1uh4M0i~SItBO@L3OA3850p_?kbnO=pN%AJoigZ#0pU-~p3c=oy&w&KWw$5Ka(7htrH6WoADjsJF74kjl$o-EPQ zGvvU-sU^j}^}Y7XQHhVdC!?g||G)+!TSB#Y_N|czec--duAZfi6zaQ~kp5OK$5ujB zdIR-?GM2Ksa(f?*H+J^@#&f6j+m|0ik3qv<#bZN0l9mB%^(_=-hh^C)Z-awZWS|*W zf5=%2D-wCbU(wnYW$`fNtea6Z5XSHW@cx-7QBA4XH5M242*@lrI@Q!dvka)1)V0 z#<&$;_;3AziA*K@CBPw;LdU*EIln^*mP7*R3sP1Yl5A1R_jKtQdb#YVgf_w0NTI&) zGvMj;XAI(fAH3LgsHVWF0`7}5$eZ+8eb5a%fG6~@dO}SnD{xx(^YGDuMWV(tssIqH zJ~0k3)svRdfYLJukDff_61S5lsjExHu6^%pmKaZeA@>T;RWb8Dw$0~S+ol(xFph}_ z<#lwK+_6m@V%=qJ2o1~*4aydUF2lOF;mw}37t<{-u9$^v)Ym=`WuXhupcx-YBhmgObE&+sN>2Kk`V% zU!Ms^URWYvQ+6LHxIN^T3J?AX9t z*yRK`tRHFt;ysy#yjB2{!q}0V{5n)~XItE@FF|v|3&dK85_K&}M06ZysyJ@>;<8%m zAt&d<aM3E5CqA!FvokK1v}K z)3|wc^VloOH8Gs5_R7z(ndJBq9e5ztU6g()${`&2hnB&$!GtdS>L|2O62-0cZSq+Bf5vj4g-e@QNbA zd_URL51IHKSf{YG|5>h^Lv$6uRGDlIF<8r2pecaxtPTo}lMjwTFDMw#Yt5b7%0yWN zkK|+6&X{U~UgbaSn;w-Y*iKr0}NN&Idok%HO=&o z($dLic%L8TUa$f(iNt@IQJ5dX(7n0Lrg^|q&=+xh;F*9eLHy33l-py%05^Q8Zo;fR zNKH1%3;-DEYuAdpBhz17 z-Q?k?WR(XgE`XMWhU{HM>QyQ-dc0Q|mCRy=PE8W#h!;cozTRxP!-i8rXmh3c(dBbe zOEd|!p2=Povc`2@GLJKB^9S?xJZJrnDhz&{)aSTj1amG(;y@5@5$~`*D;9kbS=uod zQ2K6SGWLRcR~?Z~ctDHg5gw6U1gR@tj=LGWnY8bPuY*zzgHfty@~8e%MBkPP?q)#! z$tVUHV+Y0C-5zSK9<1E9<8>qzMK9RDpEGd_mbgjE0dh&BGwsKF8ZAD0q@^7rBJ%GB1D#~Kp{_gUR~rlwF$R?DAZ zPWATK&Ii>H4$I}kscJA`#;a=Dl&Fc!9Dw& zu_yJ7jSUHG0C{Pc2tSkfb(i== zNYZ#g5@Ub}g*M#;8vGRUstA>Zm^fAQI;)SSYuZ{oireqxtikJ_DgZNZqm-1=HvUNz zu-yhhA0BZ5tr(5pb#Ak99;+mAnY3aA(0?Dg!1<4T{q}a86wtsNi#OjbRX^S~!Uzy! zBYtTk?m@R^9r|N4%Nqt8D302Tln&2q=12I?EzBW52ltM~1VkbM#vFh@5UK#v7XKP7 z!ksu)V0){IdGr_$dtGoLP<*aR2NEiM{u!Hd9Jcr$h3YY0{P7b||q z)W`^SxtzvujBSJ$s_FkGm(goRFe!v#g@aggLGo~&zX3_(ClC_tO^Jdl;*G^W`IK`u zwFZq($T`7_`8bLgiC)jS;qf{xwX8bBt(@=tbXUJ?F!gSi&{Tpg={sT$?IfZPu|U|u zVi6CP!A+%7)F-LP<9gaDP*X&ZTh|P39~{13fqQ=>Gp+^dD*0iAE$GV)o+NW zmwXUNfg#5{1VNx~i-}$)jn6B~j+!*i1HNc}dq-F>w~aTv;)IvA*Kro65s30~@s+pjyUbVvrZd zDKqTuB`4W_S5dN(F{OAgK5Re91dzr^$U1)&*eZh8`)RBe68B}!ph|`+sylT?6U_ja zN{Tn&hWo<1I>_lZcN=x^JZJb{+vpakZy=1hzoE&MQ z)K0w8fQxWmy?G%L3lx>T!nm{m;T)g~If~)|6nxLwo;mlpk!V{S-V_vCQCN;T>o;S0 zXM(QxJ$NgI9$=90tHd*5bizgU*ERq_sT1|JBIK9=noF~j94Jphn2R4pJZQO+ zCWoKDLhYt3F(a6e=MM-Krl$dk;WOMORy2rnxr5wf`b)cA&^e&ZS;n?8E%MBAuVl_5 z7|tB?&ZL%g>*ZC7PVqeFDawaLssGCe6^a2yhj3gt^3w=f9hG=wfu8gMVPZg~pf3tbm)*csQCHlF%o+1v1OU4qlW(JKv6-?ItM<*4? z_3f_IKL92f-ebiR7Q*@G@3xxGK_jQj`LQV~*enfN<4=OD%$k@2CDvknrJUkNnkAma8HJrb+vr^u4C{?_$^i<)2vv&GVsljFElb9lF;W5zp zw0Q4KB&Ep8cCr9;n%R$@W@-J1L5?GPhdpa~SxQ@XDDV8Q{(5siBPF#y6|G=KFFa21 zzsc^qJbF4l5*MpmCPHCB6+%T9On(n1K9;s-xSw*RW}ebEh$B>2OdEM>dpK~gfCCtj z@Z3xE|7fC}sMb5sXuEfJzyBS3U2>nYDYd!y+o%PmtjjwugsF(qtHdT1zKFLlYEa3oUp9rX*{LX#S{l{$%Vtw-Wiz%Ae2M{(Otn_`Ww#-30K|>S;l`HbR(9E z?(VEV`_l8L{^hotPm7c1!Il;cA8oD0oTf1wGcb{CTRs!ubacAZ?aE?}GUr z0gcKFkw$^N^Vyp!?eVN$4qx1J?aE2DWe%Z*UPxB!p zUvzh(ii>OmcS&554|~T`KtQ7f@t}Q zhYb7lR@COr`=6Nj&XMbS!ZfJh+Xuf~=?VEQ>+)_hvS&Y}>nx(?hA%M{&StUfMLkYCCZn$(yFtA2biFoJJp5I-{?Jno z_F7JsaDC9SLz@6_&SLsK>>Fc7e%k@HPVX27%N4(z+1Z1e;J~YQ1tLY;2EFiol9)^4 zt|XfN)3ks8G8q*J|3|@gs-kYgUQ<((q=W$oW)#_i&Ggs|GM4qNz24DgToDoA!B7Cs zVh%v*|F7F0*ty2d;74&0L?_X-^g=$!GQT42BOZee)FE=SuE0jT^aC9mM^MR|s-s%b zbLH0-ms(A@LvbcnO%s#hMS%R24!f(rgG2anp+9udS~-9Co(Y*HJ{IMRZkXU4- ztG^$U%mVlT@VKFx*&pT43o!#kD#`UPTVm%kie59(k7aWa%*rTU&F$zYBj=~4Y3Htp z`o~pvCWobk*bSFW@3c~}k*T05S{{Apc^gF)I>;wTSg15LVR{a~BRaopmXC z{#P+){?5kU{_#Pq-B4Oltu6L7;RMwjp-Pj61fljuBeq&jY<(;TRaG>2kf_+I#8Nc2 zmZC&k4boUjTXj%96t%P-;?NfDcb=cWf53BH^TW(s*US&|xvy*Pd*=Om@kemUU=`ja z@>j}G`P2QBJA^@`)&Tt$(oQis0yUWw>i##crQUlZO;ryd{RHb^yVv3G31cT>_3|f;wRebTKU%& zGCFAzVPa0)$HR8;hr&B1!&an0|8>N4u&D#W@}z@!dq+nL*yMswwicwQZJk&hz)3ab z`(c|gO%;)`M_k@+Z6QFGXMX-_IS5RrfOw1dc5TF=Q~<={LEbygQl`o*vtLuOpqZy| z+d!izEn>;w)ZzKBp6kFm(?9`4uTPmjr@Lsm<%MCl;f9;#xBm0_-N)o?E zAEvE}@z1p*29ofuQ#^@#;}`*cPT_*gyg7Gd4J z<}8qwT55G;nZZ(HAPNhnyIg7=!G(Fgd*EICcWD*4M6v*5R5NITf9-f@8B#~tK?Wym znBWK%flu(GR+}ieLCqfs$*bOTHG4S8)W7t+qFOB19`Dr0+$hH1t zL9>HDe;r0%PxG0K?a{4{G%0kJ0!uTg-NkT474#5*27-;XAe$w*6kgzQ{px9TeFF_M zPRz_j{B9v!EdI<}Yk9%_>m`e=YjID!@)bKBaWk}=PBluVOx?xbYP+E4pKPIqqBuXq zN5eyf%ny;o(aLBDnlvcAb6QlgPbKN73NR+xEcFqVavX50fZmu3c^uv;7_ppdYi*6} zSnIN8LP)YXsIIXVW-iI(NI^!5T1&|?MXl54L7R zV|%Z;xd5$@{t7J1Kz@W)8IXCv8q!RSc|@AI zx8yLydEH5|j=rs@ka7sMYIHt|W!cJ^7{gUC7X1MC+F9QiAG3*XP9%(aAB>z)rOk9b z!?@Mh>rt+EtL`b7RErfoPatE~n%GZ*@GE?)u5vOZZm}>_M!Sp^U1;m%oNQ2(dg-kdpGlM`CVJPc5=6K{fM1v1+-6P?~W74 zVV9<>m%@`WPFccT8>{LqkZ&%VedU*}cw|R>X?qZOd?=_VlAJ^!1xTSJR zEq#mO4BitNX5pm`GCg5HlMP;^9UeLp2dPZj1bl}ROit#V@9;S%=k=(Uu?x|)Qv*6 z8Q^`pd~esuf1R;7eW@qM7$7U650k`;zg=*vLq-p%o(2dvCCzh8T$fu>-)o-aIv{RN z6}5*>CG7M=GKStJ+99)vS#V8@WgW8qQmIy{pa`yMzN|);etXO*3!`(onyy~GT}>}{ z=G}Gf!s>*}r9*ddupG=R9&6F1F$wWMT=g?SUZuJy`V!^)&Um3SZ}#aV{T=_oPQZ>C z8dcM)MT>$|b}p&tLEs{a@QeFRjh*~W4bImUAN@mhQmRYlBND2Co(Fk>^u^&1RyL%Z z1saR_PS~=CX5sJoGjALB>I&w~0$b-3j#5-xSK+$7+{Ff8x8PLp4+;;lR!N*|y5Q#| zw`rbJ25!$tAGy?ZN!2IBER1TAio^8_x7`%gDdLew4hFNaIu}*36So*_K>HOEzv7Ig zAY?_+S&^0aiReeAo^4k7o%&5qz2ngWi`cnK`7FcN1D zDwi};vNC1+A5C}(E)6Eebq`mS(SPMi+b0l zjz3eIHYOXLFVlEY)H!cSW^%&RX?iH*D~*t7i5G*!e5o-u@tN4ML)Upq(L07$pGBZ9P>i`umv~0?7KWcF!HKb-gwaVm0ko6gdUO z1*-|g*X4~1g#h&zP7f`9P0#&|jU7epHn#^pVDzk)7pANmBHT5);ym|_YsQkk%982b zt~PS49IuZr&*(8u$-HxeFVpwAiahu2QvtqpZ-aAhHh%44A}Hp0=yr*6Newd-z)ie< zkxzqvo*IzYL~y0XZ(EOPK3h5WB2fD8t=2u@4~py`c4Ir;+7UZ{tAB6cQ9fP3{Cw(} z{ZxA>V#!3W+#=_^ZP3z#)uREvqQC=b*nOI8EzhJ-rgs?Fdd>T{m{c-0!p;0SjJ92> zl7|9EX6T9@6J_UI?2KJn?;9&V#BSE6H4`u=m++uJUZ)v$4* zNtP-3D7CZ>hIzx#YpT0->w-?J50k$G=1?Mp>CZO~KG?4!QkkSm2w_e2U8(C4%dRhB zZg#{Asjqhn7avd9=g6NvId|oU;X=7z{N^lDU@Uksc*Vn)QhP-3f_LemFV~pFk`b{{ z{qre=fJ4}YG~}MhjM4^EU|9onJk-{H(qV#;22W^a7ucYo%l$b1HL;fS*112R*(Y)t zmCJh7^x=zJkA$l#*E9>%?EHH=`e?K(@xL!ByOma(bS{6j+%4-nMie$j(;d|7C0Iw* zwf8PyKGY{TRM(UtbMl(A5(XG^KifE`-Qrz)7;pWc+)RdR<#HX7@KftPXA;*o8umQ! zT@&-G|MJprf}#%tjbz$_P8zNc6O|y)Lm}nFPv2vFs(oPi-pKJFW*)dU+baS zZAGuX%gAI;&s}!qxKbJ?ei8CF(8Dp}w{Fq_p6>Y4n?~5|?`9LC>FRA3h(8u4aSQMM z40tgeH+13+k!kmZ=qAhOO-XfO z_<`esRoR58-E8&n5}EgtYo(X{l>VMxrr2JIeYhGA-ZkbZ-6WL?@zmO2om<$-eRcVo zEoYA{un+m9#eXhEa#M_n+&b5iX;;W9nS{Umr~Xl^fXZ?0_pJ3!K%KdZG@P|{9cU=< zwfp26$J@dSyto&6BLlPD%A-v_U!$(i#Jc4E>^rQG0+&}AlRV!tUJL!gmEnhHgjz{N z8CCrg-tSiO9GCTTiP>2>W(+&(a<@BU0;D|F!u zd_}(d$wq}lq+%*6X#Rr{ZemJnvCK{FLDZjSqcdNAo1yMKY?7Q84_KEVE-6=}e+cgm zmyX|OOT}#8i)tfrGOk*cw?#nWrymCTn)Lgozu1OA2qSW_k{Ya;W0eUGX5Y?z?B66i zoO;*a+b9||R`F~&Q-mrS{@E~gDkV8e zkQ_bw!O!>kowIYce|EO_`+D84xUMTkUsscwf`tMA0BUV5bwdCEU48@sFw)C6GtZJo z0DuCt)m4mqa@SiPREP|C@$Dt_<(`>6mGrM@(R(`hDQQsA-qLm2`N3TR1l~_0mWcQ9&4zGD(tWqwu@b@95~o-Xid;-YWi#}eUi=GuGSTe zL@>*aO}xuq`?5IxQ2shMH}~Wg>nswHofa>?^0E5+`NiYaLYji=?{fY!S3%eyEt){K z;F&uhB(MTmX*dF7_}e}ruq-%I+!fsDx3wsR66LK&L9-^{m332T63TM~Rvb$%jCcmM zO0WuP11g`{%Rhq>$|j}NfM7yG&Cc>z5EhJs<2>AA+m80Oe_b@c_Zq(^Z}dDufF`X7 zYW((dk5}EdG0AVG{V#R{%FU$5Skuy%YMA!71!Jqy)ObMtbo zrR3YUF6NXww*t@o+x|F}ZIhKq7#CF!2N6c3H|TNJAF=!A*MWt$1LGh{>0M{DX^Z)t zKVa!NXUA6_UgVCSe-KYcmP_6%)}!j!L5pwsNR(szs?1^}>hijr;KJH{E)9x+9*1JP zox)>aM(d~hQj*@__B4%BM^W`tHg$IJGLKOc-iIkk=v-yJ;*PyB-Lc=-7VqeRY7bzNzH836w|{A-X`jX z=SjMpg#xjsK~uBtH##bUFQf@`WSsx**k^|*_?=U+$L>a?5XJEGh;Bo;r32ZgMBs`G zg^yxzMBJLOiJS4zTaAjbUPrNxXP)7`@0N*pdCu4CFE|tg^8nVT`QLRXLDy8SE~k`o z#}v4nOmSkX1U{Y`zjoDSV$D z#5U0g$Ai}Qzg<23#d%?ig@svgz9=t@#;7CrqI?1lpvG}m&1TH3>Lw*S0MB2){*q_p zkVs8Qj`Pi?+1YR#!BeLPPM-NEAg5f9?7Tv&1YVM>j=8q2FZ?~4^f@W>7JtQ2C~*5p zooRDx5H%7%vSv&q@+)`Dp3Ght8;z9vbJ0ARUQ((-R8EvzxmwO~2A|S+$Ob2H1`*eg zG<;&fHCItW@cFshf|qZc`DZnAV=;-q{J$)AI2WTBL#Yi3=2b3>P3Q%_tRlfL@6t2D9gJb$)(_H6e2%IJrCnFs#B z8Vo=52WXrr^YHZ#$q%r0|6JeU{e8Bxe~-SYu_O4z^4z zJ|??>DW6p5+q693B~SW(#s1&@%hZxqmP*&>TH-K8Kjm|Uzl-ItEiA4e^chXI?hiFa zj>_pI91Lho`a*s|uO{1SZwU@@;3d@gR$>X*1Inm>26D_UtLDu-7txa1J4-QQ0gn*8Dh zj+{-9tVqWvYa$sVq!o;!24j*nwSDoln)1@6sl0Y~Ixf zzhoVYwylffGo>#aN`sTm{8{_$W59~HQH~im`_;wz?(Ff80%9h@%k}m3xNoNuwM9eg=Ht>e z4b^T_jUGT$t>W40=TeWB`e#^8pzW3xHq^}?zfJoAVwv&rX~Yk7|8rURyR~_VnW)EB zV^2k% z`Bow6I(mkku^5d}RnfUKw?|c3R+~5VdiN3U(C_xLg(RS=r(Hf=gpJ zoiNNN%frA`$aiMIH%W8^h@whi=@S4yP#!CPay6a%vF166YP1GY?!&VPm(MpHqCV?h z!V6aaU>5&~n#x~|Y5+vqf~GeB!ZT04n@Zqiq54@q^}mPY%Cb zCBktHM;Iy(c?p{SBGM1$5#63KlS^!qWsnO3YwOIbjn9byM+e*Y(I&~uS7l>QiE>r= z5NlTh$o}J=_Z(1j7u2I`fGl9d+GBI%tBwN%4yh=)4ErO2DhDv;8bS+m&)DQ+X1)2> zPrqFu*3Zdt|KmKvV+!)-iL%OxvH~p?HL?mC6IwAs6(=d`3aBPTFh20kSjY_Zf=5;p z_lJCRj1e{PZ61Bhws6w-&l3TU9a zR=|WRY3zWOtUHB!U|A)`$;-hP9J33Fc8YseKu)f!dyF7|H_Hp={O_y%7TD(N&(F@H zZGtwbQJNG=D(}owliMH2xUa_dwmDl38YAT~$^G5*2iBAol=a!^P^!lCJ&1|sC3yB) z0t&=Sdgia`68kMcYS*CdtL#lP(Up&@!22+DLT|eeU*@61Dy8w+1 zJ4hkiUIXlBYbEoVFdgs(CY$dQ?1>!-(WZh%cSp$;DYQ#Vc%i6>+d??H5H^I>{4PDV zP6+%8?DHRmW%x3oOz&u2_$XldKv|(JA9zWNgmGnKyvo?<{&s${5d3yqJCC(f0~%{GfukhtAj0E;>wjt zlCP9`zyO!Ibrn(axpH`ch%hGk{2a@56COp9;Hs?jT^FSAKek{dN7ht{@T>JZG^%M? zwRJN^<8UFCF>pWxjlB|%gG4Eyrz8Vpm>3IWuUKvQZuNuIr$hfgsHR6KQFhAF%H{o& z$)dZ(z;XifsUXgJ0BId*^FTM&$|;5C#^DOHRtH$wSw|xOk@U16VRh>H3JhN`iog|$ zWJ14=#vnpZ;!q9FQa^W$B(l7cHLalFJuByd4f1__C7 zbHmxQ6aI(H?WT*W9MS#AR^b4P$=kuH>iE%yAE7+JMvJ7Zs(W!~As8J_rcd7ioBifJ zm;3(*?hWIC;`mS};{mxH^gs6l0XDvwq~Nl(>Cw z<@kCi9JlWqpafxaLxKV8^w(eYt2mOE``;HqF2XKLPh;&uqYxINvSD*J#Ey){yoZnm zp+IA~NX%l$ZGs}WAek=ui`^g=Cb~%hva8M46p{WeuYD}38uI;$(?8k!$p$1dlV|On zaXD0 zCIbA5efXa#Oxg7VP9bg*zQ8;N+eh<9yZXYw8wHyPlh`X|mJz*b8=!lTvce2co!Zp= z==_%%-Z*>a)@5d+I<2nVR>N9Z9rp0>e5CMBD6VC@w-~4V;~R$m2OXx>l?^;Dm8+^R z#YV6O&j%jS#O^rsFu+@-qgNuhgT9StdNAetEE)efQPac5kn-PD1phtKY+;%0_`JEU zyGDOmW;(LvRg*2z#a3;9h^pbxGKebdUX8Wco-W@Pa-XEZEi#lYE$!4e_|+m5yRw7= zK8;B$aKa$3GulZ19(h9v|5fP@EhhEMZIl;uP=6I}GjkN2U$US8aL12drE9Kp@a4pA zUI|eT9gG5dSte9a9NA|6Y!kc)R29<<;-X)X!4obktv24uZ>|-L*ohlg)`h92?2dcc z&N8pG3h;>kQF%AiM?A5lU{r)yjxKE4*SP{r|6BY#mmfpN~b-sc&yTD+o5ZG;KJI1~TOrID?;}%@jI( zv=GYQWUC}3_2&O31D*5J$kvmOOH{HU&`#I zAz^I~oRGhkVR=p+c=Gyd?_WZJ&cGA3smSSi^ax#&a~t={Fc_kkaH6P9*j{`J@;c;V zM=p^}{Y^&hrQOB+he99N?dmzLykI>r{afuMtlm^ZGBE$kN@43w6X*v2N%1W_tbHFW zGl%dEpgF%GY?TT}W7#NC-|niu_mg8F;76&Uay5e6n*HfyCje+&g)#hV+X}^AXXFbl z7Kx#5cWVw2WXLZ>w8x}6B%}{ynn9jILuq-e14xE<>K0X(B)?K>$dbnUX93&lSFMO47FN$uDgJcKB}(Oo@C6gwyr~wQlWt7my8JJMj$zZF0B$Ux^(Fc1hOC5SSFqYDvl{?ed*b=3;miD^(PYDz;@w}-aKJS zGjD8sX+{G&ls~rP?6zcy-GOSWb?nyVngo0|KfNdz6~wAdvd<`AOVh?!L=txBwNzZy z$bGeZ2V>E4eA@`bNcss1edv2j`x-_F+e4`ap7k!pUJ}czOKgb`h1{=LZaanu{)m|! z+J}VLNm~)cqPN?o7!Jz~R)ULonEU)CBb7-|T7U|*{!@2-q9QJt(u#7H@oO`}@wK`4 z0p=e;erq|P3?s?|-xiy_QxpIgn4ll;PNxM{=*m~E)>y}YMG`<*!X|e8m@X`g2Tgq5 zdRIA|QRCcARf|?vOm;aPE+?P$&zkZL%MSW4GiwK1P{m;K{0w2gRrC2BpY8WA-8k^F zH~WU|1=o9pKTPIiO|g&EyrKaKUB5`s?SK;L-9~?hlnq>xr5#wm3n!I9liF5n2q^4r zr^WUHJc|cJ&iI8@HntOnE9hCGI&(3qasODT6!y>|4Zb60xqPmWPGAgZyaG2X#_b#s`>GNYp8x=+9ZcKIVvP*VNW3Yt+mQK z=oQ!huJy8Q!8O;D#~Ebc6U6g9O?A42nnp%80IAgPuq3}FyTVZ?>w?5>4Adjak~<1s7Ki6#*K3@L07d=B z)rPSj{sibi=icP?P+|;834XIm-6!bt?t*YTSSb>7i)AOPj0I+mNf)N)K|G`#(mOf* z<^1#aKUYR$oqj4ge*x_^K()PNw|o$UO?!RksjZ9ZVSsLPT<~j6Tt%89L~9sh3&(h_ zpJe=(zuX~RjP-n6968qYbSOLxC={ga?7_IY(H6DB&1VKpny zj#(aS-AxmD`Qm@aOtZ>VrtLuKzkaO`u{Ln@5|@L+rvqJIZBZxB;NKH+q<1PZ8KI)c0lk@p)xk<-bU&d;AU!K!eVtK2e}z@_5QMZEF!Ly>=<&RGxXQ z;xbyeHjw+Rhg#k#kYG*N|HSNfJ-c}H&80}YKixVOC_XCgi6=b=24D5Wzal^ii~A`$ z3)`S72OLik@H9JWv009weCZo6v$7lU&9;vQ3ADI(0lXNe{5LDOE!S?E`$*3a6rJMd z{cO5lFRXWq1oc~rFVZnDso^fr2LGqQ$N?X6Ka?L6kgNbd92jt+>Uh^$L=}*sGcU)n zI6sEXA;*-0B!qC@)IA}pK^T39Hpl-!zrB|L!U(+}5?+|n{h2vgp8277yby>Ez9k$I zz-JfTF09y=bEqtvks7Xj@TxF$l<=-v?Oz0u5+iC*+v$8e@8z$NZkH}a}x@aIoAZdtMob@-D(hNae87J*3>q%E9>~tKnCKF z2Ci7TTc28dRz!d8OD3c*EaoL@fOqAxZ+7F(6z^l%w%}jU)6^YNid~GanJ*Mo46Z)O zVWXqbH9UtGM2iWKt$a{o%;A+P@iZ>`Uw^Vjw!)a6H}Nm>gHyza>*FzAnM5nL6wED{ z2g@Lmr(p4+!6HXyy>O5^LMc88Lbg+?Mf>LMr>z@tIQ&*AZQw|60kXhy@AQiC$T79( zBL~Z|%M-%rN>2@BRrCF_+?Yxt4zJH&__$go+^E(2(iOBcy2BbI{=92u7P;_JY>r3g zT32*Z!n=ib*265he5H5x~9Q&MA ztt~~`1fW%z^3IzWoXn?{w|vPVG$5*&K()S$@M~R#yV!SsCPOwIzW+;@x&Dp=)QO0j zx9lJ}{VnRlIk3^7vha$F>)?_pzvCm8S+Ozz2vN&EEDv7wDVd1{6GK81%Ty(EeKii#x z+o&YhliU>)Z$9w4B$t1}^9WnW(zPP?_yztkcZtStB3st4sh1%kSDtfu!c4)2=*3+U zt;1}%E`6xFEorz@Ka~y3L8Oe5T=(`O{msjqTDKX?+2aJTY)1L;FHvc*K6!uVBcOv# z(EfwWl-vJ#Iv{Tt8+T377HWbnmJc(hrA`Yali*B4fy>?IuVM74wTbYrH-h{tXIb$+ zp0R2Df{%)9`GAe{Rkzi7?@?DBz|%-7>1%7S#vig-qQ{x91T`LpgW}*UP7ifeBCYm# zYe#AeNx6P+C_bM*v43&}ktD6)`I;l1aYpeTjm^s^Ik$rHQduj$s?()~_K_e9q$ZRe zu&nGKXC>&ld+j0h67y}Q@(YaV0kLOePLZ6&ZnvKuNPb1ZKX_~D01zN>JWly|rIY6T z!&d9Xk6>}jL67R@o{b%r&!58C&T?O*Kiwordj7d*X-6Vx<6i4uz9y{1jqCYC zfBe!j>{nBYYt2qXmPchsZ>;Uzqlqak`azD*E9Y#lSb($ql}Q$ETL}jI%2Kpf6AtHIofj zb~Q2v{A^~5m*lF;ztWyZPtzoHR=30FDC3f@8$Rk{8feQCX2%Npa{V1}({RTDLZKdsgEDe8ZUj zwIZh{9OMr>Gp=Ae+uJGivlP3P@zh>qKtrB3dD5vVNT2F; zBQyd`LLsnskJBMcGb=+A1%KO3uO`{CT$gXt+QL8+tvCmbrFNSljHZlf04)eiq!EKh zUc1=6@@3Lsd?s>qCGYf`@Q3G?~-K)!VaGyd=P z-2lIB!J0OTBR?DUzd2(~gAzGF71}_gdMjG}rxX-{^yPlFu}V?IRqh<$<5ve|22;(I zNUIqzW*xj8TA~k>#D;bZmIsAC|4cinjY4CuYr+Hxblv!tYGW!{61Y)B?w>|rDNJkA z2Ifbesm=od6%>H^e_cQAA-mw3@!wP8U{~y^WV88fYTIJ2mcz2UFH)YFS@L`u8rfw0 zqFikDdy#};D707{l`Y`OgUd4on}?3xA-6fPlfQ`8qD>xjb#k%8O~&jhz0~QH`YY*i zvuGO`yx?})OI#_k?0zOkLRI>S_>J}&yoOmer_T}i%ocXGLq@BvV)yR-W0>HdLBU4^Th z=pnb;$B!H#(^jTi9Yn90VaJbb*PX4@U=@~s@aIMita zSk_&bqchC77*N=XrN(pt9z2OG5rgYG$sF+NQ7W?&kkeR5y6VclDHC~y2wK|q-uCfI z+;$J$whFa&!@9IYNJ&bKunbnTsoTE?#83yrK)LZ)p&7VcMAJ~IG?N$9K*JY8zp}}U z@;A{7Ao+-P}NETKEgAUl=$`srI8?F&rk6*s%?L4yOZ-=Zsz3s2{J*$q-?Cd zv9-sh0q6M%=P65ueOIaSl>$c!gX-hnW6{{ZUQNtXUn>aT)4avlb;a2AR48OvI17a- zo_IN*{@%^+WkP-0wu;|=6wlkX;>mnQ41TS-ksV!Wvn7iSAR%?T_jZXe^`}ko33yyRnP^^IT5L z??`l-?^hxZsm1a_@FoeoKvUH)pq*Hi5Jkt9;INVz2uIZJliq9T_H4p!95X5hA6@_G z_2HD-Ys`c-Vabab$O$!wGv#fmF*yJRr%m}leEaIFVV%kr{7IdP5cPS36qk1#O7A2< z=k4~`%K@G^a&O_-CNNkGci48wwEdy&KvBW(St7q)o|O!8eq?Q|zPYi(uc52E`}Wi| zSD=HQaY51KtN&%vc;M!3y1Tl{Fq*^Qbk}yA(@NrHfj;kLo4)mMV77OEhsAhzz@1>m z75aa>00a&E*H?W<>umY0uH+;$(1MfNw0((Q__UpG?#cYwR3jD9_tlTWmM=y_57kN^ z?Yz{+|C-brx*K>oP0wQiP?ro=WD{yFUe$D96~0?e8{a7F7QXCIy0zA@*;(wW&L#L5 zNH7D^^y1xUd->@pR84@o{Hpar;S(|FM=$5~Rgw3N9p83Xl!N#026%4oo(AH_^RSa6 zWr2CQy)IboP_r51BbXf4-+lK$WINF7H;;AH9ua<`H^@!WY6Pol{qWTDMjZLgn(Hex z9_K{z){`F1?aSDu%BGP~yP|1@l{l}Hu5*Bcx?IcaM3r}`qO;;3>CmKMghwF(4yOqE=8y?7Q8mi zGU)^DHoPXzXg|#W>$qT+=E&0`_I&`Z{Z6uYC^h){HiS6dB1X;Krwu>|Q)%{HEUeC+ozU z&|8l8imuh_zfS_~yG!|m&-tv-M#|#2GWOoGpFYfBp6wqqq7<`sH^`~Npa8)$W*!Y~ zd-(TzULY`TWR><}Ww~v+_Vb#vxowMS;rpuv@UAs&OhF6jcg|OoB&u^&?}`zi*qyZ^ z<=BB=*VNJ;Q%0XXt|^mo^^M2!Yd(mQ=v7?V-(De7rPqwC?R$6z#HOWP&&^ltCO(P( zuy!?G)7H%5KjO*{IORSKn>})A_S*(etc+G%`H0g^R`O*)7{~)b z;19UzW@DkkAe2IV0EjU9Tb`H`eAd=)srbcwMCT6Q{Ml!`^N+lT&ngrrehT~S_`7~! zJ=d#!Gj;scusOt1USExB1b)#Oe4%V}39diK6w2rQN!w}pr^qqm%mZEhB3U>8DDc?x zgta3EDysK>Q4SUPb3giJ%bARQcG~X-G@OFRounXoXDH|zzUA>yzv z^o;j43azppFSUP&7rCl4*ZwY^Hrc543gli2m^oB}>Y?%Ei!?7DEBe@IC_P2GzJTf^ z0zu>^WGcU~(|zL4C5Gr@{vzo_cFZElbyPlm&|~EwB(P^I_Kw3WN2Z)97QmxBJ33Ef zW?;CTTG@GwV`h?GI54_UZRlal_4CY29&D|jnU(o;=mu5l7v-dIFM)MXqnT4p{^P4* zKbuwx8v27+Zh>;XM>(Q+!wz;`Hlr#ZRD60+?(VzK5`4PNIoG}GK-?J+y<{VoEkszG zy@I_wsGfWH;ld*i7f$=b%8zxdY__3#uIE%EMqP}ifTY;9UgTlVimjufvMg5UHmTQd z-=JiYA{*RQ_}HAE5Ip=IEmRd`p9N$4EvAC}+w=m`di94{W%KwzHg~8<*Kw`sdT$pO&mHJ6lQk278}& zCtSZ-{u$E|zhSNJc(UgYwIMsx4^YLIPEw)aPuDh9g4z_{%$xK z7bX9A56bQ5{acEbvrle(y|u7k z@nZovPn(A|HU_r^ip8f`V_)SJMS*ab;fdSNC~fY8S~LY0$YTSaj1kZh8M1O=93^=2<<4_rwbKpIG9*V`>JWD z5KzQR=aqgJYU5&-@A-LWUv_Zkc$H!GeUFV24Tt3)p;ify%z;>sRcm8JNROjql$#Sf z468FP_=54t=h9E*#sc2FiGG?$#)Bf7FDA4@uJ7YR?^8Wf1+nh{9ODt(&<$9)K1M}e z^~XoJnLHx_O+_98_LWqLEx5Df2_}I_QV0xl(OYq$$d2D$@CRpq{Io*TIzv>>gjf|g zBCb0h&X+$zf#uUufq~$)ImLQjcRE8WcWzJs&(_mIsDH2)7()*pXL=dGc2~N!96VQ_ zHSf3I$lK%cAaS+FY9NZV%BW^^+~Lt6^A_94n=_H|{gaMJyC#jZ8w#}z6ZbJ+(H_fi$LZOTwBHDiRI2y?p0u(+xJ`EN0PWP-$-3;D?(`M)w zW}u39_~? zgx7Ju3H3Ja@jI9hSpRxOdPI_M3A*4JuOj{oTlT8$dFo7fB_^9CLP%JP+86uuN{B!5 zNi!#HXe?MenFb`V$K@V`Wh$&ubgoPB7RfA2%i@5W*j7Ed%})H0e&^`J5sMl zQM7^U@!y!B040ta9%f7`N7}{{VwMED8lffYNXL5?AfX>8k*|iL8UZRQEDAu8@z9KH zA{%gBshVV51mk)&xX2|({g=$2cyG7zOw-7N9O#Q_wY%&Mfs8jp3R!wYm$gX>x&wNu zpas)mbS~-1pb#)9x>dgdd@FP4It7WtVM5h*laTudx5|<~D-3};{+gGLn*MF1RKyy~ z$3p9SAum>S8R{#sR=ea~)=**hn0r79ii9FYotZRi=nnHR)-x8!aBrqf4nnoO?yB5^ZJJ#-)8>-&BmagoC-kDe#u8jd0h9Ahv!5i9&N1>|}!H;1HJ zSem-I8uif$EH#0OJV+HD;h-HQpTlbJGJ3IF5)0^0&1s+J-iyjQ_SFQ7dHi{0d!gm2 zCII=(`%cp9QC#RP6?pqy=dxrUd z(TY?f&&aN6`by?lW_^7tz)@)Z04!E%3ox#cFy@fNzQ)+OLg`{}pk4?;JlsehKn0o0U~Zf%_nh26t3EiIpnqUK9aC z7j0%$n9EeLgyNO|tO%pmK+#?WS_xmyUo)i0w@oF$#zaoBH2(f|x<1d0t$3v>eqA{g znf5j$7oczdpoyokm<@X<{UXF{X6!o9TJcg<0Iv$jvei#)xVM;utg;C#kXe@NRUaCh zNk8E>y)bp+hTm63YCmAnnEIU5RBo`D_5R2AEmfuDCZ{N-3Jd(svBV~|mT*2qY`do1 zc}m#Ly}GJ`BayVI0PuPdi1M@s@SZ^U%QuQ2fJ^teSaloulI4=0OI&|k^^;lsCMMJ? z;Om}ZFq8-%|HY&vyJFYEW)2(syrRMIkXFkRr2ZqH3v8x@lMrhte^aX^5qzeAKrUD+ zh)W41DPA+nQ2Icsnwd{Svp1T88!a332_XMNMIOHMmdlanf~xoIJ|a1z1z@??@>v$- z5*(AYi-sB}sd_V1WUh6L(C(W~;Ex}({yv`7XAOAQS&PPBKi785kX++-5>>d?uohyM z|Lu5lyQ+*1Lt#>OiH*ie92s^rYIx!mB;@Ck`RC5^+K)xf375s>Os5S2WCUT@Sb!L6 z>qD0shBh#PRaIKFY9u7gyqJAOX^bI4ZL-3pNhNZ`h=kI+9IB62T{T=FbA9 zZD4fIss?+;LwIES7B{b-%VB5uFJ2Eml8wN66`WK-pD3hYevgrwI-eX0`2UhBK5UH} zdN|Ob+x8={v7Xj=_iA%}KuEWZbw1~ewHycP(|xcQ)gl!+;q-_o7_@hsq)22H!j0_C zv|Lu=R-u55feD5o1nGo6biP|CAuqgYN)?N~#3|kN2%#q&DhBrCJRsjPC*=x(l#BPk z$d$!hR?J7}I<>wMDL0RVSfiBwU5L z!+4s%VqrhC?)$>7X>xAc(JcyG&DS&&sZr;9O)fwSfnqpJ)c7W0@A*%~zCx9<)dHA; ztO?<2k-js@J%P(j$M+WVm%+Iv*XC!=YonHAu|4ys*8|CRT*)IClFgGSjlED>$n*!0 zmMVS0GFThf2-tvJ#}c#t}qCkjM+b|4=_O2CbtuSq#A~ z1OTUU%p3&MP|JN4-Lu`5OB-nLST*CW9gNX&>Aa*U#4KN|6@< zZz?|QO4B@4P@bG#04C@Gz_H-{YVwi82#$Z@kMl4G;if?s8vCQaik-TEx*gM77|I5P zCfsi6z7v?BE!$n6YZZ--?sL^c4-?$DQ@@d!9C0p#ZqVzG{V)w@BvSe92;rs~~mrhBtd|3fRBQiD`rr=z%=6y?M2QbQ^U>b-b0Dm51=mDkcuNz z9k|X*N#5p${Kqe=Jx(?Wi+e8z8N;Ac_0bPhImuzKvbZ-ESSZvnLRU z+nfsSAsAXiG!jwGdLs=>9g(~zkX6&lFb11X3w#-a{(7DYPfpI5 zRUh8f{X`xV%(k$FIHn^v#=>ES4_DoL?L%N=I- z`sCeXS$o{%5h9vvS!}G%WR#L>7`|W=?;-w49nVpK0p2Ta@&`pb_ikqtTvv>(Rd|0ePt11C6QIY(flsi!^eY+vm={?V^E!WI) z(nN4rC3b{k{4aP;n!0O0Xcvw#lZD(!3&9XbB|9dy1Xp;`a4dybi`VabmazIe$M06r zno!!Q9^}Vwm!7Y-Gcit_uN&d_ei`IK7s>-e@qk@YlQ|z1LW!+$%TwR8;0PHBEyVzR zps=-#kM9Z{k3m;w;KKeXpC$Lg)^I2d6W8A)fxnr5pbA7;Va#s(SHFNXP_={w^F&Uz z)-e^DSfBs1p0jK_m|Ga0K?~+=aO;G8ViqFYNt_USP0iD_Tu%J~C?!4pOxr?rNKV-d z0nb}vz#Us0m8k6?-IZV>iNz;BUK6>OHG~h7Q6z0KO1?4&M{{(^3fx z@Dv)vN#U4z9X1_}jzRLDk2l?Yq_u?lY@eCi#AH9%~i2kg8U1l!apI ziKP@iUfWcwY@edMb-3F(O2OBbT~(aCC~tAqC+%ed4rx%F%hM)>7qQsr%AZ$1K2G?s zO8aXbW-FdKErwnH%H3>9%i((@C6mBJq zzeB9qouyOx(sd3-gLER{0;KiEpqa4nz_(5)KCnUlQme{tuYrVDn_lQqQ?Br?-zG<@ zVgB_CddyZoF8i&?#Jk<+=0yUr!uVfDM&w#xEm0r(Eq=Q~?S=QPU6SV3#TrN^x_F8c z@*C%ma>$e{%{wI|S|9ar6k8@g`L=qw8Xtc+Y!FXV$|%$0ji0^lB*u=Re-TrE`MYdq z%Zfp%uynlJonr)ag(RyX9xNj$@^mmRWvw}r1{~SuwaT15?a)AUf86;L|unDg2(~*1cmwK{4$*8FAi+Y%bTB zKAly;iLnt<@fWylom%tI%9G3vHN6T1Uh3I1Art_yrVF6}XsO%3eYD0_BkZ zQTc(-sW34O4!|evRIz69dUHrcnRXX#V?ji(qQVd;PkMHXRXeL1R_O}F#wI#Mq$RMJ zw#!dsKCpr#bqWZ}zo9b5hn+2L(Apfx#p+@P2O(h(dWf5uuN2TIJ=!ufp#0e>7zWqg zGRyXfZ!o6`wmJSz7kaqq`FU^i?+MiKPm}+eCN1q%RrNuR@uupRs*!LBCscD3f?flX zLF&H{j4$^9QUODTnY{B_LpXT1pHP10R!fUIS?@>=>OdYoYdug7{y)5BLrn zhAD+VVYEwy+?l?9QVs?%eqO<)>Lyk(IB>i+djB+1(HrbVDqWYKb{c|&63uBv!EJz| z(FCKXI`3K;}!zIW^lCiVB!!u3XcD+yWgS4vEUuTzx7Y3ww zw0+#JVy`L&y@xM43}>UKisr{;RmJ#ZukfL{6H`=W9>qUC$Cn0=6C_iyrK-2a-tjF2 zmBI{%-n|FzlRMUgnTL9C;wQDNEKl18PnHk#)W>b&Tw1!94nBWl5Xii$Rel@lWl5?+ zadbI`BpCiIQUM;<5A~7MU}yQ=O>u)iEfWt9Y07}$#qE1kCU5!@3o}s%oRu|`w7=yf zjFQnnR04vCSanDXqQ@-etJz^+WV{KtN_|e7tHij>N*T;{dWGnY>; zBpQk&ie$C;3%D=7J!1e<-DDD(s1>0nFiE!J-=;TJ@+9vP54V5Lrk`eRyxnzq`>EUh zb35-xp)C5lR3m+snNpJYr+~%x97l80uQVK#sP?Tdc1+gk1Uhwmdww_&f?N;Wr4i}f zREXxM8@#)^{d?{-`<;GG<67nii)&0s1Ug*~LkMxre*wooJf2Ph6(Tu4; z*(jofGSB6Lzdc+v#t0Wkz#RcRw}3ef^*h;bX)z!|l3AZYkZgAF?7DJY`$pf=v%Ji^ zw+9r89KM(^G)pmEP7rnC1T~!2TdvcoWQk$zwc!3ok5cu^z0o1bNB3#FfaQ-t+<*D~ zVDVDzMe^EPpli7GC8bQ+iVCe^Z=RG$;JiT#rjod4TZQ%a5?*0mPxlG-2gNn&-rAtYnWx-G4)Zi~84En*zF z-P}TB#ZT#MBTV>}L|tpB$q)L^rMT*EgVygtN~d2y93jejPu2BvSSmh@)r&D9-=p6y zQE4uvl!R%Kh=B-9p-&W&p2Uliqt8Av4Fp{jq<|RK`{zL4fT++U*-n{YvLMnxS|Lmg zA~h&rnq8)#Ljpc}ozRlQB!u%1E``|)-7dIo0~~yl9$U%_(eOs~DdRO1{vHIE7pZ^O3y;jIv09(qGDE)s(BlSF zLI>Z%soa!MIwK`O>XMMFL{#9)ZQutKdaRl7e9Tv}wVggpxdj#QwAYg&et;p~pPQ#R zg69`qK7fcq)%EBJ3Wt*hY^(%r>Of0Q=K1f{wvj!c$CdypBt_YG|Ds5g+^$o@`|6su?MO7{EVz#Q;)wMGcUB2b;+6rCiex|GlndAlGJeBAM2x{W-o znK5raDPgIZk7(QX&EEA9Mu6{_`}_mngOG5@3ldyn!ynuw2qO-I-LKA!+ql4-KPESGJZyXP9ET6#l%5S z;$KL>P@^8EBonCDt{K2WR#8QXMysJbGd#93Vr#6m@tLTj8sv7i+DNbtjoC$8*Bf&j z7ueJ()c0O~uMa=tEPlc%a?38PQprZE@(YSp6 zkw08FaRNcLocEm(3f%kf>7l(LNIEyG=*ab@_dB3;3ptTeAuhH(sX&(ptX3T8}G}X6b#pI7}Hz3QUJWSPgdVrq3Cpx8_;#)ImCG zJU0f_ZIqRBb|{km;j1VB%R6uonRZ@Gp!>&l2G?M+XAPfr!xis&iz?YX!8Dn_=uUxb zkNZOBYFHc zX|~dWUz}Y1a-1bYt^o6CpB26E_X`jI#6N2IW4W+-O04*#%i)%E3{8qpJWrArn1lLA z&3$$6)uNVMGN3Df*bTf-$F@}7SB38@LJ1{wWl8~JpRCDUB++3#du%YX4Rj0*pSza6 z7@{*^FN+@`I7Pf>{CB;3W}Y z(*hj|O<#SnVH<2wQjlhkKEhk9eRiA3E{DJ9+m@ZK&N~_@vOvUWNFc+)5oW0-lbj?E z3J?JsW)Lupw~PIIVRMZl`c7H zfh{fGQ#KHZ3I2m-x$*>Qe=4y)sfE@9Y1iM!*gG%xEyd?FL22(?hD?sk_0IR`Y7&um z)NM1)3!y@6G!(Z_YcXe?@#%=3S;S$*8+&m(R~it{XQ8YiAqHI`*l-9l!pe~Z_BVxu z2r2&B$5&rvku7eMs!QVdJfR-}5z2v3$URPx=J9_25iAR!uk1SN`6-&$E$Ls|&74b) zw0NOF@9-t0Y8}Yb;Zhx^0J``i__zZ7y%H_cc{CxKt)=58BH3;uLEGs?X?H@MFfaAH zTn~4KO1EY1<_XEWm#0>|Zyp2Tq)ZCETQiUxW=KJL$_eg!FTZ)Pbd|0TB*Is!|MS?@ zL+MhIHA5)QNYfUTtdc?b>rtP-=~TK6^X|pLJV?lAYnit!ZOX)Xa-%&sE+4fU@=OC) z4rIaJZ`qca7!Ziyx(IKhe8ftnXO$uUo(jo*okGE5I(6?Kt+GCLj3X)C%Mz@!LS~FtXr9;pCis5AK&f{(+m#u+*jTs4lv|`S4 z8?$Tcr)&K;v66sjACFx=bKLrOTAW&kkUZ_5)6h<}57u8JD1vB-U2|LGwpQ*4xC&mM zv4YoZ`85H2?V1nW0|H_X-0mUvPR&nA-~h}lCjezhvhfptx>IOEZ#UVD7nAHY>c`p& zEj<*OnIM?{oM9t-#fn^k9D}x@ZAFap6Kp|M;!q6hdJD8>quO?mK(jL$bdH&1sq9G9|O2Fn-T^7jQ-%`nAU$P~R~e%6Uf~B=X*0 zI>%~`W$9wV)5&|bT#PJF4__xi*X{Ago;3ji;D>9faYFlS*K;QEg;Ay?IeagbQ*o5Q zt&-_d7 zZRvXM6?O9?A^Ctvr{~MM;rt6~LO-IQmF6-$i_hXhuOmXL_5{>I^{`umQ40Gxb0q*e zcD0JDbC%XQYOs$C06FhbbCrgK3nH5*7F5I)L-Yo68m`fP@0}D#*nmTpoX^BYV?!3K z0^g^R&w?Mk*T+-mVauJeG+q3wy0?e}-n65^AtLY~6)H~-M-;COyOS=7o%!JaECG-y z1E9%$-=Uyp~bhUB6vd+d*eUnq|QcxS)M9d|7@RPZaT-)Gx zSQ3_9+0O&KKMVH{$;_MQno)y)Nru8jvtxDKA7?A)L;H4{imT|nzKExja;;l|?oi_~ zQ*61rmrHW^0a zDdA_244(kd$4>?howfi)HJNrAUfIobA`%VD~ zHi19*J5ogGDtBi3GW$z^Apvpci7hRZTcR2`BHUA-CM-pX9my3z9yoZ_Q1^QdEVPYc zP`UXAm&orN612Qv;Vv}HCez(v<#?A4rhxwFWW@0k@MLN^F)h9-lO%4vt{^G)eInVF zkZ(S1kx>A9=9p$CZT3X2PGIZq&UoU_B5{b^$tA@g*N=JwTAz%B=}vLgq;TK$k1yb{ z1J>+$^IJ^(WXLN=fsn=f3 zgG=+aRO9NVE`L zIzn44OHSuJNgE#fI?7DPS9r%K<0`QkKFrM94?$i^RFN{lDg6mF0F;585ukwd(5UAi z_~vemL9#5tf_BTgWz>qvW`q>wdAm*S2Jhh`>Iqg4{N~b-09&m{`*)``v;K#B48gF&Z9b=Q=dZI4$I|w(3K__NI_+7!79;%X%Ov# z|F(f|jwWks?Sr}4L(-u>e_vG}ukG%&Y>BMe)$Vu$L#~1-y1?Y$)E4Ze6oW?y@2p!X zAjAd{jkN0<*KG-F!zrrD-igr5SU{vDGJ2B{j$_BRxna{Pnub#o{y^6_c#sW9i3e!djm*%Z4&oHiyw4cCFz6gIr?wYUf=QN*I z-*8*uUh_?U=?%H=bU#*hC!vTU{+{D;78ZOZ0^QxEKqLI^5vL$TzbTa}*)gYl?~W=R z;b?0&yP0c4v+*L3on8JS`*=Z+x&>|O{epP?Na4>`|u|y%E=F8 z=wKlzpctz6?XNgHKx}l!I0YY9EA3!?TR1-c)kxSKu1=zxWbWGyG*^(-c23d_MXDi) z!nSvXp=a!D{{YMV_23mom2K4%p{pLE7*?~*j7i%fB`w=>d^XG9^C~p?kTlsNI`i%N z=-q^UrLMDIg@cxWg_R{VpleL2!(RcD$ZGn?b+`2yJb>-&tGxR3?!zOrpuC7%6NFp9Jwq`-Lb+8gJa zd#wovKA}~72f?@fdy6r*7s)I8o>nK8U!LV6hu&gG}boqb9H_Cbw%Q* z)tx1ql4YADS_2$I1BN`G_h%-)e6{%fZK2)tKGeq#43C(80Z8wvW0omX35B=WFCO~D zZ*e}*rx@mW%Pg(F-7mz?Nc3>>-6}ZmLM|6naddaQKo$_HP`;ke=SQDLjiWz|jn%tJ zNp|CO3vw5Sy*>w*rlpLn1`q&Th#n&tv`6T3+XCwtJ%-qpN0?2Wr)|J`V{XqR%gSI& zenIcHvL4}N6M43|G&A*MWohCE@_MV}kiriJ8|+&(weQV)V-AtBGxKI-DX1 z`n-J}e9YYWTGud&KMekO?S=q1gWUn{PyZy^^t&{wHit-CS zZ$fb-w_jWd2fsF&&TGBfA}nV*cWq*hmblLgb#Ektup0@BTPc+-U?FYX?U-F&qUi(>plhC8=D7|@@n#vR%F06{vvcIWHg+Yn3rMB&%@ zaT(rB&rSq9S-nj(jdIOaXRB^_M?4?0n*X{031g>%=}?pkal}f<-lZ=iMIAbO6=g;Z zGZxmSKfl)}&1WT^0Z=$`mbq)CXcK{zl40v^`W!&hA3wQI(ltR zPJ>ujGSU|0)MFXpRX;1KL(rRlAJ5+2qP$FA>|ONO2Jb*sh2itXHy+XY!4Uk8+Ip6)%wIyr}NA73NeJRao)naPhXa=2nVrkioT3K=AGxDUrA)|zW zZRKFKCEwiSM^O4`Dmc@bhBcmvgXu0oj7R^|l+vbTQjeb^L=8K=E$;gkhf355!VFpm z3(0$nqodYCDx${&vTyw&zLiy!pc4TeXc>-c!v~8ka@^M<(0RhkXFw${>U~d*Unsa9 z*@$2~fPVX!Otq6iV5)ro^}+AfkiIDaPx5#I)dmZgLQtUi54%IlqMg30_fnxXEr_OADq{M_U0=wLOnV>8ShRoe>(g`U|TWjk!7yWv96az6c3qfDbF;@qGcBFh%P zsEftBKPF9yYRt;B40=D>D^h(n;5&L5t1g>FdA*T(kt(HveKPrFZ+`7h5*li5D#l>* zLn-O9r62;QPwXDG58r@CZ{TXez+)}-Ljg|SS#$gj_0KlvRWAn{V4T;dz`#8z}X@`JbPJM9Is;(^Od1vhlE^tU3pRP z#S~=hw^-6#l&h{w1UAT)VI}@fhBf6$YLoI@_$*HMg_HN4FRu(AyuKlBdQJG51}Amn z>g0|8g8MaA-xhOF(NZE%^8Zyag&E`YQy$>R+X0oR*DW0$ja_T7pl~_tC=0wY-Cryo z&E!^RMg&SkXU;pTF3uQ|lUIJ%!#lNt*uGyedExg?tHsEc^^D(`_(P{{AsUh&!#%H} z{vf`WJDsd(Jq?fM8#tJ#sO(AI#NDhHhq7m~)*CrC{%3FTipaf^j%Od8m{0QNLY`Ry z-41nl@q=im>EpCpLd2fn0KU@$>F!GUnb^L5*N@-QQhkpfC^OMnA>Q@FEW$Bcme4^W zv5vb_T>r~KWqh{!30%osLxNiDbh|mu|5d^KX7ZKi2?s3zUTOaFPp-<^YLGe2hhn$d zfVkkp4uvwyecuR7{U6W_R7Za5esd zNWME-%v&sY2k&{~lnvCDX&(&!_GdY_D888bnU!cF#+k^5kl6T242w)Xxzj&2t!^N$ zNZ`#(7wiB*`3S{-08^|e5I=`YNq5)?DVMK@L2-3j`Gg|E+dV{k?aF1_yLU=b!-npe z^!UHu-;A5i?U#2NB`haic{*ApA^;NDzEkUS&l3)e0pDDn_zX$?hfh_Tby>$m1eMeCB;0u zw2^8i_1m<;SfGzRrhCz&X1`B85F}q^V&T=g*Y>RPD_EWmD9W7(OWW5-5dXm2WYhby zrUI>+qJrK0xrQAazKLqP>}*@L59&~}DUf2&m6QqUcxiP8Dh1)fj-(kgHMem2u;u$t zMDF(%uAa(XUIZVm9yVVB_}MFtyiX#&$iY8qHToI#IUNx&BB7DtJ3q|CCxorA(AS}P zEP}T{zEu*H%`k%1w<09|(sBznr;#hmJdO`zILhj$SUKGp4-U6QWiNjAeu~=p$xQOb zxU#)Nd=)?XmmI%Qi`9&!9E_V9PoFZZR5XDiGzA%h$zFcQFLGUda1Y5N9lA8bTbzh= z&=VOsyp_sit~@k;ewd{&|EgO%-Nv}>(MgloZ8=x_#OKW%#E$sf1JI={ar7q)*PKXZ z+-s|1DP#I~&F9?-jnfwUrw31mxMPM8y~49@VNQMEhrki%ew>i~q`dVg%r#h0oqCaz zE1shuKw~kT{r(QSXq)NG?!cFqqsNi1P)>^jz0v#v_s`=!;}7v! z*_e!b2q(>5uf}xC<*p@HIhe*KyeqoCHfadXt+JfE=}n_IL|ZphZ?2l$I=M_dYt1Xk z%A%ehO}45!?Sql}=-v~;r=wY!1SN}B)z|_bA|6fB_()qMi|cze*|tj-qxNXkYD2C< zUP%9L?uEby^0cROKrjWsQ6yeI z+i2|yE{%@YDh+oSD@l@YuAlA;G~`ivJ^!{~Pqg?`?iBQ2|Ap2TsHlNyjcp3SDfkn3r8PufO<%KUjp?CBm4_bVa!{Am*#S$nvrOjRVSM1_3Dj3So6vs?;_@QzAxQcAp^Q4y|p2l$K( zlX*i{tSD}P;e_P?M*aNbSO{%X8_NN6sLQGP`B==(BD|SUkMpMLC|@a$ZGo`}D3bE& zGoYD3_6wF@YL0oJcbp(m5FaX;D<0EmId`*pqq~I1nepT(ldTagxM0++y2(?L>(vc?}Qa72-bLRsgW^H&gnl4qi^xozpp=p_wNm# z*QDoa#Xn!55kG%qRR$%WOi=}od?Z{yvV=YdAJc_^S5VBE;&~?X;}%)+d*3l`!){Tn z`BrZw`a2Pv>X6?EJ+Wreai~W=_1~cz@2;DA@9WzB^=IG|L1LhSPnQUrhBX(u;ZJ-y zW@r@S26BTe-#6{xWY2mgRc+b6Y6{j|W!Zc=QeT>ZT|wmLFs_doa^SDc zDxbbx7elin;frw@v0q|8E@w~LWjj>b;V5^{qj!`(h3s+10(`K>s@8xbhCg{f{aU!4K zuZCw20k6*Bm2&M@V$?>-Arnila-b*DrXdHUW@ZHUc3E@);VQEv5334kM`EwFjbTwh zTT`Zxg|gD%x0E@pPNY-@7RFPv>11IYL?||R4PbmgdparDukkxKJmSRoXciLo@X_CZ zpPqR^Wj%Iz^I4sF|3?3?u;-W((COIfa9BPasGE?dOAoEo$vHRd?VqO@dXYR3_!S#* zL`p`?4Nz1xV8M1Jk=r8|@F8)>9TXw5UBOKLZH7%+xHsK?WB2ygvUB_#}2=1b^R^mp>l z)XU)K^DlQwEP=|*D8F(Y8Zv@^qYb{`u8oA|riC2aY6|4J&Ia%7-}lODAtWw=Rbt zx&Gb_o()Eb{Ct0arKwTCO{sQL7R1&4_RMP|#_*W4)v~_k@PrfofX3eOu%?z+V(w`+ zA#Rpuf<5^F)4B9@lYp<3O;v+AyTN01izWlz!!p!=FH2&mehj|UMEu$PyMSH*V*nM= z&|Um>&acbYT3foEb83K7?bBkBK$p~7=6bi=(ah^(J(R-DfTDx{OR_V3+}Js|ec3>% z33;HmC9aM{6-0PmkLH)}q|Z7d_o(7R&tEr6aB1A7@WVrJ+=hivBNS1S7hhaON;!bj zD`k7h)b`Z)Ef%KN&3e^0mp7(ld8aEJQ#3w$4V;+##H7HpJ5}XZ3U;OQ>z7%xvt(ln zMCm7)9if?5FuszVKkhXrpv$Qb_b7ciiGya1sbGyg-))8Ge)o>pd&?!`o!nWV6SDe;iQ|L{Q_FQvB8-2XRT( z90!gIukO5#xKVG*f}R1Cx`)!3L-b!pY!L?tNdV~?Uy(z#A;*T~ZLk^dukNhqUCt)lMl~KxnbTprPywdn#7IxRmBC-0C98^XN zx92HPyzq!+Z_$p&Z9(sNWiAHSI%Rq18_QTlC%xx%qQ>Wj5QZG#p5=1=vkX;78IqSF zo{I6yeTB+GZOS}bym`3sF7B!>Cz0%bm#MtXsK1&w7M*!vdRDYE`HAE0SsTybQ=qy- z4P1gv0)n%_$8SnpTj}30Q9Z5!&8_Q+Qy^P@ZCers3H^i8bfj+WT|_Ia&v}c(O>w$| zaBEQR&XhqVw(gs=jrXz~BpW~)`|B+N{;&eZZ{(Pm}%Rej#SMl4bfCnZc&JtzB-^pv3@;cIx(T-)=?0FeD?<&FF z8t$P+gdzo6q_I1q5A}N8_XesodCij%bw|fi)h;{FvE&m8pQT8Nab-^LXzD_F;|`mo zCbXB%b7r%UP%{^WR2PN6W21_|2>At^vEULz_K`{QJpL%7!S;#2=S@hd9NDzXcV9g| zwVG)MnRx(}8~UcAXlb7uHwL-zmXx*elU7jOGACt_UE_S6VtwJ#tkF%=*f-ZL zuN;!n%lEU5N+RRd_AJx&v0V7;Bgj31Fr3F0M&LUwzbj4Z&rE4jZ8Li<5ai1!!var9 zzW~UP{;q#Yiu1mRj@HURa~G(&i^odSK-T1mM|ElX+V&)Muz~rMMW~0!mF)4(EynE& zZp~TK?^dSIBJ*`$y6JAsOqjuA&YpGx9Et@8#X<*ohXNv~K>ub3qqqK^(0*>X4oyK& z^9~Sb2L7Yw8V<-LhmQ*$;nAkSTrY5L8HU0wXT|l1|1z-j>M_Na@{;n@pT6^xh?l0` zcE`@o)%7anPcpSB-Ts66aP`wbX@Gej{Hf6_+o{u;D^=V8vbD6%v3E4899B{%J8l9Y zdoBT#0NdD3e#8?x{k}q8Q|y{l?r3mw;=AOrd$acL-K^^!JVpXVUL};39_~__A07ZP zwhB`$!ND{)U7qV6F?DG{QgV}tz-Fp1uownQhTvTI-aq4VSTQdR`kWcJUe{P^z9Fj} z_Dw5Se4?7!*fiiTlU{#&2S*-fqc-^7KXAY+q#~G(98o4KHZ}fUranC&aA)SGby4q; z;LDref6~@?`eDli*$`>^f1`EU6?{XT$F^JV3%Jth=H)Z8gt;8ke^T){F&;Pe8b2B3 z1N|4BaWgf26^+Od8rwRpC=g59;~;K1wR`2Cv#)W=}P^d4Pz+mtLJ_j)b?AiL-3+E{Y|i~Y>Jsh zw%6I~#dW15Va$w=qY)%PG7!#26wK-2lVirtmZ6fx2Lw!|ZDv!0O;kZ26+-m61vO&= zZ5(!R0{~-Kap}QhMzwi$P|1g00f0Xec(n{LYXMvb_)%4u6fv%q*m_zh{m+Ar-R7U3 zO|4cb_`C+`ZBNP{mPu*bI%KZeW~jT)(e;lWr*GJs(E_#UEp$-}IHLkuiDd{Ms!S+2 z*egU#xRT(GTxM4RuXkGyK_e|8G#Mn|VjIpLY5(Kw-XreQ0{{+4B<8$<1mR%hCwjVI z5yol@fsEl-5M8&*)|x$=BbqlLUm8oq*HYvDhe-PeSF$UcCJvOKPb+Wp1)isR^1e6N z_c=&kdDB0$`oxMcbsplzjKbiY0N{g;#L0<08sU!_ZEc<-9jZf}74qIQ^H@8MYQ0j1 zGZi-tJjd?&;zIpBSW*$jw^0?E`NGIuTj-!DU}d?)VppJnxa`~1t`I#AA>(M!zK2Gq zlrLxz4$ShosR+L+!Lx_Iu@X6rEg3^2IebnJ>xq=To~rQK(x8{5e8fcG|zZTb1aO8?`2k2m4zgQoALTBlF69c1Mn4tBvAm~DI! z1A%KZw=?#?s#S+G5?1R2tH}KSOZ^f}KRjPmxi|SEtDY=i3wUWZn*V zyhwRC#UqaqW)XC`(Yo&f#w8Dh58_#(^jm22hFdSw!fPv_bRkXqAjU6`f3gSis(YR( z5`ooza^&S4OzpKl021QdLa}`xB<uV~i8Sr@l1)gJq*Zq_7tY;m?UIP)7{ zFfS|4074T#&Lj;SVG{Jcm5@R{zLNVC(&Wh8Ke z$9Qkvs89$(k{+~LEP5*O)O9(es9!+3c(UlWF0zF&MAB^g(&P(7((i|5%B%R0#*@^b z1>3ETqiB&~YEv0q+z*Njf6-Sje`PapNOmaNTxqmx4JA^cWqs2ox@oPbQic`uxCHM1 zb8SUvH5Qbxv_j-66PPtN#vOY^f${DVW!8<4x(j3jj&ibQ5+dcH_mE2Yy7UA}^3aFW z6s#?LSC$Y2d#V`kp+X%WGJ=AYW=5HdYT5I>pj~xUd_`&q6hZSAZoZbOR2+0;S{ zxLATI!B6Lc6 zdLf2#@1v}>ROUg}AdHgB>Ou>w10Vx%0|-N*`|VS0?YV*1c&VzI(ymGm4R21(gL|_E z#VssfU|<*7u$=0dvg+_4Wf$km#h-LYcN30AS=!k=E;8l&FC?_;=f>(vqN;Xh6VR_j znCVVrbocGu2gb&{eLN14y}i1Ura2-q8LUW5NkZE|^_Ss`{UbVyJ)@Na3)Q^#e=$~# z!eD=mB_OQrya#sp>*<~dY$z%jEH_PwWDD7=HhbYw>DT!R*MezsUD!j1UT&YLvts+a z&=1ex`=jToY#;4a{=TfXEK4;^w4AUOW}+l0knP^?f5?wq8%D2@2i+#%THWB5-FLuA)~@2_m2=2dfrL?t>q)`FI|kBEEhIR+3Cx_5y>g0Gb-ZP{n(_7G;7IKFvNC)+%Uvx#Jkk?6|dT zft-dioOB%LKWtWF<`msTX=!O)>O+2>KkWqNR*qn|p`7Yf$Xtd&$H6q?lGPmpjv~9_ zF!|j;<-DM$8C;)ugXo2Fe`(~8ptWKPA_q^Hf-VoaW1EHBuF!ip<59PbMp;YByp%NE zy_LT2@^4e6*bz_(Zih`vium_KQrUFC?OCoN*C+JOT~4Z4r|=GTVSkI zkN~MUo-|~~M93cXm-_vE4P%W}5GWJG6>X7Q+}@1+!tLr_CEb0b!e`ez)Vu49%Ex&H zyzc=^@Y>b3S&zuQq|U%a7ceI5spP;d zx%9%4u6HgHI!Uk!td>cr+zbBcMAfXSbT0GSbjt~m_JQiG>4&!jIh>w{`ze8f2!WQ{ z3m6S}MwF;O=RFhq8&+KIM8I2tFVG(;h_GgrTvnE0jYT}!kKSf*cK;hnfZI}9B?6ve zqGPc{LcQ00w9+Evn9yy89k)f?<^w<)hTJA>1+iDLG>`x_AXRHsY}GfiI)MM(m(*RK u*xdlknB4-ih8;$OMA#ti=uy^l*x-7~zLr?*7hJzMfV#4dQkeog^#1@9y@|~L literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/notebook-blue.png b/src/cx/fbn/nevernote/icons/notebook-blue.png new file mode 100644 index 0000000000000000000000000000000000000000..9c70ff050e8d3ad44225250a01df556f4fc56a75 GIT binary patch literal 6184 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 W58>hH$PUoP2PrG4%NNTU2mS{|^VeVi literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/notebook-green.png b/src/cx/fbn/nevernote/icons/notebook-green.png new file mode 100644 index 0000000000000000000000000000000000000000..86e118c1abc6060f1dc313a3515a8b33e2ff9bfb GIT binary patch literal 6178 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 literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/notebook-red.png b/src/cx/fbn/nevernote/icons/notebook-red.png new file mode 100644 index 0000000000000000000000000000000000000000..6c9329e75d16b7455a7d6866ceb95a15b9ee5b2b GIT binary patch literal 6207 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 JsVeO8{{W!?@^1hD literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/numberList.gif b/src/cx/fbn/nevernote/icons/numberList.gif new file mode 100644 index 0000000000000000000000000000000000000000..2d33f4fa5a6e11c7d823da041574879fb0432592 GIT binary patch literal 104 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 VW5vqjLytuRs!AG))$*31{~s2ZyNCb) literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/redo.gif b/src/cx/fbn/nevernote/icons/redo.gif new file mode 100644 index 0000000000000000000000000000000000000000..31c74c322e8e3d43f12ee5537f05a174a425446f GIT binary patch literal 105 zcmZ?wbhEHb6lD-)n8*MG4M6bV{$n6Z2gC)5J8(ELuyV+FY*^sf#K<7PvLGPgaI=82 z*PM*-O!NFz@VXc@G8x|gJ7f|+^ n<@sjxrvzx00IF3 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 F{{v-X7@q(D literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/search.png b/src/cx/fbn/nevernote/icons/search.png new file mode 100644 index 0000000000000000000000000000000000000000..84b5c16a8381216ad5ecfda1248bee26c5d9a950 GIT binary patch literal 38265 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

    SYYa=yG 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 literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/search_config.jpg b/src/cx/fbn/nevernote/icons/search_config.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6e74b4f015c6b1d76a03efb7030742ad407804c3 GIT binary patch literal 69061 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 literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/searchclear.png b/src/cx/fbn/nevernote/icons/searchclear.png new file mode 100644 index 0000000000000000000000000000000000000000..a1cd3e006e687ff1aa6ec5be542e7d2f874363c5 GIT binary patch literal 52520 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 literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/show-columns.png b/src/cx/fbn/nevernote/icons/show-columns.png new file mode 100644 index 0000000000000000000000000000000000000000..52e6f8b25416c0ac62edf6c1bc77f69e3bdba0e2 GIT binary patch literal 16651 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 P002!@U6nE=tFZqEvuU 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 F{{h4I=XwAD literal 0 HcmV?d00001 diff --git a/src/cx/fbn/nevernote/icons/splash_logo.png b/src/cx/fbn/nevernote/icons/splash_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6206ea760f480b7d3b6db7b88d969da1bcd466d2 GIT binary patch literal 194775 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

    6ojGJvn>{mLcj=$e?68~C zQX!6T+3zsre=2g`{J0~J_W4Uv(s2IJiwnzUpz2T8KOYGNeIqQ8w%zCAMF}c2seEQA&ncRm~<2nyt}{?>ifI@~`e;LP-dd=0q0y?$ZS=9bpWI zVF6~|n$GGywnjDKZsWXQ@NO$oI2j7c^$))X&R1j5j1{H?OVy7Wz^gS?LeTSeYd=*^ zAG?E{7a;IdD%C;23!YtcH!t*3`D8p&cOd=weKL7sa+rvz0Gp^OUh`wzzqw$-mm3Ga zZl+GRKhpZ7fL9H*TWY^~_Nl0@1n7F6;?JTKbG#k!H>TF0<@dW!p^oz0UsToQt{

    are technically valid, but Evernote + // expects that a