/* * This file is part of NixNote/NeighborNote * Copyright 2009 Randy Baumgarte * Copyright 2013 Yuki Takahashi * * 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.awt.Desktop; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.net.Authenticator; import java.net.PasswordAuthentication; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.Vector; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.h2.tools.ChangeFileEncryption; import com.evernote.edam.error.EDAMErrorCode; import com.evernote.edam.error.EDAMNotFoundException; import com.evernote.edam.error.EDAMSystemException; import com.evernote.edam.error.EDAMUserException; import com.evernote.edam.notestore.NoteFilter; import com.evernote.edam.notestore.NoteVersionId; import com.evernote.edam.type.Data; import com.evernote.edam.type.LinkedNotebook; import com.evernote.edam.type.Note; import com.evernote.edam.type.NoteAttributes; import com.evernote.edam.type.Notebook; import com.evernote.edam.type.Publishing; import com.evernote.edam.type.QueryFormat; import com.evernote.edam.type.Resource; import com.evernote.edam.type.SavedSearch; import com.evernote.edam.type.Tag; import com.evernote.edam.type.User; import com.evernote.thrift.TException; import com.trolltech.qt.QThread; import com.trolltech.qt.core.QByteArray; import com.trolltech.qt.core.QDateTime; import com.trolltech.qt.core.QDir; import com.trolltech.qt.core.QEvent; import com.trolltech.qt.core.QFile; import com.trolltech.qt.core.QFileInfo; import com.trolltech.qt.core.QFileSystemWatcher; import com.trolltech.qt.core.QIODevice; import com.trolltech.qt.core.QIODevice.OpenModeFlag; import com.trolltech.qt.core.QLocale; import com.trolltech.qt.core.QMimeData; import com.trolltech.qt.core.QModelIndex; import com.trolltech.qt.core.QSize; import com.trolltech.qt.core.QTemporaryFile; import com.trolltech.qt.core.QTextCodec; import com.trolltech.qt.core.QTextStream; import com.trolltech.qt.core.QThreadPool; import com.trolltech.qt.core.QTimer; import com.trolltech.qt.core.QTranslator; import com.trolltech.qt.core.QUrl; import com.trolltech.qt.core.Qt; import com.trolltech.qt.core.Qt.BGMode; import com.trolltech.qt.core.Qt.DockWidgetArea; import com.trolltech.qt.core.Qt.ItemDataRole; import com.trolltech.qt.core.Qt.KeyboardModifier; import com.trolltech.qt.core.Qt.MouseButton; import com.trolltech.qt.core.Qt.SortOrder; import com.trolltech.qt.core.Qt.WidgetAttribute; import com.trolltech.qt.gui.QAbstractItemView; import com.trolltech.qt.gui.QAbstractItemView.ScrollHint; import com.trolltech.qt.gui.QAction; import com.trolltech.qt.gui.QApplication; import com.trolltech.qt.gui.QClipboard; import com.trolltech.qt.gui.QCloseEvent; import com.trolltech.qt.gui.QColor; import com.trolltech.qt.gui.QCursor; import com.trolltech.qt.gui.QDesktopServices; import com.trolltech.qt.gui.QDialog; import com.trolltech.qt.gui.QFileDialog; import com.trolltech.qt.gui.QFileDialog.AcceptMode; import com.trolltech.qt.gui.QFileDialog.FileMode; import com.trolltech.qt.gui.QGridLayout; import com.trolltech.qt.gui.QHBoxLayout; import com.trolltech.qt.gui.QIcon; import com.trolltech.qt.gui.QImage; import com.trolltech.qt.gui.QKeySequence; import com.trolltech.qt.gui.QListWidgetItem; import com.trolltech.qt.gui.QMainWindow; import com.trolltech.qt.gui.QMenu; import com.trolltech.qt.gui.QMessageBox; import com.trolltech.qt.gui.QMessageBox.StandardButton; import com.trolltech.qt.gui.QPainter; import com.trolltech.qt.gui.QPalette.ColorRole; import com.trolltech.qt.gui.QPixmap; import com.trolltech.qt.gui.QPrintDialog; import com.trolltech.qt.gui.QPrinter; import com.trolltech.qt.gui.QShortcut; import com.trolltech.qt.gui.QSizePolicy; import com.trolltech.qt.gui.QSpinBox; import com.trolltech.qt.gui.QSplashScreen; import com.trolltech.qt.gui.QSplitter; import com.trolltech.qt.gui.QStatusBar; import com.trolltech.qt.gui.QSystemTrayIcon; import com.trolltech.qt.gui.QTableWidgetItem; import com.trolltech.qt.gui.QTextEdit; import com.trolltech.qt.gui.QToolBar; import com.trolltech.qt.gui.QTreeWidgetItem; import com.trolltech.qt.gui.QWidget; import com.trolltech.qt.network.QNetworkAccessManager; import com.trolltech.qt.network.QNetworkProxy; import com.trolltech.qt.network.QNetworkProxy.ProxyType; import com.trolltech.qt.network.QNetworkReply; import com.trolltech.qt.network.QNetworkRequest; import com.trolltech.qt.webkit.QWebPage.WebAction; import com.trolltech.qt.webkit.QWebSettings; import cx.fbn.nevernote.clipboard.ClipBoardObserver; import cx.fbn.nevernote.config.InitializationException; import cx.fbn.nevernote.config.StartupConfig; import cx.fbn.nevernote.dialog.AccountDialog; import cx.fbn.nevernote.dialog.ConfigDialog; import cx.fbn.nevernote.dialog.DBEncryptDialog; import cx.fbn.nevernote.dialog.DatabaseLoginDialog; import cx.fbn.nevernote.dialog.DatabaseStatus; import cx.fbn.nevernote.dialog.FindDialog; import cx.fbn.nevernote.dialog.IgnoreSync; import cx.fbn.nevernote.dialog.LogFileDialog; import cx.fbn.nevernote.dialog.NotebookArchive; import cx.fbn.nevernote.dialog.NotebookEdit; import cx.fbn.nevernote.dialog.OnlineNoteHistory; import cx.fbn.nevernote.dialog.PublishNotebook; import cx.fbn.nevernote.dialog.SavedSearchEdit; import cx.fbn.nevernote.dialog.SetIcon; import cx.fbn.nevernote.dialog.ShareNotebook; import cx.fbn.nevernote.dialog.SharedNotebookSyncError; import cx.fbn.nevernote.dialog.StackNotebook; import cx.fbn.nevernote.dialog.SynchronizationRequiredWarning; import cx.fbn.nevernote.dialog.TagEdit; import cx.fbn.nevernote.dialog.TagMerge; import cx.fbn.nevernote.dialog.ThumbnailViewer; import cx.fbn.nevernote.dialog.UpgradeAvailableDialog; import cx.fbn.nevernote.dialog.WatchFolder; import cx.fbn.nevernote.evernote.NoteMetadata; import cx.fbn.nevernote.filters.FilterEditorNotebooks; import cx.fbn.nevernote.filters.FilterEditorTags; import cx.fbn.nevernote.gui.AttributeTreeWidget; import cx.fbn.nevernote.gui.BrowserWindow; import cx.fbn.nevernote.gui.DateAttributeFilterTable; import cx.fbn.nevernote.gui.ExternalBrowse; import cx.fbn.nevernote.gui.MainMenuBar; import cx.fbn.nevernote.gui.NotebookTreeWidget; import cx.fbn.nevernote.gui.RensoNoteList; import cx.fbn.nevernote.gui.RensoNoteListDock; import cx.fbn.nevernote.gui.SavedSearchTreeWidget; import cx.fbn.nevernote.gui.SearchEdit; import cx.fbn.nevernote.gui.TabBrowse; import cx.fbn.nevernote.gui.TabBrowserWidget; import cx.fbn.nevernote.gui.TableView; import cx.fbn.nevernote.gui.TagTreeWidget; import cx.fbn.nevernote.gui.Thumbnailer; import cx.fbn.nevernote.gui.TrashTreeWidget; import cx.fbn.nevernote.gui.ZoomPanel; import cx.fbn.nevernote.gui.controls.QuotaProgressBar; import cx.fbn.nevernote.oauth.OAuthTokenizer; import cx.fbn.nevernote.oauth.OAuthWindow; import cx.fbn.nevernote.sql.DatabaseConnection; import cx.fbn.nevernote.sql.WatchFolderRecord; import cx.fbn.nevernote.threads.IndexRunner; import cx.fbn.nevernote.threads.SyncRunner; import cx.fbn.nevernote.threads.ThumbnailRunner; import cx.fbn.nevernote.utilities.AESEncrypter; import cx.fbn.nevernote.utilities.ApplicationLogger; import cx.fbn.nevernote.utilities.FileImporter; import cx.fbn.nevernote.utilities.FileUtils; import cx.fbn.nevernote.utilities.ListManager; import cx.fbn.nevernote.utilities.SyncTimes; import cx.fbn.nevernote.xml.ExportData; import cx.fbn.nevernote.xml.ImportData; import cx.fbn.nevernote.xml.ImportEnex; import cx.fbn.nevernote.xml.NoteFormatter; public class NeverNote extends QMainWindow{ QStatusBar statusBar; // Application status bar DatabaseConnection conn; MainMenuBar menuBar; // Main menu bar FindDialog find; // Text search in note dialog List<String> 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 QNetworkAccessManager versionChecker; // Used when checking for new versions 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 public QToolBar toolBar; // The tool bar under the menu SearchEdit searchField; // search filter bar on the toolbar; QShortcut searchShortcut; // Shortcut to search bar boolean searchPerformed = false; // Search was done? QuotaProgressBar quotaBar; // The current quota usage ApplicationLogger logger; List<String> selectedNotebookGUIDs; // List of notebook GUIDs List<String> selectedTagGUIDs; // List of selected tag GUIDs List<String> selectedNoteGUIDs; // List of selected notes String selectedSavedSearchGUID; // Currently selected saved searches private final HashMap<String, ExternalBrowse> externalWindows; // Notes being edited by an external window; NoteFilter filter; // Note filter String currentNoteGuid; // GUID of the current note Note currentNote; // The currently viewed note HashMap<Integer, Boolean> noteDirty; // Has the note been changed? HashMap<Integer, Boolean> inkNote; // if this is an ink note, it is read only HashMap<Integer, Boolean> readOnly; // Is this note read-only? ListManager listManager; // DB runnable task List<QTemporaryFile> 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; // Thread which talks to evernote ThumbnailRunner thumbnailRunner; // Runner for thumbnail thread QThread thumbnailThread; // Thread that generates pretty pictures QTimer saveTimer; // Timer to save note contents QTimer authTimer; // Refresh authentication QTimer externalFileSaveTimer; // Save files altered externally QTimer thumbnailTimer; // Wakeup & scan for thumbnails QTimer debugTimer; List<String> externalFiles; // External files to save later List<String> importFilesKeep; // Auto-import files to save later List<String> importFilesDelete; // Auto-import files to save later 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 QAction allNotesButton; // Reset & view all notes QTimer synchronizeAnimationTimer; // Timer to change animation button int synchronizeIconAngle; // Used to rotate sync icon 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 ZoomPanel zoomLayout; // Widget to hold search field, zoom, & quota 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<String> importedFiles; // History of imported files (so we don't import twice) OnlineNoteHistory historyWindow; // online history window List<NoteVersionId> 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 int enRelatedNotesThreadDeadCount=0; // number of consecutive dead times for the EvernoteRelatedNotes Thread boolean disableTagThreadCheck=false; boolean disableNotebookThreadCheck=false; boolean disableTrashThreadCheck=false; boolean disableSaveThreadCheck=false; boolean disableSyncThreadCheck=false; boolean disableIndexThreadCheck=false; boolean disableENRelatedNotesThreadCheck=false; HashMap<String, String> noteCache; // Cash of note content HashMap<String, Boolean> readOnlyCache; // List of cashe notes that are read-only HashMap<String, Boolean> inkNoteCache; // List of cache notes that are ink notes HashMap<Integer, ArrayList<String>> historyGuids; // タブごとの以前見たノートのGUID HashMap<Integer, Integer> historyPosition; // Position within the viewed items HashMap<Integer, Boolean> fromHistory; // Is this from the history queue? String trashNoteGuid; // Guid to restore / set into or out of trash to save position List<Thumbnailer> thumbGenerators; // generate preview image ThumbnailViewer thumbnailViewer; // View preview thumbnail; boolean encryptOnShutdown; // should I encrypt when I close? boolean decryptOnShutdown; // should I decrypt on shutdown; String encryptCipher; // What cipher should I use? //Signal0 minimizeToTray; boolean windowMaximized = false; // Keep track of the window state for restores List<String> pdfReadyQueue; // Queue of PDFs that are ready to be rendered. List<QPixmap> syncIcons; // Array of icons used in sync animation private boolean closeAction = false; // Used to say when to close or when to minimize private static Logger log = Logger.getLogger(NeverNote.class); private String saveLastPath; // last path we used private final QTimer messageTimer; // Timer to clear the status message. private QTimer blockTimer; BrowserWindow blockingWindow; private final TabBrowserWidget tabBrowser; // ブラウザウィンドウをタブ化 private final HashMap<Integer, TabBrowse> tabWindows; // タブウィンドウ private final RensoNoteListDock rensoNoteListDock; // 連想ノートリストドックウィジェット ClipBoardObserver cbObserver; String rensoNotePressedItemGuid; String iconPath = new String("classpath:cx/fbn/nevernote/icons/"); //*************************************************************** //*************************************************************** //** Constructor & main entry point //*************************************************************** //*************************************************************** // Application Constructor @SuppressWarnings("static-access") public NeverNote(DatabaseConnection dbConn) { cbObserver = new ClipBoardObserver(); conn = dbConn; if (conn.getConnection() == null) { String msg = new String(tr("Unable to connect to the database.\n\nThe most probable reason is that some other process\n" + "is accessing the database or NeighborNote is already running.\n\n" + "Please end any other process or shutdown the other NeighborNote before starting.\n\nExiting program.")); QMessageBox.critical(null, tr("Database Connection Error") ,msg); System.exit(16); } setObjectName("mainWindow"); // thread().setPriority(Thread.MAX_PRIORITY); logger = new ApplicationLogger("nevernote.log"); logger.log(logger.HIGH, "Starting Application"); decryptOnShutdown = false; encryptOnShutdown = false; conn.checkDatabaseVersion(); // Start building the invalid XML tables Global.invalidElements = conn.getInvalidXMLTable().getInvalidElements(); List<String> elements = conn.getInvalidXMLTable().getInvalidAttributeElements(); for (int i=0; i<elements.size(); i++) { Global.invalidAttributes.put(elements.get(i), conn.getInvalidXMLTable().getInvalidAttributes(elements.get(i))); } logger.log(logger.EXTREME, "Starting GUI build"); QTranslator nevernoteTranslator = new QTranslator(); nevernoteTranslator.load(Global.getFileManager().getTranslateFilePath("neighbornote_" + QLocale.system().name() + ".qm")); QApplication.instance().installTranslator(nevernoteTranslator); Global.originalPalette = QApplication.palette(); QApplication.setStyle(Global.getStyle()); if (Global.useStandardPalette()) QApplication.setPalette(QApplication.style().standardPalette()); setWindowTitle(tr("NeighborNote")); mainLeftRightSplitter = new QSplitter(); mainLeftRightSplitter.setOrientation(Qt.Orientation.Horizontal); setCentralWidget(mainLeftRightSplitter); leftSplitter1 = new QSplitter(); leftSplitter1.setOrientation(Qt.Orientation.Vertical); browserIndexSplitter = new QSplitter(); browserIndexSplitter.setOrientation(Qt.Orientation.Vertical); //* Setup threads & thread timers // int indexRunnerCount = Global.getIndexThreads(); // indexRunnerCount = 1; QThreadPool.globalInstance().setMaxThreadCount(Global.threadCount); // increase max thread count logger.log(logger.EXTREME, "Building list manager"); listManager = new ListManager(conn, logger); logger.log(logger.EXTREME, "Building index runners & timers"); indexRunner = new IndexRunner("indexRunner.log", Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), Global.getBehaviorDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword); indexThread = new QThread(indexRunner, "Index Thread"); indexRunner.indexAttachmentsLocally = Global.indexAttachmentsLocally(); indexRunner.indexImageRecognition = Global.indexImageRecognition(); // indexRunner.indexNoteBody = Global.indexNoteBody(); // indexRunner.indexNoteTitle = Global.indexNoteTitle(); // indexRunner.specialIndexCharacters = Global.getSpecialIndexCharacters(); indexThread.start(); synchronizeAnimationTimer = new QTimer(); synchronizeAnimationTimer.timeout.connect(this, "updateSyncButton()"); indexTimer = new QTimer(); indexTime = 1000*Global.getIndexThreadSleepInterval(); indexTimer.start(indexTime); // Start indexing timer indexTimer.timeout.connect(this, "indexTimer()"); indexDisabled = false; indexRunning = false; logger.log(logger.EXTREME, "Setting sync thread & timers"); syncThreadsReady=1; syncRunner = new SyncRunner("syncRunner.log", Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), Global.getBehaviorDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword); syncTime = new SyncTimes().timeValue(Global.getSyncInterval()); syncTimer = new QTimer(); syncTimer.timeout.connect(this, "syncTimer()"); syncRunner.status.message.connect(this, "setMessage(String)"); syncRunner.syncSignal.finished.connect(this, "syncThreadComplete(Boolean)"); syncRunner.syncSignal.errorDisconnect.connect(this, "remoteErrorDisconnect()"); syncRunner.limitSignal.rateLimitReached.connect(this, "informRateLimit(Integer)"); syncRunning = false; if (syncTime > 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, "Starting thumnail thread"); pdfReadyQueue = new ArrayList<String>(); thumbnailRunner = new ThumbnailRunner("thumbnailRunner.log", Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), Global.getBehaviorDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword); thumbnailThread = new QThread(thumbnailRunner, "Thumbnail Thread"); thumbnailRunner.noteSignal.thumbnailPageReady.connect(this, "thumbnailHTMLReady(String,QByteArray,Integer)"); thumbnailThread.start(); thumbGenerators = new ArrayList<Thumbnailer>(); thumbnailTimer = new QTimer(); thumbnailTimer.timeout.connect(this, "thumbnailTimer()"); thumbnailTimer(); thumbnailTimer.setInterval(500*1000); // Thumbnail every minute thumbnailTimer.start(); // debugTimer = new QTimer(); // debugTimer.timeout.connect(this, "debugDirty()"); // debugTimer.start(1000*60); logger.log(logger.EXTREME, "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, "Setting save note timer"); saveTimer = new QTimer(); saveTimer.timeout.connect(this, "saveNote()"); if (Global.getAutoSaveInterval() > 0) { saveTimer.setInterval(1000*60*Global.getAutoSaveInterval()); saveTimer.start(); } listManager.saveRunner.noteSignals.noteSaveRunnerError.connect(this, "saveRunnerError(String, String)"); logger.log(logger.EXTREME, "Starting external file monitor timer"); externalFileSaveTimer = new QTimer(); externalFileSaveTimer.timeout.connect(this, "externalFileEditedSaver()"); externalFileSaveTimer.setInterval(1000*5); // save every 5 seconds; externalFiles = new ArrayList<String>(); importFilesDelete = new ArrayList<String>(); importFilesKeep = new ArrayList<String>(); externalFileSaveTimer.start(); notebookTree = new NotebookTreeWidget(conn); attributeTree = new AttributeTreeWidget(); tagTree = new TagTreeWidget(conn); savedSearchTree = new SavedSearchTreeWidget(); trashTree = new TrashTreeWidget(); noteTableView = new TableView(logger, listManager, this); quotaBar = new QuotaProgressBar(); // 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()"); zoomLayout = new ZoomPanel(quotaBar, notebookTree, zoomSpinner); QGridLayout leftGrid = new QGridLayout(); leftSplitter1.setContentsMargins(5, 0, 0, 7); leftSplitter1.setLayout(leftGrid); leftGrid.addWidget(zoomLayout,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<String,String>(); readOnlyCache = new HashMap<String, Boolean>(); inkNoteCache = new HashMap<String, Boolean>(); browserWindow = new BrowserWindow(conn, cbObserver); // 下から移動してきた。 historyGuids = new HashMap<Integer, ArrayList<String>>(); historyPosition = new HashMap<Integer, Integer>(); fromHistory = new HashMap<Integer, Boolean>(); // タブブラウザ作成 tabWindows = new HashMap<Integer, TabBrowse>(); tabBrowser = new TabBrowserWidget(this); tabBrowser.setStyleSheet("QTabBar::tab{width:150px;}"); tabBrowser.setMovable(true); tabBrowser.setTabsClosable(true); TabBrowse tab = new TabBrowse(conn, tabBrowser, cbObserver); browserWindow = tab.getBrowserWindow(); int index = tabBrowser.addNewTab(tab, ""); tabWindows.put(index, tab); tabBrowser.currentChanged.connect(this, "tabWindowChanged(int)"); tabBrowser.tabCloseRequested.connect(this, "tabCloseRequested(int)"); noteDirty = new HashMap<Integer, Boolean>(); noteDirty.put(index, false); inkNote = new HashMap<Integer, Boolean>(); readOnly = new HashMap<Integer, Boolean>(); // 履歴記録のハッシュマップを初期化 historyGuids.put(index, new ArrayList<String>()); historyPosition.put(index, 0); fromHistory.put(index, false); mainLeftRightSplitter.addWidget(leftSplitter1); mainLeftRightSplitter.addWidget(browserIndexSplitter); // 連想ノートリストをセットアップ rensoNoteListDock = new RensoNoteListDock(conn, this, syncRunner, iconPath, tr("Renso Note List")); addDockWidget(DockWidgetArea.RightDockWidgetArea, rensoNoteListDock); if (Global.getListView() == Global.View_List_Wide) { browserIndexSplitter.addWidget(noteTableView); browserIndexSplitter.addWidget(tabBrowser); } else { mainLeftRightSplitter.addWidget(noteTableView); mainLeftRightSplitter.addWidget(tabBrowser); } // 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()"); //Setup external browser manager externalWindows = new HashMap<String, ExternalBrowse>(); listManager.loadNotesIndex(); initializeNotebookTree(); initializeTagTree(); initializeSavedSearchTree(); attributeTree.itemClicked.connect(this, "attributeTreeClicked(QTreeWidgetItem, Integer)"); attributeTreeSelected = null; initializeNoteTable(); selectedNoteGUIDs = new ArrayList<String>(); statusBar = new QStatusBar(); setStatusBar(statusBar); menuBar = new MainMenuBar(this); emitLog = new ArrayList<String>(); tagTree.setDeleteAction(menuBar.tagDeleteAction); tagTree.setMergeAction(menuBar.tagMergeAction); tagTree.setEditAction(menuBar.tagEditAction); tagTree.setAddAction(menuBar.tagAddAction); tagTree.setIconAction(menuBar.tagIconAction); tagTree.setVisible(Global.isWindowVisible("tagTree")); leftSplitter1.setVisible(Global.isWindowVisible("leftPanel")); tagTree.noteSignal.tagsAdded.connect(this, "tagsAdded(String, String)"); menuBar.hideTags.setChecked(Global.isWindowVisible("tagTree")); listManager.tagSignal.listChanged.connect(this, "reloadTagTree()"); if (!Global.isWindowVisible("zoom")) { zoomLayout.hideZoom(); menuBar.hideZoom.setChecked(false); } notebookTree.setDeleteAction(menuBar.notebookDeleteAction); notebookTree.setEditAction(menuBar.notebookEditAction); notebookTree.setAddAction(menuBar.notebookAddAction); notebookTree.setIconAction(menuBar.notebookIconAction); notebookTree.setStackAction(menuBar.notebookStackAction); notebookTree.setPublishAction(menuBar.notebookPublishAction); notebookTree.setShareAction(menuBar.notebookShareAction); notebookTree.setVisible(Global.isWindowVisible("notebookTree")); notebookTree.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)"); notebookTree.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)"); notebookTree.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)"); menuBar.hideNotebooks.setChecked(Global.isWindowVisible("notebookTree")); savedSearchTree.setAddAction(menuBar.savedSearchAddAction); savedSearchTree.setEditAction(menuBar.savedSearchEditAction); savedSearchTree.setDeleteAction(menuBar.savedSearchDeleteAction); savedSearchTree.setIconAction(menuBar.savedSearchIconAction); savedSearchTree.itemSelectionChanged.connect(this, "updateSavedSearchSelection()"); savedSearchTree.setVisible(Global.isWindowVisible("savedSearchTree")); menuBar.hideSavedSearches.setChecked(Global.isWindowVisible("savedSearchTree")); // noteTableViewに新しいタブで開くを追加 noteTableView.setOpenNewTabAction(menuBar.noteOpenNewTab); noteTableView.setAddAction(menuBar.noteAdd); // noteTableViewに新しいタブでノート追加を追加 noteTableView.setAddNoteNewTabAction(menuBar.noteAddNewTab); noteTableView.setDeleteAction(menuBar.noteDelete); noteTableView.setRestoreAction(menuBar.noteRestoreAction); noteTableView.setNoteDuplicateAction(menuBar.noteDuplicateAction); noteTableView.setNoteHistoryAction(menuBar.noteOnlineHistoryAction); noteTableView.noteSignal.titleColorChanged.connect(this, "titleColorChanged(Integer)"); noteTableView.noteSignal.notePinned.connect(this, "notePinned()"); noteTableView.setMergeNotesAction(menuBar.noteMergeAction); noteTableView.setCopyAsUrlAction(menuBar.noteCopyAsUrlAction); noteTableView.doubleClicked.connect(this, "listDoubleClick()"); listManager.trashSignal.countChanged.connect(trashTree, "updateCounts(Integer)"); quotaBar.setMouseClickAction(menuBar.accountAction); 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")) { menuBar.showEditorBar.setChecked(false); toggleEditorButtonBar(); } if (!Global.isWindowVisible("leftPanel")) menuBar.hideLeftSide.setChecked(true); if (Global.isWindowVisible("noteInformation")) { menuBar.noteAttributes.setChecked(true); toggleNoteInformation(); } quotaBar.setVisible(Global.isWindowVisible("quota")); // IFIXED quotaBar.isVisible() → Global.isWindowVisible("quota") // なぜかquotaBar.isVisible()が常にfalseを返すようなので修正 if (!Global.isWindowVisible("quota")) menuBar.hideQuota.setChecked(false); if (quotaBar.isHidden() && zoomSpinner.isHidden() && notebookTree.isHidden()) zoomLayout.hide(); setMenuBar(menuBar); setupToolBar(); find = new FindDialog(); find.getOkButton().clicked.connect(this, "doFindText()"); // Setup the tray icon menu bar trayShowAction = new QAction(tr("Show/Hide"), this); trayExitAction = new QAction(tr("Exit"), this); trayAddNoteAction = new QAction(tr("Add Note"), this); trayExitAction.triggered.connect(this, "closeNeverNote()"); 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(tr("NeighborNote")); trayIcon.setContextMenu(trayMenu); trayIcon.activated.connect(this, "trayActivated(com.trolltech.qt.gui.QSystemTrayIcon$ActivationReason)"); currentNoteGuid=""; currentNoteGuid = Global.getLastViewedNoteGuid(); if (currentNoteGuid.equals("")) currentNote = new Note(); /* 上に移動したのでここには不要 * historyGuids = new ArrayList<String>(); * historyPosition = 0; * fromHistory = 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(browserWindow); tagIndexUpdated(true); savedSearchIndexUpdated(); notebookIndexUpdated(); updateQuotaBar(); setupSyncSignalListeners(); setupBrowserSignalListeners(); setupIndexListeners(); tagTree.tagSignal.listChanged.connect(this, "tagIndexUpdated()"); tagTree.showAllTags(true); QIcon appIcon = new QIcon(iconPath+"nevernote.png"); if (QSystemTrayIcon.isSystemTrayAvailable()) { setWindowIcon(appIcon); trayIcon.setIcon(appIcon); if (Global.showTrayIcon() || Global.minimizeOnClose()) trayIcon.show(); else trayIcon.hide(); } scrollToGuid(currentNoteGuid); if (Global.automaticLogin()) { remoteConnect(); if (Global.isConnected) syncTimer(); } setupFolderImports(); loadStyleSheet(); restoreWindowState(true); if (Global.mimicEvernoteInterface) { notebookTree.selectGuid(""); } threadMonitorTimer = new QTimer(); threadMonitorTimer.timeout.connect(this, "threadMonitorCheck()"); threadMonitorTimer.start(1000*10); // Check for threads every 10 seconds; // IFIXED 恐らく不要なのでコメントアウト /* * historyGuids.add(currentNoteGuid); * historyPosition = 1; */ menuBar.blockSignals(true); menuBar.narrowListView.blockSignals(true); menuBar.wideListView.blockSignals(true); if (Global.getListView() == Global.View_List_Narrow) { menuBar.narrowListView.setChecked(true); } else{ menuBar.wideListView.setChecked(true); } menuBar.blockSignals(false); menuBar.narrowListView.blockSignals(false); menuBar.wideListView.blockSignals(false); // IFIXED 上に同じコードがあるのでコメントアウト /* * if (Global.getListView() == Global.View_List_Wide) { * browserIndexSplitter.addWidget(noteTableView); * browserIndexSplitter.addWidget(tabBrowser); * browserIndexSplitter.addWidget(browserWindow); } else { * mainLeftRightSplitter.addWidget(noteTableView); * mainLeftRightSplitter.addWidget(tabBrowser); * mainLeftRightSplitter.addWidget(browserWindow); } */ messageTimer = new QTimer(); messageTimer.timeout.connect(this, "clearMessage()"); messageTimer.setInterval(1000*15); clearMessage(); int sortCol = Global.getSortColumn(); int sortOrder = Global.getSortOrder(); noteTableView.proxyModel.blocked = true; // We sort the table twice to fix a bug. For some reaosn the table won't sort properly if it is in narrow // list view and sorted descending on the date created. By sorting it twice it forces the proper sort. Ugly. if (sortCol == 0 && sortOrder == 1 && Global.getListView() == Global.View_List_Narrow) noteTableView.sortByColumn(sortCol, SortOrder.resolve(0)); noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder)); noteTableView.proxyModel.blocked = false; noteTableView.proxyModel.sortChanged.connect(this, "tableSortOrderChanged(Integer,Integer)"); // Set the startup notebook String defaultNotebook = Global.getStartupNotebook(); if (!defaultNotebook.equals("AllNotebooks") && !defaultNotebook.equals("")) { for (int k=0; k<listManager.getNotebookIndex().size(); k++) { if (listManager.getNotebookIndex().get(k).isDefaultNotebook()) { notebookTree.clearSelection(); notebookTree.selectGuid(listManager.getNotebookIndex().get(k).getGuid()); notebookTree.selectionSignal.emit(); } } } if (Global.checkVersionUpgrade()) { checkForUpdates(); } if (currentNoteGuid == null || currentNoteGuid.equals("")) { menuBar.noteAddNewTab.setEnabled(false); } } public void debugDirty() { List<Note> dirty = conn.getNoteTable().getDirty(); logger.log(logger.LOW, "------ Dirty Notes List Begin ------"); for (int i=0; i<dirty.size(); i++) { logger.log(logger.LOW, "GUID: " +dirty.get(i).getGuid() + " Title:" + dirty.get(i).getTitle()); } logger.log(logger.LOW, "------ Dirty Notes List End ------"); } // Main entry point public static void main(String[] args) { log.setLevel(Level.FATAL); QApplication.initialize(args); QPixmap pixmap = new QPixmap("classpath:cx/fbn/nevernote/icons/splash_logo.png"); QSplashScreen splash = new QSplashScreen(pixmap); boolean showSplash; DatabaseConnection dbConn; try { initializeGlobalSettings(args); showSplash = Global.isWindowVisible("SplashScreen"); if (showSplash) splash.show(); dbConn = setupDatabaseConnection(); // Must be last stage of setup - only safe once DB is open hence we know we are the only instance running Global.getFileManager().purgeResDirectory(true); } catch (InitializationException e) { // Fatal e.printStackTrace(); QMessageBox.critical(null, "Startup error", "Aborting: " + e.getMessage()); return; } // Setup proxy crap String proxyUrl = Global.getProxyValue("url"); String proxyPort = Global.getProxyValue("port"); String proxyUserid = Global.getProxyValue("userid"); String proxyPassword = Global.getProxyValue("password"); boolean proxySet = false; QNetworkProxy proxy = new QNetworkProxy(); proxy.setType(ProxyType.HttpProxy); if (!proxyUrl.trim().equals("")) { System.out.println("Proxy URL found: " +proxyUrl); proxySet = true; proxy.setHostName(proxyUrl); } if (!proxyPort.trim().equals("")) { System.out.println("Proxy Port found: " +proxyPort); proxySet = true; proxy.setPort(Integer.parseInt(proxyPort)); } if (!proxyUserid.trim().equals("")) { System.out.println("Proxy Userid found: " +proxyUserid); proxySet = true; proxy.setUser(proxyUserid); } if (!proxyPassword.trim().equals("")) { System.out.println("Proxy URL found: " +proxyPassword); proxySet = true; proxy.setPassword(proxyPassword); } if (proxySet) { QNetworkProxy.setApplicationProxy(proxy); } NeverNote application = new NeverNote(dbConn); if (Global.syncOnly) { System.out.println("Performing synchronization only."); application.remoteConnect(); if (Global.isConnected) { application.syncRunner.syncNeeded = true; application.syncRunner.addWork("SYNC"); application.syncRunner.addWork("STOP"); while(!application.syncRunner.isIdle()); application.closeNeverNote(); } return; } application.setAttribute(WidgetAttribute.WA_DeleteOnClose, true); if (Global.startMinimized()) application.showMinimized(); else { if (Global.wasWindowMaximized()) application.showMaximized(); else application.show(); } if (showSplash) splash.finish(application); QApplication.exec(); System.out.println("Goodbye."); QApplication.exit(); } /** * Open the internal database, or create if not present * * @throws InitializationException when opening the database fails, e.g. because another process has it locked */ private static DatabaseConnection setupDatabaseConnection() throws InitializationException { ApplicationLogger logger = new ApplicationLogger("nevernote-database.log"); File f = Global.getFileManager().getDbDirFile(Global.databaseName + ".h2.db"); File fr = Global.getFileManager().getDbDirFile(Global.resourceDatabaseName + ".h2.db"); // IFIXED resourceDatabaseNameになっていたので修正 File fi = Global.getFileManager().getDbDirFile(Global.indexDatabaseName + ".h2.db"); File fb = Global.getFileManager().getDbDirFile(Global.behaviorDatabaseName + ".h2.db"); if (!f.exists()) Global.setDatabaseUrl(""); if (!fr.exists()) Global.setResourceDatabaseUrl(""); if (!fi.exists()) Global.setIndexDatabaseUrl(""); if (!fb.exists()) Global.setBehaviorDatabaseUrl(""); 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); } } DatabaseConnection dbConn = new DatabaseConnection(logger,Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), Global.getBehaviorDatabaseUrl(), Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword, 0); return dbConn; } // Encrypt the database upon shutdown private void encryptOnShutdown() { String dbPath= Global.getFileManager().getDbDirPath(""); try { Statement st = conn.getConnection().createStatement(); st.execute("shutdown"); st = conn.getResourceConnection().createStatement(); st.execute("shutdown"); st = conn.getIndexConnection().createStatement(); st.execute("shutdown"); st = conn.getBehaviorConnection().createStatement(); st.execute("shutdown"); if (QMessageBox.question(this, tr("Are you sure"), tr("Are you sure you wish to encrypt the database?"), QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No) == StandardButton.Yes.value()) { ChangeFileEncryption.execute(dbPath, "NeverNote", encryptCipher, null, Global.cipherPassword.toCharArray(), true); ChangeFileEncryption.execute(dbPath, "Resources", encryptCipher, null, Global.cipherPassword.toCharArray(), true); ChangeFileEncryption.execute(dbPath, "Index", encryptCipher, null, Global.cipherPassword.toCharArray(), true); ChangeFileEncryption.execute(dbPath, "Behavior", encryptCipher, null, Global.cipherPassword.toCharArray(), true); Global.setDatabaseUrl(Global.getDatabaseUrl() + ";CIPHER="+encryptCipher); Global.setResourceDatabaseUrl(Global.getResourceDatabaseUrl() + ";CIPHER="+encryptCipher); Global.setIndexDatabaseUrl(Global.getIndexDatabaseUrl() + ";CIPHER="+encryptCipher); Global.setBehaviorDatabaseUrl(Global.getBehaviorDatabaseUrl() + ";CIPHER=" + encryptCipher); QMessageBox.information(this, tr("Encryption Complete"), tr("Encryption is complete")); } } catch (SQLException e) { e.printStackTrace(); } } // Decrypt the database upon shutdown private void decryptOnShutdown() { String dbPath= Global.getFileManager().getDbDirPath(""); String dbName = "NeverNote"; try { Statement st = conn.getConnection().createStatement(); st.execute("shutdown"); if (Global.getDatabaseUrl().toUpperCase().indexOf(";CIPHER=AES") > -1) encryptCipher = "AES"; else encryptCipher = "XTEA"; if (QMessageBox.question(this, tr("Confirmation"), tr("Are you sure", "Are you sure you wish to decrypt the database?"), QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No) == StandardButton.Yes.value()) { ChangeFileEncryption.execute(dbPath, dbName, encryptCipher, Global.cipherPassword.toCharArray(), null, true); Global.setDatabaseUrl(""); Global.setResourceDatabaseUrl(""); Global.setIndexDatabaseUrl(""); QMessageBox.information(this, tr("Decryption Complete"), tr("Decryption is complete")); } } catch (SQLException e) { e.printStackTrace(); } } /** * Encrypt/Decrypt the local database **/ public void doDatabaseEncrypt() { // The database is not currently encrypted if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") == -1) { if (QMessageBox.question(this, tr("Confirmation"), tr("Encrypting the database is used" + "to enhance security and is performed\nupon shutdown, but please be aware that if"+ " you lose the password your\nis lost forever.\n\nIt is highly recommended you " + "perform a backup and/or fully synchronize\n prior to executing this funtction.\n\n" + "Do you wish to proceed?"), QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No)==StandardButton.No.value()) { return; } DBEncryptDialog dialog = new DBEncryptDialog(); dialog.exec(); if (dialog.okPressed()) { Global.cipherPassword = dialog.getPassword(); encryptOnShutdown = true; encryptCipher = dialog.getEncryptionMethod(); } } else { DBEncryptDialog dialog = new DBEncryptDialog(); dialog.setWindowTitle(tr("Database Decryption")); dialog.hideEncryption(); dialog.exec(); if (dialog.okPressed()) { if (!dialog.getPassword().equals(Global.cipherPassword)) { QMessageBox.critical(null, tr("Incorrect Password"), tr("Incorrect Password")); return; } decryptOnShutdown = true; encryptCipher = ""; } } return; } private static void initializeGlobalSettings(String[] args) throws InitializationException { StartupConfig startupConfig = new StartupConfig(); for (String arg : args) { String lower = arg.toLowerCase(); if (lower.startsWith("--name=")) startupConfig.setName(arg.substring(arg.indexOf('=') + 1)); if (lower.startsWith("--home=")) startupConfig.setHomeDirPath(arg.substring(arg.indexOf('=') + 1)); if (lower.startsWith("--disable-viewing")) startupConfig.setDisableViewing(true); if (lower.startsWith("--sync-only=true")) startupConfig.setSyncOnly(true); } Global.setup(startupConfig); } // Exit point @Override public void closeEvent(QCloseEvent event) { if (Global.minimizeOnClose() && !closeAction) { event.ignore(); hide(); return; } logger.log(logger.HIGH, "Entering NeverNote.closeEvent"); waitCursor(true); if (currentNote != null & browserWindow != null) { if (currentNote.getTitle() != null && browserWindow != null && !currentNote.getTitle().equals(browserWindow.getTitle())) conn.getNoteTable().updateNoteTitle(currentNote.getGuid(), browserWindow.getTitle()); } saveNote(); setMessage(tr("Beginning shutdown.")); // Close down external windows Collection<ExternalBrowse> windows = externalWindows.values(); Iterator<ExternalBrowse> iterator = windows.iterator(); while (iterator.hasNext()) { ExternalBrowse browser = iterator.next(); browser.windowClosing.disconnect(); browser.close(); } // タブブラウザに対してクローズ処理を行う Collection<TabBrowse> win = tabWindows.values(); Iterator<TabBrowse> it = win.iterator(); tabBrowser.currentChanged.disconnect(); tabBrowser.tabCloseRequested.disconnect(); while (it.hasNext()) { TabBrowse browser = it.next(); browser.close(); } externalFileEditedSaver(); if (Global.isConnected && Global.synchronizeOnClose()) { setMessage(tr("Performing synchronization before closing.")); syncRunner.syncNeeded = true; syncRunner.addWork("SYNC"); } else { syncRunner.keepRunning = false; } syncRunner.addWork("STOP"); setMessage("Closing Program."); threadMonitorTimer.stop(); thumbnailRunner.addWork("STOP"); indexRunner.addWork("STOP"); saveNote(); listManager.stop(); saveWindowState(); // 連想ノートリストのEvernote関連ノート取得スレッドを終了 rensoNoteListDock.getRensoNoteList().stopThread(); 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(); if (isVisible()) Global.saveWindowVisible("toolBar", toolBar.isVisible()); saveNoteColumnPositions(); 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"); if (indexRunner.thread().isAlive()) indexRunner.thread().join(50); if (!indexRunner.thread().isAlive()) logger.log(logger.MEDIUM, "Index thread has stopped"); else { logger.log(logger.MEDIUM, "Index thread still running - interrupting"); indexRunner.thread().interrupt(); } } catch (InterruptedException e1) { e1.printStackTrace(); } if (!syncRunner.thread().isAlive()) { logger.log(logger.MEDIUM, "Waiting for syncThread to stop"); if (syncRunner.thread().isAlive()) { System.out.println(tr("Synchronizing. Please be patient.")); for(;syncRunner.thread().isAlive();) { try { wait(10); } catch (InterruptedException e) { e.printStackTrace(); } } } logger.log(logger.MEDIUM, "Sync thread has stopped"); } if (encryptOnShutdown) { encryptOnShutdown(); } if (decryptOnShutdown) { decryptOnShutdown(); } try { Global.getFileManager().purgeResDirectory(false); } catch (InitializationException e) { System.out.println(tr("Empty res directory purge failed")); e.printStackTrace(); } logger.log(logger.HIGH, "Leaving NeverNote.closeEvent"); } private void closeNeverNote() { closeAction = true; close(); } public void setMessage(String s) { if (logger != null) logger.log(logger.HIGH, "Entering NeverNote.setMessage"); else System.out.println("*** ERROR *** " +s); if (statusBar != null) { statusBar.show(); if (logger != null) logger.log(logger.HIGH, "Message: " +s); statusBar.showMessage(s); if (emitLog != null) emitLog.add(s); if (messageTimer != null) { messageTimer.stop(); messageTimer.setSingleShot(true); messageTimer.start(); } } if (logger != null) logger.log(logger.HIGH, "Leaving NeverNote.setMessage"); } private void clearMessage() { statusBar.clearMessage(); statusBar.hide(); } private void waitCursor(boolean wait) { if (wait) { if (QApplication.overrideCursor() == null) QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.WaitCursor)); } else { if (QApplication.overrideCursor() != null) QApplication.restoreOverrideCursor(); else QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.ArrowCursor)); } listManager.refreshCounters(); } private void setupIndexListeners() { // indexRunner.noteSignal.noteIndexed.connect(this, "indexThreadComplete(String)"); // indexRunner.resourceSignal.resourceIndexed.connect(this, "indexThreadComplete(String)"); indexRunner.signal.indexStarted.connect(this, "indexStarted()"); indexRunner.signal.indexFinished.connect(this, "indexComplete()"); } 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.saveUploadAmount.connect(this,"saveUploadAmount(long)"); 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.noteSignal.noteDownloaded.connect(listManager, "noteDownloaded(Note)"); syncRunner.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)"); syncRunner.syncSignal.refreshLists.connect(this, "refreshLists()"); } private void setupBrowserSignalListeners() { setupBrowserWindowListeners(browserWindow, true); } private void setupBrowserWindowListeners(BrowserWindow browser, boolean master) { browser.fileWatcher.fileChanged.connect(this, "externalFileEdited(String)"); browser.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)"); browser.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)"); if (master) browser.noteSignal.noteChanged.connect(this, "setNoteDirty()"); browser.noteSignal.titleChanged.connect(listManager, "updateNoteTitle(String, String)"); browser.noteSignal.titleChanged.connect(this, "updateNoteTitle(String, String)"); browser.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)"); browser.noteSignal.createdDateChanged.connect(listManager, "updateNoteCreatedDate(String, QDateTime)"); browser.noteSignal.alteredDateChanged.connect(listManager, "updateNoteAlteredDate(String, QDateTime)"); browser.noteSignal.subjectDateChanged.connect(listManager, "updateNoteSubjectDate(String, QDateTime)"); browser.noteSignal.authorChanged.connect(listManager, "updateNoteAuthor(String, String)"); browser.noteSignal.geoChanged.connect(listManager, "updateNoteGeoTag(String, Double,Double,Double)"); browser.noteSignal.geoChanged.connect(this, "setNoteDirty()"); browser.noteSignal.sourceUrlChanged.connect(listManager, "updateNoteSourceUrl(String, String)"); browser.blockApplication.connect(this, "blockApplication(BrowserWindow)"); browser.unblockApplication.connect(this, "unblockApplication()"); if (master) browser.focusLost.connect(this, "saveNote()"); browser.resourceSignal.contentChanged.connect(this, "externalFileEdited(String)"); browser.evernoteLinkClicked.connect(this, "evernoteLinkClick(String, String)"); } //************************************************** //* Setup shortcuts //************************************************** private void setupShortcut(QShortcut action, String text) { if (!Global.shortcutKeys.containsAction(text)) return; action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text))); } //*************************************************************** //*************************************************************** //* Settings and look & feel //*************************************************************** //*************************************************************** @SuppressWarnings("unused") private void settings() { logger.log(logger.HIGH, "Entering NeverNote.settings"); saveNoteColumnPositions(); saveNoteIndexWidth(); showColumns(); ConfigDialog settings = new ConfigDialog(this, conn); String dateFormat = Global.getDateFormat(); String timeFormat = Global.getTimeFormat(); indexTime = 1000*Global.getIndexThreadSleepInterval(); indexTimer.start(indexTime); // reset indexing timer settings.exec(); indexRunner.indexAttachmentsLocally = Global.indexAttachmentsLocally(); // indexRunner.indexNoteBody = Global.indexNoteBody(); // indexRunner.indexNoteTitle = Global.indexNoteTitle(); // indexRunner.specialIndexCharacters = Global.getSpecialIndexCharacters(); indexRunner.indexImageRecognition = Global.indexImageRecognition(); if (Global.showTrayIcon() || Global.minimizeOnClose()) trayIcon.show(); else trayIcon.hide(); showColumns(); if (menuBar.showEditorBar.isChecked()){ for(int i = 0; i < tabBrowser.count(); i++){ BrowserWindow browser = ((TabBrowse) tabBrowser.widget(i)).getBrowserWindow(); showEditorButtons(browser); } } // Reset the save timer if (Global.getAutoSaveInterval() > 0) saveTimer.setInterval(1000*60*Global.getAutoSaveInterval()); else saveTimer.stop(); // Set special reloads if (settings.getDebugPage().reloadSharedNotebooksClicked()) { conn.executeSql("Delete from LinkedNotebook"); conn.executeSql("delete from SharedNotebook"); conn.executeSql("Delete from Notebook where linked=true"); conn.executeSql("Insert into Sync (key, value) values ('FullLinkedNotebookSync', 'true')"); conn.executeSql("Insert into Sync (key, value) values ('FullSharedNotebookSync', 'true')"); } // Reload user data noteCache.clear(); readOnlyCache.clear(); inkNoteCache.clear(); noteIndexUpdated(true); logger.log(logger.HIGH, "Leaving NeverNote.settings"); } // Restore things to the way they were private void restoreWindowState(boolean mainWindow) { // We need to name things or this doesn't work. setObjectName("NeverNote"); restoreState(Global.restoreState(objectName())); mainLeftRightSplitter.setObjectName("mainLeftRightSplitter"); browserIndexSplitter.setObjectName("browserIndexSplitter"); leftSplitter1.setObjectName("leftSplitter1"); rensoNoteListDock.setObjectName("rensoNoteListDock"); // Restore the actual positions. if (mainWindow) restoreGeometry(Global.restoreGeometry(objectName())); mainLeftRightSplitter.restoreState(Global.restoreState(mainLeftRightSplitter.objectName())); browserIndexSplitter.restoreState(Global.restoreState(browserIndexSplitter.objectName())); leftSplitter1.restoreState(Global.restoreState(leftSplitter1.objectName())); rensoNoteListDock.restoreGeometry(Global.restoreGeometry(rensoNoteListDock.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()); Global.saveState(objectName(), saveState()); Global.saveGeometry(rensoNoteListDock.objectName(), rensoNoteListDock.saveGeometry()); } // Load the style sheet private void loadStyleSheet() { String styleSheetName = "default.qss"; if (Global.getStyle().equalsIgnoreCase("cleanlooks")) styleSheetName = "default-cleanlooks.qss"; String fileName = Global.getFileManager().getQssDirPathUser("default.qss"); QFile file = new QFile(fileName); // If a user default.qss doesn't exist, we use the one shipped with NeverNote if (!file.exists()) { fileName = Global.getFileManager().getQssDirPath(styleSheetName); file = new QFile(fileName); } file.open(OpenModeFlag.ReadOnly); String styleSheet = file.readAll().toString(); file.close(); setStyleSheet(styleSheet); } // Save column positions for the next time private void saveNoteColumnPositions() { 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); position = noteTableView.header.visualIndex(Global.noteTableGuidPosition); Global.setColumnPosition("noteTableGuidPosition", position); position = noteTableView.header.visualIndex(Global.noteTableThumbnailPosition); Global.setColumnPosition("noteTableThumbnailPosition", position); position = noteTableView.header.visualIndex(Global.noteTablePinnedPosition); Global.setColumnPosition("noteTablePinnedPosition", position); } // 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); width = noteTableView.getColumnWidth(Global.noteTableThumbnailPosition); Global.setColumnWidth("noteTableThumbnailPosition", width); width = noteTableView.getColumnWidth(Global.noteTableGuidPosition); Global.setColumnWidth("noteTableGuidPosition", width); width = noteTableView.getColumnWidth(Global.noteTablePinnedPosition); Global.setColumnWidth("noteTablePinnedPosition", width); } @SuppressWarnings("unused") private void toggleSearchWindow() { logger.log(logger.HIGH, "Entering NeverNote.toggleSearchWindow"); toggleSearchField(); menuBar.hideSearch.setChecked(searchField.isVisible()); Global.saveWindowVisible("searchField", searchField.isVisible()); logger.log(logger.HIGH, "Leaving NeverNote.toggleSearchWindow"); } private void toggleSearchField() { if (searchField.isVisible()) searchField.hide(); else searchField.show(); } @SuppressWarnings("unused") private void toggleQuotaWindow() { logger.log(logger.HIGH, "Entering NeverNote.toggleQuotaWindow"); zoomLayout.toggleQuotaBar(); menuBar.hideQuota.setChecked(quotaBar.isVisible()); Global.saveWindowVisible("quota", quotaBar.isVisible()); logger.log(logger.HIGH, "Leaving NeverNote.toggleQuotaWindow"); } @SuppressWarnings("unused") private void toggleZoomWindow() { logger.log(logger.HIGH, "Entering NeverNote.toggleZoomWindow"); zoomLayout.toggleZoom(); menuBar.hideZoom.setChecked(zoomSpinner.isVisible()); Global.saveWindowVisible("zoom", zoomSpinner.isVisible()); logger.log(logger.HIGH, "Leaving NeverNote.toggleZoomWindow"); } //*************************************************************** //*************************************************************** //** 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.itemClicked.connect(this, "notebookTreeSelection()"); notebookTree.selectionSignal.connect(this, "notebookTreeSelection()"); listManager.notebookSignal.refreshNotebookTreeCounts.connect(notebookTree, "updateCounts(List, List)"); logger.log(logger.HIGH, "Leaving NeverNote.initializeNotebookTree"); } // Listener when a notebook is selected private void notebookTreeSelection() { logger.log(logger.HIGH, "Entering NeverNote.notebookTreeSelection"); noteTableView.proxyModel.blocked = true; clearTrashFilter(); clearAttributeFilter(); clearSavedSearchFilter(); if (Global.mimicEvernoteInterface) { clearTagFilter(); searchField.clear(); } menuBar.noteRestoreAction.setVisible(false); menuBar.notebookEditAction.setEnabled(true); menuBar.notebookDeleteAction.setEnabled(true); menuBar.notebookPublishAction.setEnabled(true); menuBar.notebookShareAction.setEnabled(true); menuBar.notebookIconAction.setEnabled(true); menuBar.notebookStackAction.setEnabled(true); // ゴミ箱から元の画面に戻す。連想ノートリストをONに。 if (!rensoNoteListDock.isEnabled()) { rensoNoteListDock.setEnabled(true); } List<QTreeWidgetItem> selections = notebookTree.selectedItems(); selectedNotebookGUIDs.clear(); searchField.setTargetNotebook(""); searchField.setTargetStack(""); String guid = ""; String stackName = ""; if (selections.size() > 0) { guid = (selections.get(0).text(2)); stackName = selections.get(0).text(0); } if (!Global.mimicEvernoteInterface) { // If no notebooks are selected, we make it look like the "all notebooks" one was selected if (selections.size()==0) { selectedNotebookGUIDs.clear(); for (int i=0; i < listManager.getNotebookIndex().size(); i++) { selectedNotebookGUIDs.add(listManager.getNotebookIndex().get(i).getGuid()); } menuBar.notebookEditAction.setEnabled(false); menuBar.notebookDeleteAction.setEnabled(false); menuBar.notebookStackAction.setEnabled(false); menuBar.notebookIconAction.setEnabled(false); } } if (!guid.equals("") && !guid.equals("STACK")) { selectedNotebookGUIDs.add(guid); searchField.setTargetNotebook(guid); menuBar.notebookIconAction.setEnabled(true); } else { // スタック選択 searchField.setTargetStack(stackName); menuBar.notebookIconAction.setEnabled(true); for (int j=0; j<listManager.getNotebookIndex().size(); j++) { Notebook book = listManager.getNotebookIndex().get(j); if (book.getStack() != null && book.getStack().equalsIgnoreCase(stackName)) { selectedNotebookGUIDs.add(book.getGuid()); } } } listManager.setSelectedNotebooks(selectedNotebookGUIDs); listManager.loadNotesIndex(); noteIndexUpdated(false); refreshEvernoteNote(true); listManager.refreshCounters = true; listManager.refreshCounters(); if (selectedNotebookGUIDs.size() == 1) { int col = conn.getNotebookTable().getSortColumn(selectedNotebookGUIDs.get(0)); int order = conn.getNotebookTable().getSortOrder(selectedNotebookGUIDs.get(0)); if (col != -1) { noteTableView.proxyModel.blocked = true; if (order == 1) noteTableView.sortByColumn(col, Qt.SortOrder.DescendingOrder); else noteTableView.sortByColumn(col, Qt.SortOrder.AscendingOrder); } } noteTableView.proxyModel.blocked = 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(); searchField.setTargetNotebook(""); searchField.setTargetStack(""); listManager.setSelectedNotebooks(selectedNotebookGUIDs); notebookTree.blockSignals(false); } // Triggered when the notebook DB has been updated private void notebookIndexUpdated() { logger.log(logger.HIGH, "Entering NeverNote.notebookIndexUpdated"); // Get the possible icons HashMap<String, QIcon> icons = conn.getNotebookTable().getAllIcons(); notebookTree.setIcons(icons); if (selectedNotebookGUIDs == null) selectedNotebookGUIDs = new ArrayList<String>(); List<Notebook> books = conn.getNotebookTable().getAll(); for (int i=books.size()-1; i>=0; i--) { for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) { if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(books.get(i).getGuid())) { books.remove(i); j=listManager.getArchiveNotebookIndex().size(); } } } listManager.countNotebookResults(listManager.getNoteIndex()); notebookTree.blockSignals(true); notebookTree.load(books, listManager.getLocalNotebooks()); for (int i=selectedNotebookGUIDs.size()-1; i>=0; i--) { boolean found = notebookTree.selectGuid(selectedNotebookGUIDs.get(i)); if (!found) { selectedNotebookGUIDs.remove(i); searchField.setTargetNotebook(""); searchField.setTargetStack(""); } } listManager.refreshCounters = true; listManager.refreshCounters(); notebookTree.blockSignals(false); logger.log(logger.HIGH, "Leaving NeverNote.notebookIndexUpdated"); } // Show/Hide note information @SuppressWarnings("unused") private void toggleNotebookWindow() { logger.log(logger.HIGH, "Entering NeverNote.toggleNotebookWindow"); zoomLayout.toggleNotebook(); 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 stackNotebook() { logger.log(logger.HIGH, "Entering NeverNote.stackNotebook"); StackNotebook edit = new StackNotebook(); List<QTreeWidgetItem> selections = notebookTree.selectedItems(); QTreeWidgetItem currentSelection; for (int i=0; i<selections.size(); i++) { currentSelection = selections.get(0); String guid = currentSelection.text(2); if (guid.equalsIgnoreCase("")) { QMessageBox.critical(this, tr("Unable To Stack") ,tr("You can't stack the \"All Notebooks\" item.")); return; } if (guid.equalsIgnoreCase("STACK")) { QMessageBox.critical(this, tr("Unable To Stack") ,tr("You can't stack a stack.")); return; } } edit.setStackNames(conn.getNotebookTable().getAllStackNames()); edit.exec(); if (!edit.okPressed()) return; String stack = edit.getStackName(); for (int i=0; i<selections.size(); i++) { currentSelection = selections.get(i); String guid = currentSelection.text(2); listManager.updateNotebookStack(guid, stack); } notebookIndexUpdated(); logger.log(logger.HIGH, "Leaving NeverNote.stackNotebook"); } // Edit an existing notebook @SuppressWarnings("unused") private void editNotebook() { logger.log(logger.HIGH, "Entering NeverNote.editNotebook"); NotebookEdit edit = new NotebookEdit(); List<QTreeWidgetItem> selections = notebookTree.selectedItems(); QTreeWidgetItem currentSelection; currentSelection = selections.get(0); edit.setNotebook(currentSelection.text(0)); String guid = currentSelection.text(2); if (!guid.equalsIgnoreCase("STACK")) { edit.setTitle(tr("Edit Notebook")); edit.setNotebooks(listManager.getNotebookIndex()); edit.setLocalCheckboxEnabled(false); for (int i=0; i<listManager.getNotebookIndex().size(); i++) { if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) { edit.setDefaultNotebook(listManager.getNotebookIndex().get(i).isDefaultNotebook()); i=listManager.getNotebookIndex().size(); } } } else { edit.setTitle(tr("Edit Stack")); edit.setStacks(conn.getNotebookTable().getAllStackNames()); edit.hideLocalCheckbox(); edit.hideDefaultCheckbox(); } edit.exec(); if (!edit.okPressed()) return; if (guid.equalsIgnoreCase("STACK")) { conn.getNotebookTable().renameStacks(currentSelection.text(0), edit.getNotebook()); for (int j=0; j<listManager.getNotebookIndex().size(); j++) { if (listManager.getNotebookIndex().get(j).getStack() != null && listManager.getNotebookIndex().get(j).getStack().equalsIgnoreCase(currentSelection.text(0))) listManager.getNotebookIndex().get(j).setStack(edit.getNotebook()); } conn.getNotebookTable().renameStacks(currentSelection.text(0), edit.getNotebook()); currentSelection.setText(0, edit.getNotebook()); return; } updateListNotebookName(currentSelection.text(0), edit.getNotebook()); currentSelection.setText(0, edit.getNotebook()); for (int i=0; i<listManager.getNotebookIndex().size(); i++) { if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) { listManager.getNotebookIndex().get(i).setName(edit.getNotebook()); if (!listManager.getNotebookIndex().get(i).isDefaultNotebook() && edit.isDefaultNotebook()) { for (int j=0; j<listManager.getNotebookIndex().size(); j++) listManager.getNotebookIndex().get(j).setDefaultNotebook(false); listManager.getNotebookIndex().get(i).setDefaultNotebook(true); conn.getNotebookTable().setDefaultNotebook(listManager.getNotebookIndex().get(i).getGuid()); } conn.getNotebookTable().updateNotebook(listManager.getNotebookIndex().get(i), true); if (conn.getNotebookTable().isLinked(listManager.getNotebookIndex().get(i).getGuid())) { LinkedNotebook linkedNotebook = conn.getLinkedNotebookTable().getByNotebookGuid(listManager.getNotebookIndex().get(i).getGuid()); linkedNotebook.setShareName(edit.getNotebook()); conn.getLinkedNotebookTable().updateNotebook(linkedNotebook, true); } i=listManager.getNotebookIndex().size(); } } // Build a list of non-closed notebooks List<Notebook> nbooks = new ArrayList<Notebook>(); for (int i=0; i<listManager.getNotebookIndex().size(); i++) { boolean found=false; for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) { if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid())) found = true; } if (!found) nbooks.add(listManager.getNotebookIndex().get(i)); } FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger); List<Notebook> filteredBooks = notebookFilter.getValidNotebooks(currentNote, listManager.getNotebookIndex()); browserWindow.setNotebookList(filteredBooks); Iterator<String> set = externalWindows.keySet().iterator(); while(set.hasNext()) externalWindows.get(set.next()).getBrowserWindow().setNotebookList(filteredBooks); Iterator<Integer>it = tabWindows.keySet().iterator(); while (it.hasNext()) { tabWindows.get(it.next()).getBrowserWindow() .setNotebookList(filteredBooks); } logger.log(logger.HIGH, "Leaving NeverNote.editNotebook"); } // Publish a notebook @SuppressWarnings("unused") private void publishNotebook() { List<QTreeWidgetItem> selections = notebookTree.selectedItems(); QTreeWidgetItem currentSelection; currentSelection = selections.get(0); String guid = currentSelection.text(2); if (guid.equalsIgnoreCase("STACK") || guid.equalsIgnoreCase("")) return; Notebook n = null; int position = 0; for (int i=0; i<listManager.getNotebookIndex().size(); i++) { if (guid.equals(listManager.getNotebookIndex().get(i).getGuid())) { n = listManager.getNotebookIndex().get(i); position = i; i = listManager.getNotebookIndex().size(); } } if (n == null) return; PublishNotebook publish = new PublishNotebook(Global.username, Global.getServer(), n); publish.exec(); if (!publish.okClicked()) return; Publishing p = publish.getPublishing(); boolean isPublished = !publish.isStopPressed(); conn.getNotebookTable().setPublishing(n.getGuid(), isPublished, p); n.setPublished(isPublished); n.setPublishing(p); listManager.getNotebookIndex().set(position, n); notebookIndexUpdated(); } // Publish a notebook @SuppressWarnings("unused") private void shareNotebook() { List<QTreeWidgetItem> selections = notebookTree.selectedItems(); QTreeWidgetItem currentSelection; currentSelection = selections.get(0); String guid = currentSelection.text(2); if (guid.equalsIgnoreCase("STACK") || guid.equalsIgnoreCase("")) return; Notebook n = null;; for (int i=0; i<listManager.getNotebookIndex().size(); i++) { if (guid.equals(listManager.getNotebookIndex().get(i).getGuid())) { n = listManager.getNotebookIndex().get(i); i = listManager.getNotebookIndex().size(); } } String authToken = null; if (syncRunner.isConnected) authToken = syncRunner.authToken; ShareNotebook share = new ShareNotebook(n.getName(), conn, n, syncRunner); share.exec(); } // Delete an existing notebook @SuppressWarnings("unused") private void deleteNotebook() { logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook"); boolean stacksFound = false; boolean notebooksFound = false; boolean assigned = false; // Check if any notes have this notebook List<QTreeWidgetItem> selections = notebookTree.selectedItems(); for (int i=0; i<selections.size(); i++) { QTreeWidgetItem currentSelection; currentSelection = selections.get(i); String guid = currentSelection.text(2); if (!guid.equalsIgnoreCase("STACK")) { notebooksFound = true; for (int j=0; j<listManager.getNoteIndex().size(); j++) { String noteGuid = listManager.getNoteIndex().get(j).getNotebookGuid(); if (noteGuid.equals(guid)) { assigned = true; j=listManager.getNoteIndex().size(); i=selections.size(); } } } else { stacksFound = true; } } if (assigned) { QMessageBox.information(this, tr("Unable to Delete"), tr("Some of the selected notebook(s) contain notes.\n"+ "Please delete the notes or move them to another notebook before deleting any notebooks.")); return; } if (conn.getNotebookTable().getAll().size() == 1) { QMessageBox.information(this, tr("Unable to Delete"), tr("You must have at least one notebook.")); return; } // If all notebooks are clear, verify the delete String msg1 = new String(tr("Delete selected notebooks?")); String msg2 = new String(tr("Remove selected stacks (notebooks will not be deleted)?")); String msg3 = new String(tr("Delete selected notebooks & remove stacks? Notebooks under the stacks are" + " not deleted unless selected?")); String msg = ""; if (stacksFound && notebooksFound) msg = msg3; if (!stacksFound && notebooksFound) msg = msg1; if (stacksFound && !notebooksFound) msg = msg2; if (QMessageBox.question(this, tr("Confirmation"), msg, QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No)==StandardButton.No.value()) { return; } // If confirmed, delete the notebook for (int i=selections.size()-1; i>=0; i--) { QTreeWidgetItem currentSelection; currentSelection = selections.get(i); String guid = currentSelection.text(2); if (currentSelection.text(2).equalsIgnoreCase("STACK")) { conn.getNotebookTable().renameStacks(currentSelection.text(0), ""); listManager.renameStack(currentSelection.text(0), ""); } else { conn.getNotebookTable().expungeNotebook(guid, true); listManager.deleteNotebook(guid); } } notebookIndexUpdated(); // notebookTreeSelection(); // notebookTree.load(listManager.getNotebookIndex(), listManager.getLocalNotebooks()); // listManager.countNotebookResults(listManager.getNoteIndex()); logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook"); } // A note's notebook has been updated @SuppressWarnings("unused") private void updateNoteNotebook(String guid, String notebookGuid) { // 同じノートブックに入れられたノート間の履歴を登録 conn.getHistoryTable().addSameNotebookHistory(guid, 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<listManager.getNotebookIndex().size(); i++) { if (listManager.getNotebookIndex().get(i).getGuid().equals(notebookGuid)) { notebookName = listManager.getNotebookIndex().get(i).getName(); break; } } // If we found the name, update the browser window if (notebookName != null) { updateListNoteNotebook(guid, notebookName); if (guid.equals(currentNoteGuid)) { int pos = browserWindow.notebookBox.findText(notebookName); if (pos >=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<listManager.getNotebookIndex().size(); j++) { if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) { Notebook n = listManager.getNotebookIndex().get(j); conn.getNotebookTable().setArchived(n.getGuid(),true); listManager.getArchiveNotebookIndex().add(n); j=listManager.getNotebookIndex().size(); } } } for (int i=na.getOpenBookList().count()-1; i>=0; i--) { String text = na.getOpenBookList().takeItem(i).text(); for (int j=0; j<listManager.getNotebookIndex().size(); j++) { if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) { Notebook n = listManager.getNotebookIndex().get(j); conn.getNotebookTable().setArchived(n.getGuid(),false); j=listManager.getNotebookIndex().size(); } } } notebookTreeSelection(); listManager.loadNotesIndex(); notebookIndexUpdated(); noteIndexUpdated(false); reloadTagTree(true); // noteIndexUpdated(false); // Build a list of non-closed notebooks List<Notebook> nbooks = new ArrayList<Notebook>(); for (int i=0; i<listManager.getNotebookIndex().size(); i++) { boolean found=false; for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) { if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid())) found = true; } if (!found) nbooks.add(listManager.getNotebookIndex().get(i)); } FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger); List<Notebook> filteredBooks = notebookFilter.getValidNotebooks(currentNote, listManager.getNotebookIndex()); browserWindow.setNotebookList(filteredBooks); // Update any external windows Iterator<String> set = externalWindows.keySet().iterator(); while(set.hasNext()) externalWindows.get(set.next()).getBrowserWindow().setNotebookList(filteredBooks); // 全てのタブウィンドウを更新 Iterator<Integer> it = tabWindows.keySet().iterator(); while (it.hasNext()) { tabWindows.get(it.next()).getBrowserWindow() .setNotebookList(filteredBooks); } waitCursor(false); } // Change the notebook's icon @SuppressWarnings("unused") private void setNotebookIcon() { boolean stackSelected = false; boolean allNotebookSelected = false; QTreeWidgetItem currentSelection; List<QTreeWidgetItem> selections = notebookTree.selectedItems(); if (selections.size() == 0) return; currentSelection = selections.get(0); String guid = currentSelection.text(2); if (guid.equalsIgnoreCase("")) allNotebookSelected = true; if (guid.equalsIgnoreCase("STACK")) stackSelected = true; QIcon currentIcon = currentSelection.icon(0); QIcon icon; SetIcon dialog; if (!stackSelected && !allNotebookSelected) { icon = conn.getNotebookTable().getIcon(guid); if (icon == null) { dialog = new SetIcon(currentIcon, saveLastPath); dialog.setUseDefaultIcon(true); } else { dialog = new SetIcon(icon, saveLastPath); dialog.setUseDefaultIcon(false); } } else { if (stackSelected) { icon = conn.getSystemIconTable().getIcon(currentSelection.text(0), "STACK"); } else { icon = conn.getSystemIconTable().getIcon(currentSelection.text(0), "ALLNOTEBOOK"); } if (icon == null) { dialog = new SetIcon(currentIcon, saveLastPath); dialog.setUseDefaultIcon(true); } else { dialog = new SetIcon(icon, saveLastPath); dialog.setUseDefaultIcon(false); } } dialog.exec(); if (dialog.okPressed()) { saveLastPath = dialog.getPath(); QIcon newIcon = dialog.getIcon(); if (stackSelected) { conn.getSystemIconTable().setIcon(currentSelection.text(0), "STACK", newIcon, dialog.getFileType()); if (newIcon == null) { newIcon = new QIcon(iconPath+"books2.png"); } currentSelection.setIcon(0,newIcon); return; } if (allNotebookSelected) { conn.getSystemIconTable().setIcon(currentSelection.text(0), "ALLNOTEBOOK", newIcon, dialog.getFileType()); if (newIcon == null) { newIcon = new QIcon(iconPath+"notebook-green.png"); } currentSelection.setIcon(0,newIcon); return; } conn.getNotebookTable().setIcon(guid, newIcon, dialog.getFileType()); if (newIcon == null) { boolean isPublished = false;; boolean found = false; for (int i=0; i<listManager.getNotebookIndex().size() && !found; i++) { if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) { isPublished = listManager.getNotebookIndex().get(i).isPublished(); found = true; } } newIcon = notebookTree.findDefaultIcon(guid, currentSelection.text(1), listManager.getLocalNotebooks(), isPublished); } currentSelection.setIcon(0, newIcon); } } //*************************************************************** //*************************************************************** //** These functions deal with Tag menu items //*************************************************************** //*************************************************************** // Add a new notebook @SuppressWarnings("unused") private void addTag() { logger.log(logger.HIGH, "Inside NeverNote.addTag"); TagEdit edit = new TagEdit(); edit.setTagList(listManager.getTagIndex()); List<QTreeWidgetItem> selections = tagTree.selectedItems(); QTreeWidgetItem currentSelection = null; if (selections.size() > 0) { currentSelection = selections.get(0); edit.setParentTag(currentSelection.text(0)); } edit.exec(); if (!edit.okPressed()) return; Calendar currentTime = new GregorianCalendar(); Long l = new Long(currentTime.getTimeInMillis()); String randint = new String(Long.toString(l)); Tag newTag = new Tag(); newTag.setUpdateSequenceNum(0); newTag.setGuid(randint); newTag.setName(edit.getTag()); if (edit.getParentTag().isChecked()) { newTag.setParentGuid(currentSelection.text(2)); newTag.setParentGuidIsSet(true); currentSelection.setExpanded(true); } conn.getTagTable().addTag(newTag, true); listManager.getTagIndex().add(newTag); reloadTagTree(true); logger.log(logger.HIGH, "Leaving NeverNote.addTag"); } @SuppressWarnings("unused") private void reloadTagTree() { reloadTagTree(false); } private void reloadTagTree(boolean reload) { logger.log(logger.HIGH, "Entering NeverNote.reloadTagTree"); tagIndexUpdated(reload); boolean filter = false; if (reload) listManager.countTagResults(listManager.getNoteIndex()); if (notebookTree.selectedItems().size() > 0 && !notebookTree.selectedItems().get(0).text(0).equalsIgnoreCase("All Notebooks")) filter = true; if (tagTree.selectedItems().size() > 0) filter = true; tagTree.showAllTags(!filter); tagIndexUpdated(false); 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<QTreeWidgetItem> 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<listManager.getTagIndex().size(); i++) { if (listManager.getTagIndex().get(i).getGuid().equals(guid)) { listManager.getTagIndex().get(i).setName(edit.getTag()); conn.getTagTable().updateTag(listManager.getTagIndex().get(i), true); updateListTagName(guid); if (currentNote != null && currentNote.getTagGuids().contains(guid)) browserWindow.setTag(getTagNamesForNote(currentNote)); logger.log(logger.HIGH, "Leaving NeverNote.editTag"); //return; } } listManager.reloadNoteTagNames(guid, edit.getTag()); noteIndexUpdated(true); refreshEvernoteNote(true); browserWindow.setTag(getTagNamesForNote(currentNote)); logger.log(logger.HIGH, "Leaving NeverNote.editTag..."); } // Delete an existing tag @SuppressWarnings("unused") private void deleteTag() { logger.log(logger.HIGH, "Entering NeverNote.deleteTag"); if (QMessageBox.question(this, tr("Confirmation"), tr("Delete the selected tags?"), QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No)==StandardButton.No.value()) { return; } List<QTreeWidgetItem> selections = tagTree.selectedItems(); for (int i=selections.size()-1; i>=0; i--) { QTreeWidgetItem currentSelection; currentSelection = selections.get(i); removeTagItem(currentSelection.text(2)); } tagIndexUpdated(true); tagTreeSelection(); 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<listManager.getTagIndex().size(); a++) { if (listManager.getTagIndex().get(a).getGuid().equals(guid)) { listManager.getTagIndex().remove(a); return; } } } // Setup the tree containing the user's tags private void initializeTagTree() { logger.log(logger.HIGH, "Entering NeverNote.initializeTagTree"); // tagTree.itemSelectionChanged.connect(this, "tagTreeSelection()"); // tagTree.itemClicked.connect(this, "tagTreeSelection()"); tagTree.selectionSignal.connect(this, "tagTreeSelection()"); listManager.tagSignal.refreshTagTreeCounts.connect(tagTree, "updateCounts(List)"); logger.log(logger.HIGH, "Leaving NeverNote.initializeTagTree"); } // Listener when a tag is selected private void tagTreeSelection() { logger.log(logger.HIGH, "Entering NeverNote.tagTreeSelection"); clearTrashFilter(); clearAttributeFilter(); clearSavedSearchFilter(); menuBar.noteRestoreAction.setVisible(false); // ゴミ箱から元の画面に戻す。連想ノートリストをONに。 if (!rensoNoteListDock.isEnabled()) { rensoNoteListDock.setEnabled(true); } List<QTreeWidgetItem> selections = tagTree.selectedItems(); QTreeWidgetItem currentSelection; selectedTagGUIDs.clear(); searchField.getTargetTags().clear(); for (int i=0; i<selections.size(); i++) { currentSelection = selections.get(i); selectedTagGUIDs.add(currentSelection.text(2)); searchField.addTargetTag(currentSelection.text(2)); } if (selections.size() > 0) { menuBar.tagEditAction.setEnabled(true); menuBar.tagDeleteAction.setEnabled(true); menuBar.tagIconAction.setEnabled(true); } else { menuBar.tagEditAction.setEnabled(false); menuBar.tagDeleteAction.setEnabled(false); menuBar.tagIconAction.setEnabled(true); } if (selections.size() > 1) menuBar.tagMergeAction.setEnabled(true); else menuBar.tagMergeAction.setEnabled(false); listManager.setSelectedTags(selectedTagGUIDs); listManager.loadNotesIndex(); noteIndexUpdated(false); refreshEvernoteNote(true); listManager.refreshCounters = true; listManager.refreshCounters(); 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<String>(); if (reload) listManager.reloadTagIndex(); tagTree.blockSignals(true); if (reload) { tagTree.setIcons(conn.getTagTable().getAllIcons()); 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); searchField.getTargetTags().remove(i); } } tagTree.blockSignals(false); browserWindow.setTag(getTagNamesForNote(currentNote)); logger.log(logger.HIGH, "Leaving NeverNote.tagIndexUpdated"); } // Show/Hide note information @SuppressWarnings("unused") 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<String> tags) { // Save any new tags. We'll need them later. List<String> newTags = new ArrayList<String>(); for (int i=0; i<tags.size(); i++) { if (conn.getTagTable().findTagByName(tags.get(i))==null) newTags.add(tags.get(i)); } listManager.saveNoteTags(guid, tags, true); listManager.countTagResults(listManager.getNoteIndex()); StringBuffer names = new StringBuffer(""); for (int i=0; i<tags.size(); i++) { names = names.append(tags.get(i)); if (i<tags.size()-1) { names.append(Global.tagDelimeter + " "); } } browserWindow.setTag(names.toString()); for (TabBrowse tab: tabWindows.values()) { if (tab.getBrowserWindow().getNote().getGuid().equals(guid)) { int index = tabBrowser.indexOf(tab); noteDirty.put(index, true); break; } } // Now, we need to add any new tags to the tag tree for (int i=0; i<newTags.size(); i++) tagTree.insertTag(newTags.get(i), conn.getTagTable().findTagByName(newTags.get(i))); } // Get a string containing all tag names for a note private String getTagNamesForNote(Note n) { logger.log(logger.HIGH, "Entering NeverNote.getTagNamesForNote"); if (n==null || n.getGuid() == null || n.getGuid().equals("")) return ""; StringBuffer buffer = new StringBuffer(100); Vector<String> v = new Vector<String>(); List<String> guids = n.getTagGuids(); if (guids == null) return ""; for (int i=0; i<guids.size(); i++) { v.add(listManager.getTagNameByGuid(guids.get(i))); } Comparator<String> comparator = Collections.reverseOrder(); Collections.sort(v,comparator); Collections.reverse(v); for (int i = 0; i<v.size(); i++) { if (i>0) 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<listManager.getTagIndex().size(); i++) { if (listManager.getTagIndex().get(i).getGuid().equals(tagGuid)) { tagName = listManager.getTagIndex().get(i).getName(); i=listManager.getTagIndex().size(); } } if (tagName == null) return; for (int i=0; i<listManager.getMasterNoteIndex().size(); i++) { if (listManager.getMasterNoteIndex().get(i).getGuid().equals(noteGuid)) { List<String> tagNames = new ArrayList<String>(); tagNames.add(new String(tagName)); Note n = listManager.getMasterNoteIndex().get(i); for (int j=0; j<n.getTagNames().size(); j++) { tagNames.add(new String(n.getTagNames().get(j))); } listManager.getNoteTableModel().updateNoteTags(noteGuid, n.getTagGuids(), tagNames); if (n.getGuid().equals(currentNoteGuid)) { Collections.sort(tagNames); String display = ""; for (int j=0; j<tagNames.size(); j++) { display = display+tagNames.get(j); if (j+2<tagNames.size()) display = display+Global.tagDelimeter+" "; } browserWindow.setTag(display); } i=listManager.getMasterNoteIndex().size(); } } listManager.getNoteTableModel().updateNoteSyncStatus(noteGuid, false); } private void clearTagFilter() { tagTree.blockSignals(true); tagTree.clearSelection(); menuBar.noteRestoreAction.setVisible(false); menuBar.tagEditAction.setEnabled(false); menuBar.tagMergeAction.setEnabled(false); menuBar.tagDeleteAction.setEnabled(false); menuBar.tagIconAction.setEnabled(false); selectedTagGUIDs.clear(); searchField.getTargetTags().clear(); listManager.setSelectedTags(selectedTagGUIDs); tagTree.blockSignals(false); } // Change the icon for a tag @SuppressWarnings("unused") private void setTagIcon() { QTreeWidgetItem currentSelection; List<QTreeWidgetItem> selections = tagTree.selectedItems(); if (selections.size() == 0) return; currentSelection = selections.get(0); String guid = currentSelection.text(2); QIcon currentIcon = currentSelection.icon(0); QIcon icon = conn.getTagTable().getIcon(guid); SetIcon dialog; if (icon == null) { dialog = new SetIcon(currentIcon, saveLastPath); dialog.setUseDefaultIcon(true); } else { dialog = new SetIcon(icon, saveLastPath); dialog.setUseDefaultIcon(false); } dialog.exec(); if (dialog.okPressed()) { saveLastPath = dialog.getPath(); QIcon newIcon = dialog.getIcon(); conn.getTagTable().setIcon(guid, newIcon, dialog.getFileType()); if (newIcon == null) newIcon = new QIcon(iconPath+"tag.png"); currentSelection.setIcon(0, newIcon); } } // Merge tags @SuppressWarnings("unused") private void mergeTags() { List<Tag> tags = new ArrayList<Tag>(); List<QTreeWidgetItem> selections = tagTree.selectedItems(); for (int i=0; i<selections.size(); i++) { Tag record = new Tag(); record.setGuid(selections.get(i).text(2)); record.setName(selections.get(i).text(0)); tags.add(record); } TagMerge mergeDialog = new TagMerge(tags); mergeDialog.exec(); if (!mergeDialog.okClicked()) return; String newGuid = mergeDialog.getNewTagGuid(); for (int i=0; i<tags.size(); i++) { if (!tags.get(i).getGuid().equals(newGuid)) { List<String> noteGuids = conn.getNoteTable().noteTagsTable.getTagNotes(tags.get(i).getGuid()); for (int j=0; j<noteGuids.size(); j++) { String noteGuid = noteGuids.get(j); conn.getNoteTable().noteTagsTable.deleteNoteTag(noteGuid); if (!conn.getNoteTable().noteTagsTable.checkNoteNoteTags(noteGuid, newGuid)) conn.getNoteTable().noteTagsTable.saveNoteTag(noteGuid, newGuid, true); } } } listManager.reloadIndexes(); } //*************************************************************** //*************************************************************** //** 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(tr("Edit Search")); List<QTreeWidgetItem> 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<SavedSearch> list = listManager.getSavedSearchIndex(); SavedSearch search = null; boolean found = false; for (int i=0; i<list.size(); i++) { search = list.get(i); if (search.getGuid().equals(guid)) { i=list.size(); found = true; } } if (!found) return; search.setName(edit.getName()); search.setQuery(edit.getQuery()); conn.getSavedSearchTable().updateSavedSearch(search, true); savedSearchIndexUpdated(); logger.log(logger.HIGH, "Leaving NeverNote.editSavedSearch"); } // Delete an existing tag @SuppressWarnings("unused") private void deleteSavedSearch() { logger.log(logger.HIGH, "Entering NeverNote.deleteSavedSearch"); if (QMessageBox.question(this, tr("Confirmation"), tr("Delete the selected search?"), QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No)==StandardButton.No.value()) { return; } List<QTreeWidgetItem> selections = savedSearchTree.selectedItems(); for (int i=selections.size()-1; i>=0; i--) { QTreeWidgetItem currentSelection; currentSelection = selections.get(i); for (int j=0; j<listManager.getSavedSearchIndex().size(); j++) { if (listManager.getSavedSearchIndex().get(j).getGuid().equals(currentSelection.text(1))) { conn.getSavedSearchTable().expungeSavedSearch(listManager.getSavedSearchIndex().get(j).getGuid(), true); listManager.getSavedSearchIndex().remove(j); j=listManager.getSavedSearchIndex().size()+1; } } selections.remove(i); } savedSearchIndexUpdated(); logger.log(logger.HIGH, "Leaving NeverNote.deleteSavedSearch"); } // Setup the tree containing the user's tags private void initializeSavedSearchTree() { logger.log(logger.HIGH, "Entering NeverNote.initializeSavedSearchTree"); savedSearchTree.itemSelectionChanged.connect(this, "savedSearchTreeSelection()"); logger.log(logger.HIGH, "Leaving NeverNote.initializeSavedSearchTree"); } // Listener when a tag is selected @SuppressWarnings("unused") private void savedSearchTreeSelection() { logger.log(logger.HIGH, "Entering NeverNote.savedSearchTreeSelection"); clearNotebookFilter(); clearTagFilter(); clearTrashFilter(); clearAttributeFilter(); String currentGuid = selectedSavedSearchGUID; menuBar.savedSearchEditAction.setEnabled(true); menuBar.savedSearchDeleteAction.setEnabled(true); menuBar.savedSearchIconAction.setEnabled(true); // ゴミ箱から元の画面に戻す。連想ノートリストをONに。 if (!rensoNoteListDock.isEnabled()) { rensoNoteListDock.setEnabled(true); } List<QTreeWidgetItem> selections = savedSearchTree.selectedItems(); QTreeWidgetItem currentSelection; selectedSavedSearchGUID = ""; for (int i=0; i<selections.size(); i++) { currentSelection = selections.get(i); if (currentSelection.text(1).equals(currentGuid)) { currentSelection.setSelected(false); } else { selectedSavedSearchGUID = currentSelection.text(1); } // i = selections.size() +1; } // There is the potential for no notebooks to be selected if this // happens then we make it look like all notebooks were selecetd. // If that happens, just select the "all notebooks" if (selections.size()==0) { clearSavedSearchFilter(); } listManager.setSelectedSavedSearch(selectedSavedSearchGUID); logger.log(logger.HIGH, "Leaving NeverNote.savedSearchTreeSelection"); } private void clearSavedSearchFilter() { menuBar.savedSearchEditAction.setEnabled(false); menuBar.savedSearchDeleteAction.setEnabled(false); menuBar.savedSearchIconAction.setEnabled(false); savedSearchTree.blockSignals(true); savedSearchTree.clearSelection(); savedSearchTree.blockSignals(false); selectedSavedSearchGUID = ""; searchField.setDefaultText(); searchPerformed = false; listManager.setSelectedSavedSearch(selectedSavedSearchGUID); } // trigger the tag index to be refreshed private void savedSearchIndexUpdated() { if (selectedSavedSearchGUID == null) selectedSavedSearchGUID = new String(); savedSearchTree.blockSignals(true); savedSearchTree.setIcons(conn.getSavedSearchTable().getAllIcons()); savedSearchTree.load(listManager.getSavedSearchIndex()); savedSearchTree.selectGuid(selectedSavedSearchGUID); savedSearchTree.blockSignals(false); } // trigger when the saved search selection changes @SuppressWarnings("unused") private void updateSavedSearchSelection() { logger.log(logger.HIGH, "Entering NeverNote.updateSavedSearchSelection()"); menuBar.savedSearchEditAction.setEnabled(true); menuBar.savedSearchDeleteAction.setEnabled(true); menuBar.savedSearchIconAction.setEnabled(true); List<QTreeWidgetItem> selections = savedSearchTree.selectedItems(); if (selections.size() > 0) { menuBar.savedSearchEditAction.setEnabled(true); menuBar.savedSearchDeleteAction.setEnabled(true); menuBar.savedSearchIconAction.setEnabled(true); selectedSavedSearchGUID = selections.get(0).text(1); SavedSearch s = conn.getSavedSearchTable().getSavedSearch(selectedSavedSearchGUID); searchField.setText(s.getQuery()); } else { menuBar.savedSearchEditAction.setEnabled(false); menuBar.savedSearchDeleteAction.setEnabled(false); menuBar.savedSearchIconAction.setEnabled(false); selectedSavedSearchGUID = ""; searchField.setDefaultText(); } searchFieldChanged(); logger.log(logger.HIGH, "Leaving NeverNote.updateSavedSearchSelection()"); } // Show/Hide note information @SuppressWarnings("unused") 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"); } // Change the icon for a saved search @SuppressWarnings("unused") private void setSavedSearchIcon() { QTreeWidgetItem currentSelection; List<QTreeWidgetItem> selections = savedSearchTree.selectedItems(); if (selections.size() == 0) return; currentSelection = selections.get(0); String guid = currentSelection.text(1); QIcon currentIcon = currentSelection.icon(0); QIcon icon = conn.getSavedSearchTable().getIcon(guid); SetIcon dialog; if (icon == null) { dialog = new SetIcon(currentIcon, saveLastPath); dialog.setUseDefaultIcon(true); } else { dialog = new SetIcon(icon, saveLastPath); dialog.setUseDefaultIcon(false); } dialog.exec(); if (dialog.okPressed()) { saveLastPath = dialog.getPath(); QIcon newIcon = dialog.getIcon(); conn.getSavedSearchTable().setIcon(guid, newIcon, dialog.getFileType()); if (newIcon == null) newIcon = new QIcon(iconPath+"search.png"); currentSelection.setIcon(0, newIcon); } } //*************************************************************** //*************************************************************** //** These functions deal with Help menu & tool menu items //*************************************************************** //*************************************************************** // Show database status @SuppressWarnings("unused") private void databaseStatus() { waitCursor(true); indexRunner.interrupt = 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.setUnindexedResourceCount(conn.getNoteTable().noteResourceTable.getUnindexedCount()); status.setSavedSearchCount(listManager.getSavedSearchIndex().size()); status.setTagCount(listManager.getTagIndex().size()); status.setResourceCount(conn.getNoteTable().noteResourceTable.getResourceCount()); status.setWordCount(conn.getWordsTable().getWordCount()); status.setHistoryCount(conn.getHistoryTable().getHistoryCount()); status.setRensoClickCount(conn.getHistoryTable().getRensoClickCount()); waitCursor(false); status.exec(); } // Compact the database @SuppressWarnings("unused") private void compactDatabase() { logger.log(logger.HIGH, "Entering NeverNote.compactDatabase"); if (QMessageBox.question(this, tr("Confirmation"), tr("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 NeighborNote 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.getFileManager().getProgramDirPath("release.txt")); if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly, QIODevice.OpenModeFlag.Text))) return; // 日本語文字化け対策 QTextCodec codec = QTextCodec.codecForName("UTF-8"); QTextStream textStream = new QTextStream(file); textStream.setCodec(codec); textBox.setText(textStream.readAll().toString()); file.close(); dialog.setWindowTitle(tr("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"); LogFileDialog dialog = new LogFileDialog(emitLog); dialog.exec(); 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 NeighborNote"), tr("<h4><center><b>NeighborNote</b></center></h4><hr><center>Version ") +Global.version + "(based on NixNote 1.6)" //+"1.2.120724" +tr("<hr>" +"Open Source Evernote Client.<br><br>" +"Licensed under GPL v2. <br><hr><br>" +"</center>Evernote is copyright 2001-2012 by Evernote Corporation<br>" +"Jambi and QT are the licensed trademark of Nokia Corporation<br>" +"PDFRenderer is licened under the LGPL<br>" +"JTidy is copyrighted under the World Wide Web Consortium<br>" +"Apache Common Utilities licensed under the Apache License Version 2.0<br>" +"Jazzy is licened under the LGPL<br>" +"Java is a registered trademark of Oracle Corporation.<br><hr>" +"Special thanks to:<br>BitRock InstallBuilder for the Windows installer" +"<br>CodeCogs (www.codecogs.com) for the LaTeX image rendering.")); 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 (!hidden) leftSplitter1.setHidden(true); else leftSplitter1.setHidden(false); Global.saveWindowVisible("leftPanel", hidden); } public void checkForUpdates() { // Send off thread to check for a new version versionChecker = new QNetworkAccessManager(this); versionChecker.finished.connect(this, "upgradeFileRead(QNetworkReply)"); QNetworkRequest request = new QNetworkRequest(); request.setUrl(new QUrl(Global.getUpdatesAvailableUrl())); versionChecker.get(request); } @SuppressWarnings("unused") private void upgradeFileRead(QNetworkReply reply) { if (!reply.isReadable()) return; String winVersion = Global.version; String osxVersion = Global.version; String linuxVersion = Global.version; String linux64Version = Global.version; String version = Global.version; // Determine the versions available QByteArray data = reply.readLine(); while (data != null && !reply.atEnd()) { String line = data.toString(); String lineVersion; if (line.contains(":")) lineVersion = line.substring(line.indexOf(":")+1).replace(" ", "").replace("\n", ""); else lineVersion = ""; if (line.toLowerCase().contains("windows")) winVersion = lineVersion; else if (line.toLowerCase().contains("os-x")) osxVersion = lineVersion; else if (line.toLowerCase().contains("linux amd64")) linux64Version = lineVersion; else if (line.toLowerCase().contains("linux i386")) linuxVersion = lineVersion; else if (line.toLowerCase().contains("default")) version = lineVersion; // Read the next line data = reply.readLine(); } // Now we need to determine what system we are on. if (System.getProperty("os.name").toLowerCase().contains("windows")) version = winVersion; if (System.getProperty("os.name").toLowerCase().contains("mac os")) version = osxVersion; if (System.getProperty("os.name").toLowerCase().contains("Linux")) { if (System.getProperty("os.arch").contains("amd64") || System.getProperty("os.arch").contains("x86_64")) version = linux64Version; else version = linuxVersion; } for (String validVersion : Global.validVersions) { if (version.equals(validVersion)) return; } UpgradeAvailableDialog dialog = new UpgradeAvailableDialog(); dialog.exec(); if (dialog.remindMe()) Global.setCheckVersionUpgrade(true); else Global.setCheckVersionUpgrade(false); } //*************************************************************** //*************************************************************** //** These functions deal with the Toolbar //*************************************************************** //*************************************************************** @SuppressWarnings("unused") private void focusSearch() { searchField.setFocus(); } // Text in the search bar has been cleared private void searchFieldCleared() { saveNote(); // This is done because we want to force a reload of // images. Some images we may want to highlight the text. readOnlyCache.clear(); inkNoteCache.clear(); noteCache.clear(); QWebSettings.setMaximumPagesInCache(0); QWebSettings.setObjectCacheCapacities(0, 0, 0); searchField.setDefaultText(); saveNoteColumnPositions(); saveNoteIndexWidth(); noteIndexUpdated(true); if (currentNote == null && listManager.getNoteIndex().size() > 0) { currentNote = listManager.getNoteIndex().get(0); currentNoteGuid = currentNote.getGuid(); } refreshEvernoteNote(true); if (currentNote != null) loadNoteBrowserInformation(browserWindow, currentNoteGuid, currentNote); } // 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) { QWebSettings.setMaximumPagesInCache(0); QWebSettings.setObjectCacheCapacities(0, 0, 0); if (text.trim().equals("") && !searchField.hasFocus()) { searchFieldCleared(); if (searchPerformed) { // This is done because we want to force a reload of // images. Some images we may want to highlight the text. noteCache.clear(); readOnlyCache.clear(); inkNoteCache.clear(); listManager.setEnSearch(""); listManager.loadNotesIndex(); refreshEvernoteNote(true); noteIndexUpdated(false); refreshEvernoteNote(true); } searchPerformed = false; } } // Text in the toolbar has changed private void searchFieldChanged() { logger.log(logger.HIGH, "Entering NeverNote.searchFieldChanged"); noteCache.clear(); readOnlyCache.clear(); inkNoteCache.clear(); saveNoteColumnPositions(); saveNoteIndexWidth(); String query = searchField.getSearchQuery(); listManager.setEnSearch(query.trim()); listManager.loadNotesIndex(); noteIndexUpdated(false); refreshEvernoteNote(true); searchPerformed = true; waitCursor(false); 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("Tool Bar")); toolBar.setObjectName("toolBar"); toolBar.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon); menuBar.setupToolBarVisible(); if (!Global.isWindowVisible("toolBar")) toolBar.setVisible(false); else toolBar.setVisible(true); // toolBar.addWidget(menuBar); // menuBar.setSizePolicy(Policy.Minimum, Policy.Minimum); // toolBar.addSeparator(); prevButton = toolBar.addAction(tr("")); prevButton.setToolTip(tr("Previous")); QIcon prevIcon = new QIcon(iconPath+"back.png"); prevButton.setIcon(prevIcon); prevButton.triggered.connect(this, "previousViewedAction()"); togglePrevArrowButton(Global.isToolbarButtonVisible("prevArrow", true)); nextButton = toolBar.addAction(tr("")); nextButton.setToolTip(tr("Next")); QIcon nextIcon = new QIcon(iconPath+"forward.png"); nextButton.setIcon(nextIcon); nextButton.triggered.connect(this, "nextViewedAction()"); toggleNextArrowButton(Global.isToolbarButtonVisible("nextArrow", true)); toolBar.addSeparator(); upButton = toolBar.addAction(tr("Up")); QIcon upIcon = new QIcon(iconPath+"up.png"); upButton.setIcon(upIcon); upButton.triggered.connect(this, "upAction()"); toggleUpArrowButton(Global.isToolbarButtonVisible("upArrow", false)); downButton = toolBar.addAction(tr("Down")); QIcon downIcon = new QIcon(iconPath+"down.png"); downButton.setIcon(downIcon); downButton.triggered.connect(this, "downAction()"); toggleDownArrowButton(Global.isToolbarButtonVisible("downArrow", false)); synchronizeButton = toolBar.addAction(tr("Synchronize")); synchronizeButton.setIcon(new QIcon(iconPath+"synchronize.png")); synchronizeIconAngle = 0; synchronizeButton.triggered.connect(this, "evernoteSync()"); toggleSynchronizeButton(Global.isToolbarButtonVisible("synchronize", true)); printButton = toolBar.addAction(tr("Print")); QIcon printIcon = new QIcon(iconPath+"print.png"); printButton.setIcon(printIcon); printButton.triggered.connect(this, "printNote()"); togglePrintButton(Global.isToolbarButtonVisible("print", false)); tagButton = toolBar.addAction(tr("Tag")); QIcon tagIcon = new QIcon(iconPath+"tag.png"); tagButton.setIcon(tagIcon); tagButton.triggered.connect(browserWindow, "modifyTags()"); toggleTagButton(Global.isToolbarButtonVisible("tag", false)); attributeButton = toolBar.addAction(tr("Attributes")); QIcon attributeIcon = new QIcon(iconPath+"attribute.png"); attributeButton.setIcon(attributeIcon); attributeButton.triggered.connect(this, "toggleNoteAttributes()"); toggleAttributeButton(Global.isToolbarButtonVisible("attribute", true)); emailButton = toolBar.addAction(tr("Email")); QIcon emailIcon = new QIcon(iconPath+"email.png"); emailButton.setIcon(emailIcon); emailButton.triggered.connect(this, "emailNote()"); toggleEmailButton(Global.isToolbarButtonVisible("email", false)); deleteButton = toolBar.addAction(tr("Delete")); QIcon deleteIcon = new QIcon(iconPath+"delete.png"); deleteButton.setIcon(deleteIcon); deleteButton.triggered.connect(this, "deleteNote()"); toggleDeleteButton(Global.isToolbarButtonVisible("delete", true)); newButton = toolBar.addAction(tr("New")); QIcon newIcon = new QIcon(iconPath+"new.png"); if (Global.toolBarNewAction()) { newButton.triggered.connect(this, "noteAddNewTab()"); } else { newButton.triggered.connect(this, "addNote()"); } newButton.setIcon(newIcon); toggleNewButton(Global.isToolbarButtonVisible("new", true)); allNotesButton = toolBar.addAction(tr("All Notes")); QIcon allIcon = new QIcon(iconPath+"books.png"); allNotesButton.triggered.connect(this, "allNotes()"); allNotesButton.setIcon(allIcon); toggleAllNotesButton(Global.isToolbarButtonVisible("allNotes", true)); //toolBar.addSeparator(); //toolBar.addWidget(new QLabel(tr("Quota:"))); //toolBar.addWidget(quotaBar); //quotaBar.setSizePolicy(Policy.Minimum, Policy.Minimum); updateQuotaBar(); //toolBar.addSeparator(); //toolBar.addWidget(new QLabel(tr("Zoom"))); //toolBar.addWidget(zoomSpinner); //toolBar.addWidget(new QLabel(" ")); //toolBar.addSeparator(); // 検索ボックスを右寄せするためのスペーサ QWidget spacerWidget = new QWidget(); spacerWidget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred); toolBar.addWidget(spacerWidget); spacerWidget.setVisible(true); searchField = new SearchEdit(iconPath, conn); searchField.setObjectName("searchField"); searchField.returnPressed.connect(this, "searchFieldChanged()"); searchField.textEdited.connect(this,"searchFieldTextChanged(String)"); searchField.setMaximumWidth(400); searchField.setMinimumWidth(80); searchField.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed); searchShortcut = new QShortcut(this); setupShortcut(searchShortcut, "Focus_Search"); searchShortcut.activated.connect(this, "focusSearch()"); toolBar.addWidget(searchField); searchField.setVisible(Global.isWindowVisible("searchField")); // IFIXED !searchField.isVisible() → !Global.isWindowVisible("searchField") // なぜかsearchField.isVisible()が常にfalseを返すようなので修正 if (!Global.isWindowVisible("searchField")) menuBar.hideSearch.setChecked(false); // QSizePolicy sizePolicy = new QSizePolicy(); // sizePolicy.setHorizontalPolicy(Policy.MinimumExpanding); // QLabel spacer = new QLabel(""); // spacer.setSizePolicy(sizePolicy); // toolBar.addWidget(spacer); //searchField.setInsertPolicy(InsertPolicy.InsertAtTop); //searchClearButton = toolBar.addAction("Search Clear"); //QIcon searchClearIcon = new QIcon(iconPath+"searchclear.png"); //searchClearButton.setIcon(searchClearIcon); //searchClearButton.triggered.connect(this, "searchFieldCleared()"); //toggleSearchClearButton(Global.isToolbarButtonVisible("searchClear")); logger.log(logger.HIGH, "Leaving NeverNote.setupToolBar"); } // Update the sychronize button picture @Override public QMenu createPopupMenu() { QMenu contextMenu = super.createPopupMenu(); contextMenu.addSeparator(); QAction prevAction = addContextAction("prevArrow", tr("Previous Arrow")); contextMenu.addAction(prevAction); prevAction.triggered.connect(this, "togglePrevArrowButton(Boolean)"); QAction nextAction = addContextAction("nextArrow", tr("Next Arrow")); contextMenu.addAction(nextAction); nextAction.triggered.connect(this, "toggleNextArrowButton(Boolean)"); QAction upAction = addContextAction("upArrow", tr("Up Arrow")); contextMenu.addAction(upAction); upAction.triggered.connect(this, "toggleUpArrowButton(Boolean)"); QAction downAction = addContextAction("downArrow", tr("Down Arrow")); contextMenu.addAction(downAction); downAction.triggered.connect(this, "toggleDownArrowButton(Boolean)"); QAction synchronizeAction = addContextAction("synchronize", tr("Synchronize")); contextMenu.addAction(synchronizeAction); synchronizeAction.triggered.connect(this, "toggleSynchronizeButton(Boolean)"); QAction printAction = addContextAction("print", tr("Print")); contextMenu.addAction(printAction); printAction.triggered.connect(this, "togglePrintButton(Boolean)"); QAction tagAction = addContextAction("tag", tr("Tag")); contextMenu.addAction(tagAction); tagAction.triggered.connect(this, "toggleTagButton(Boolean)"); QAction attributeAction = addContextAction("attribute", tr("Attribute")); contextMenu.addAction(attributeAction); attributeAction.triggered.connect(this, "toggleAttributeButton(Boolean)"); QAction emailAction = addContextAction("email", tr("Email")); contextMenu.addAction(emailAction); emailAction.triggered.connect(this, "toggleEmailButton(Boolean)"); QAction deleteAction = addContextAction("delete", tr("Delete")); contextMenu.addAction(deleteAction); deleteAction.triggered.connect(this, "toggleDeleteButton(Boolean)"); QAction newAction = addContextAction("new", tr("Add")); contextMenu.addAction(newAction); newAction.triggered.connect(this, "toggleNewButton(Boolean)"); QAction allNotesAction = addContextAction("allNotes", tr("All Notes")); contextMenu.addAction(allNotesAction); allNotesAction.triggered.connect(this, "toggleAllNotesButton(Boolean)"); // QAction searchClearAction = addContextAction("searchClear", tr("Search Clear")); // contextMenu.addAction(searchClearAction); // searchClearAction.triggered.connect(this, "toggleSearchClearButton(Boolean)"); return contextMenu; } private QAction addContextAction(String config, String name) { QAction newAction = new QAction(this); newAction.setText(name); newAction.setCheckable(true); newAction.setChecked(Global.isToolbarButtonVisible(config, true)); return newAction; } private void togglePrevArrowButton(Boolean toggle) { prevButton.setVisible(toggle); Global.saveToolbarButtonsVisible("prevArrow", toggle); } private void toggleNextArrowButton(Boolean toggle) { nextButton.setVisible(toggle); Global.saveToolbarButtonsVisible("nextArrow", toggle); } private void toggleUpArrowButton(Boolean toggle) { upButton.setVisible(toggle); Global.saveToolbarButtonsVisible("upArrow", toggle); } private void toggleDownArrowButton(Boolean toggle) { downButton.setVisible(toggle); Global.saveToolbarButtonsVisible("downArrow", toggle); } private void toggleSynchronizeButton(Boolean toggle) { synchronizeButton.setVisible(toggle); Global.saveToolbarButtonsVisible("synchronize", toggle); } private void togglePrintButton(Boolean toggle) { printButton.setVisible(toggle); Global.saveToolbarButtonsVisible("print", toggle); } private void toggleTagButton(Boolean toggle) { tagButton.setVisible(toggle); Global.saveToolbarButtonsVisible("tag", toggle); } private void toggleAttributeButton(Boolean toggle) { attributeButton.setVisible(toggle); Global.saveToolbarButtonsVisible("attribute", toggle); } private void toggleEmailButton(Boolean toggle) { emailButton.setVisible(toggle); Global.saveToolbarButtonsVisible("email", toggle); } private void toggleDeleteButton(Boolean toggle) { deleteButton.setVisible(toggle); Global.saveToolbarButtonsVisible("delete", toggle); } private void toggleNewButton(Boolean toggle) { newButton.setVisible(toggle); Global.saveToolbarButtonsVisible("new", toggle); } private void toggleAllNotesButton(Boolean toggle) { allNotesButton.setVisible(toggle); Global.saveToolbarButtonsVisible("allNotes", toggle); } // @SuppressWarnings("unused") // private void toggleSearchClearButton(Boolean toggle) { // searchClearButton.setVisible(toggle); // Global.saveToolbarButtonsVisible("searchClear", toggle); // } @SuppressWarnings("unused") private void updateSyncButton() { if (syncIcons == null) { syncIcons = new ArrayList<QPixmap>(); double angle = 0.0; synchronizeIconAngle = 0; QPixmap pix = new QPixmap(iconPath+"synchronize.png"); syncIcons.add(pix); for (int i=0; i<=360; i++) { QPixmap rotatedPix = new QPixmap(pix.size()); QPainter p = new QPainter(rotatedPix); rotatedPix.fill(toolBar.palette().color(ColorRole.Button)); QSize size = pix.size(); p.translate(size.width()/2, size.height()/2); angle = angle+1.0; p.rotate(angle); p.setBackgroundMode(BGMode.OpaqueMode); p.translate(-size.width()/2, -size.height()/2); p.drawPixmap(0,0, pix); p.end(); syncIcons.add(rotatedPix); } } synchronizeIconAngle++; if (synchronizeIconAngle > 359) synchronizeIconAngle=0; synchronizeButton.setIcon(syncIcons.get(synchronizeIconAngle)); } // Synchronize with Evernote private void evernoteSync() { logger.log(logger.HIGH, "Entering NeverNote.evernoteSync"); if (!Global.isConnected) remoteConnect(); if (Global.isConnected) synchronizeAnimationTimer.start(5); // 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(); if (windowMaximized) showMaximized(); else showNormal(); 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<QTreeWidgetItem> selections = trashTree.selectedItems(); if (selections.size() == 0) { currentNoteGuid = trashNoteGuid; trashNoteGuid = tempGuid; Global.showDeleted = false; menuBar.noteRestoreAction.setEnabled(false); menuBar.noteRestoreAction.setVisible(false); // ゴミ箱から元の画面に戻す。連想ノートリストをONに。 rensoNoteListDock.setEnabled(true); } else { trashNoteGuid = tempGuid; currentNoteGuid = trashNoteGuid; menuBar.noteRestoreAction.setEnabled(true); menuBar.noteRestoreAction.setVisible(true); // ゴミ箱を開く。連想ノートリストをOFFに。 rensoNoteListDock.setEnabled(false); Global.showDeleted = true; } menuBar.noteAddNewTab.setEnabled(newButton.isEnabled()); if (currentNoteGuid == null || currentNoteGuid.equals("")) { menuBar.noteAddNewTab.setEnabled(false); } 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(); logger.log(logger.EXTREME, "Emptying Trash"); listManager.emptyTrash(); logger.log(logger.EXTREME, "Resetting view after trash empty"); if (trashTree.selectedItems().size() > 0) { listManager.getSelectedNotebooks().clear(); listManager.getSelectedTags().clear(); listManager.setSelectedSavedSearch(""); newButton.setEnabled(!newButton.isEnabled()); menuBar.noteAdd.setEnabled(newButton.isEnabled()); menuBar.noteAddNewTab.setEnabled(newButton.isEnabled()); if (currentNoteGuid == null || currentNoteGuid.equals("")) { menuBar.noteAddNewTab.setEnabled(false); } menuBar.noteAdd.setVisible(true); browserWindow.clear(); clearTagFilter(); clearNotebookFilter(); clearSavedSearchFilter(); clearAttributeFilter(); Global.showDeleted = false; menuBar.noteRestoreAction.setEnabled(false); menuBar.noteRestoreAction.setVisible(false); listManager.loadNotesIndex(); noteIndexUpdated(false); // ゴミ箱から元の画面に戻す。連想ノートリストをONに。 if (!rensoNoteListDock.isEnabled()) { rensoNoteListDock.setEnabled(true); } } } // Show/Hide trash window @SuppressWarnings("unused") 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); if (currentNoteGuid == null || currentNoteGuid.equals("")) { menuBar.noteAddNewTab.setEnabled(false); } else { menuBar.noteAddNewTab.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(tr("Connect")); menuBar.connectAction.setToolTip(tr("Connect to Evernote")); menuBar.synchronizeAction.setEnabled(false); Global.isConnected = false; synchronizeAnimationTimer.stop(); return; } // Do a manual connect/disconnect private void remoteConnect() { logger.log(logger.HIGH, "Entering NeverNote.remoteConnect"); // If we are already connected, we just disconnect if (Global.isConnected) { Global.isConnected = false; syncRunner.enDisconnect(); setupConnectMenuOptions(); setupOnlineMenu(); return; } OAuthTokenizer tokenizer = new OAuthTokenizer(); AESEncrypter aes = new AESEncrypter(); try { aes.decrypt(new FileInputStream(Global.getFileManager().getHomeDirFile("oauthkey.txt"))); } catch (FileNotFoundException e) { // File not found, so we'll just get empty strings anyway. } if (Global.getProxyValue("url").equals("")) { System.setProperty("http.proxyHost","") ; System.setProperty("http.proxyPort", "") ; System.setProperty("https.proxyHost","") ; System.setProperty("https.proxyPort", "") ; } else { // PROXY System.setProperty("http.proxyHost",Global.getProxyValue("url")) ; System.setProperty("http.proxyPort", Global.getProxyValue("port")) ; System.setProperty("https.proxyHost",Global.getProxyValue("url")) ; System.setProperty("https.proxyPort", Global.getProxyValue("port")) ; if (Global.getProxyValue("userid").equals("")) { Authenticator.setDefault(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(Global.getProxyValue("userid"),Global.getProxyValue("password").toCharArray()); } }); } } syncRunner.userStoreUrl = Global.userStoreUrl; syncRunner.noteStoreUrl = Global.noteStoreUrl; syncRunner.noteStoreUrlBase = Global.noteStoreUrlBase; String authString = aes.getString(); if (!authString.equals("")) { tokenizer.tokenize(authString); syncRunner.authToken = tokenizer.oauth_token; syncRunner.enConnect(); } Global.isConnected = syncRunner.isConnected; boolean autoLoginMessageFlag = false; if (!Global.isConnected) { OAuthWindow window = new OAuthWindow(logger); if (window.error) { setMessage(window.errorMessage); return; } window.exec(); if (window.error) { setMessage(window.errorMessage); return; } tokenizer.tokenize(window.response); if (tokenizer.oauth_token.equals("")) { setMessage(tr("Invalid authorization token received.")); return; } aes.setString(window.response); try { aes.encrypt(new FileOutputStream(Global.getFileManager().getHomeDirFile("oauthkey.txt"))); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } syncRunner.authToken = tokenizer.oauth_token; syncRunner.enConnect(); Global.isConnected = syncRunner.isConnected; autoLoginMessageFlag = true; } // Global.username = syncRunner.username; if (!Global.isConnected) return; setupOnlineMenu(); setupConnectMenuOptions(); // 初回ログイン時に自動ログインが無効だったら、有効化するか確認する if (autoLoginMessageFlag && !Global.automaticLogin()) { if (QMessageBox.question(this, tr("Confirmation"), tr("Are you sure you want to enable the auto-login feature?"), QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No) == StandardButton.Yes.value()) { Global.setAutomaticLogin(true); } } logger.log(logger.HIGH, "Leaving NeverNote.remoteConnect"); } private void setupConnectMenuOptions() { logger.log(logger.HIGH, "entering NeverNote.setupConnectMenuOptions"); if (!Global.isConnected) { menuBar.connectAction.setText(tr("Connect")); menuBar.connectAction.setToolTip(tr("Connect to Evernote")); menuBar.synchronizeAction.setEnabled(false); } else { menuBar.connectAction.setText(tr("Disconnect")); menuBar.connectAction.setToolTip(tr("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(); // ゴミ箱から元の画面に戻す。連想ノートリストをONに。 if (!rensoNoteListDock.isEnabled()) { rensoNoteListDock.setEnabled(true); } 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.parent().indexOfChild(item)); else { Global.containsFilter.select(item.parent().indexOfChild(item)); } } 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.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Created && w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Since) return Global.createdSinceFilter; if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Created && w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Before) return Global.createdBeforeFilter; if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.LastModified && w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Since) return Global.changedSinceFilter; if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.LastModified && w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Before) return Global.changedBeforeFilter; } return null; } // Show/Hide attribute search window @SuppressWarnings("unused") 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 (QApplication.mouseButtons().isSet(MouseButton.RightButton)) { // 選択されたノートのguidをselectedNoteGUIDsにセット List<QModelIndex> selections = noteTableView.selectionModel().selectedRows(); if(selections.size() > 0){ selectedNoteGUIDs.clear(); for(int i = 0; i < selections.size(); i++){ int row = selections.get(i).row(); QModelIndex index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition); SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index); selectedNoteGUIDs.add((String) ix.values().toArray()[0]); } } return; } // If we have more than one selection, then set the merge note action to true. List<QModelIndex> selections = noteTableView.selectionModel().selectedRows(); if (selections.size() > 1) menuBar.noteMergeAction.setEnabled(true); else menuBar.noteMergeAction.setEnabled(false); // If the ctrl key is pressed, then they are selecting multiple // entries and we don't want to change the currently viewed note. // Shiftキーを押しながらの場合の処理も追加 if ((QApplication.keyboardModifiers().isSet(KeyboardModifier.ControlModifier) || QApplication.keyboardModifiers().isSet(KeyboardModifier.ShiftModifier)) && QApplication.mouseButtons().isSet(MouseButton.LeftButton)){ selectedNoteGUIDs.clear(); for (int i=0; i<selections.size(); i++) { int row = selections.get(i).row(); QModelIndex index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition); SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index); selectedNoteGUIDs.add((String)ix.values().toArray()[0]); } return; } // IFIXED 恐らく不要なのでコメントアウト // if (historyGuids.size() == 0) { // historyGuids.add(currentNoteGuid); // historyPosition = 1; // } noteTableView.showColumn(Global.noteTableGuidPosition); if (!Global.isColumnVisible("guid")) 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 (currentNoteGuid != null && !currentNoteGuid.equals("") && !Global.showDeleted) { menuBar.noteAddNewTab.setEnabled(true); } 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<selections.size(); i++) { int row = selections.get(i).row(); if (row == 0) upButton.setEnabled(false); else upButton.setEnabled(true); if (row < listManager.getNoteTableModel().rowCount()-1) downButton.setEnabled(true); else downButton.setEnabled(false); index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition); SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index); currentNoteGuid = (String)ix.values().toArray()[0]; selectedNoteGUIDs.add(currentNoteGuid); } } nextButton.setEnabled(true); prevButton.setEnabled(true); int currentIndex = tabBrowser.currentIndex(); ArrayList<String> histGuids = historyGuids.get(currentIndex); int histPosition = historyPosition.get(currentIndex); boolean fromHist = fromHistory.get(currentIndex); if (!fromHist) { int endPosition = histGuids.size() - 1; for (int j = histPosition; j <= endPosition; j++) { histGuids.remove(histGuids.size() - 1); } histGuids.add(currentNoteGuid); historyPosition.put(currentIndex, histGuids.size()); histPosition = histGuids.size(); } if (histPosition <= 1){ prevButton.setEnabled(false); } if (histPosition == histGuids.size()) nextButton.setEnabled(false); fromHistory.put(currentIndex, false); fromHist = false; scrollToGuid(currentNoteGuid); refreshEvernoteNote(true); if (currentNoteGuid != null && !currentNoteGuid.equals("")) { if (!Global.showDeleted) { // ゴミ箱じゃなければ addBrowseHistory(); } } // 連想ノートリストを更新 rensoNoteListDock.getRensoNoteList().refreshRensoNoteList(currentNoteGuid); waitCursor(false); logger.log(logger.HIGH, "Leaving NeverNote.noteTableSelection"); } // 複数ノートの同時閲覧履歴をデータベースに保存 private void addBrowseHistory() { // このノートと他のタブウィンドウノートの関連性を内部データベースのHistoryテーブルに登録 if (tabWindows.size() >= 2) { Iterator<Integer> it = tabWindows.keySet().iterator(); while (it.hasNext()) { int tabIndex = it.next(); String nextGuid = ((TabBrowse) tabBrowser.widget(tabIndex)).getBrowserWindow().getNote().getGuid(); // guid1=guid2のデータは登録しない if (!currentNoteGuid.equals(nextGuid)) { conn.getHistoryTable().addHistory("browse", currentNoteGuid, nextGuid); } } } // このノートと他の外部ウィンドウノートの関連性を内部データベースのHistoryテーブルに登録 if (externalWindows.size() >= 1) { Iterator<String> it = externalWindows.keySet().iterator(); while (it.hasNext()) { String nextGuid = it.next(); // guid1=guid2のデータは登録しない if (!currentNoteGuid.equals(nextGuid)) { conn.getHistoryTable().addHistory("browse", currentNoteGuid, nextGuid); } } } } // Trigger a refresh when the note db has been updated private void noteIndexUpdated(boolean reload) { logger.log(logger.HIGH, "Entering NeverNote.noteIndexUpdated"); saveNote(); refreshEvernoteNoteList(); logger.log(logger.HIGH, "Calling note table reload in NeverNote.noteIndexUpdated() - "+reload); noteTableView.load(reload); if (currentNoteGuid == null || currentNoteGuid.equals("")) { int pos; if (noteTableView.proxyModel.sortOrder() == SortOrder.AscendingOrder) pos = noteTableView.proxyModel.rowCount(); else pos = 1; if (noteTableView.proxyModel.rowCount() == 0) pos = 0; if (pos>0) { QModelIndex i = noteTableView.proxyModel.index(pos-1, Global.noteTableGuidPosition); if (i!=null) { currentNoteGuid = (String)i.data(); } } } if (!noteTableView.isColumnHidden(Global.noteTableGuidPosition)) showColumns(); 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<String>(); selectedNoteGUIDs.clear(); // clear out old entries String saveCurrentNoteGuid = new String(); String tempNoteGuid = new String(); int currentIndex = tabBrowser.currentIndex(); ArrayList<String> histGuids = historyGuids.get(currentIndex); histGuids.clear(); historyPosition.put(currentIndex, 0); prevButton.setEnabled(false); nextButton.setEnabled(false); if (currentNoteGuid == null) currentNoteGuid = new String(); //determine current note guid for (Note note : listManager.getNoteIndex()) { tempNoteGuid = note.getGuid(); if (currentNoteGuid.equals(tempNoteGuid)) { saveCurrentNoteGuid = tempNoteGuid; } } if (listManager.getNoteIndex().size() == 0) { currentNoteGuid = ""; currentNote = null; browserWindow.clear(); browserWindow.setDisabled(true); waitCursor(false); } if (Global.showDeleted && listManager.getNoteIndex().size() > 0 && saveCurrentNoteGuid.equals("")) { currentNoteGuid = listManager.getNoteIndex().get(0).getGuid(); saveCurrentNoteGuid = currentNoteGuid; refreshEvernoteNote(true); } if (!saveCurrentNoteGuid.equals("")) { refreshEvernoteNote(false); } else { currentNoteGuid = ""; } reloadTagTree(false); logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNoteList"); } // Called when the previous arrow button is clicked @SuppressWarnings("unused") private void previousViewedAction() { int currentIndex = tabBrowser.currentIndex(); ArrayList<String> histGuids = historyGuids.get(currentIndex); int histPosition = historyPosition.get(currentIndex); boolean fromHist = fromHistory.get(currentIndex); if (!prevButton.isEnabled()) return; if (histPosition == 0) return; histPosition--; historyPosition.put(currentIndex, histPosition); if (histPosition <= 0) return; String historyGuid = histGuids.get(histPosition - 1); fromHistory.put(currentIndex, true); fromHist = true; for (int i = 0; i < noteTableView.model().rowCount(); i++) { QModelIndex modelIndex = noteTableView.model().index(i, Global.noteTableGuidPosition); if (modelIndex != null) { SortedMap<Integer, Object> 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; int currentIndex = tabBrowser.currentIndex(); ArrayList<String> histGuids = historyGuids.get(currentIndex); int histPosition = historyPosition.get(currentIndex); boolean fromHist = fromHistory.get(currentIndex); String historyGuid = histGuids.get(histPosition); histPosition++; historyPosition.put(currentIndex, histPosition); fromHistory.put(currentIndex, true); fromHist = true; for (int i = 0; i < noteTableView.model().rowCount(); i++) { QModelIndex modelIndex = noteTableView.model().index(i, Global.noteTableGuidPosition); if (modelIndex != null) { SortedMap<Integer, Object> 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<QModelIndex> 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<QModelIndex> selections = noteTableView.selectionModel().selectedRows(); int row = selections.get(0).row(); int max = listManager.getNoteTableModel().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<String> tags) { logger.log(logger.HIGH, "Entering NeverNote.updateListTags"); StringBuffer tagBuffer = new StringBuffer(); for (int i=0; i<tags.size(); i++) { tagBuffer.append(tags.get(i)); if (i<tags.size()-1) tagBuffer.append(", "); } for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) { QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition); if (modelIndex != null) { SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex); String tableGuid = (String)ix.values().toArray()[0]; if (tableGuid.equals(guid)) { listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition,tagBuffer.toString()); listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false"); noteTableView.proxyModel.invalidate(); return; } } } logger.log(logger.HIGH, "Leaving NeverNote.updateListTags"); } // 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<listManager.getNoteTableModel().rowCount(); i++) { //QModelIndex modelIndex = noteTableView.proxyModel.index(i, Global.noteTableGuidPosition); QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition); if (modelIndex != null) { SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex); String tableGuid = (String)ix.values().toArray()[0]; if (tableGuid.equals(guid)) { listManager.getNoteTableModel().setData(i, Global.noteTableAuthorPosition,author); listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false"); noteTableView.proxyModel.invalidate(); return; } } } logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor"); } private void updateListNoteNotebook(String guid, String notebook) { logger.log(logger.HIGH, "Entering NeverNote.updateListNoteNotebook"); listManager.getNoteTableModel().updateNoteSyncStatus(guid, false); logger.log(logger.HIGH, "Leaving NeverNote.updateListNoteNotebook"); } // 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<listManager.getNoteTableModel().rowCount(); i++) { //QModelIndex modelIndex = noteTableView.proxyModel.index(i, Global.noteTableGuidPosition); QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition); if (modelIndex != null) { // SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex); SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex); String tableGuid = (String)ix.values().toArray()[0]; if (tableGuid.equals(guid)) { listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false"); listManager.getNoteTableModel().setData(i, Global.noteTableSourceUrlPosition,url); noteTableView.proxyModel.invalidate(); return; } } } logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor"); } @SuppressWarnings("unused") private void updateListGuid(String oldGuid, String newGuid) { logger.log(logger.HIGH, "Entering NeverNote.updateListTitle"); for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) { QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition); if (modelIndex != null) { SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex); String tableGuid = (String)ix.values().toArray()[0]; if (tableGuid.equals(oldGuid)) { listManager.getNoteTableModel().setData(i, Global.noteTableGuidPosition,newGuid); //listManager.getNoteTableModel().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<listManager.getNoteIndex().size(); j++) { if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) { String newName = listManager.getTagNamesForNote(listManager.getNoteIndex().get(j)); for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) { QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition); if (modelIndex != null) { SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex); String noteGuid = (String)ix.values().toArray()[0]; if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) { listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition, newName); i=listManager.getNoteTableModel().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<listManager.getNoteIndex().size(); j++) { if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) { for (int i=listManager.getNoteIndex().get(j).getTagGuids().size()-1; i>=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<listManager.getNoteTableModel().rowCount(); i++) { QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition); if (modelIndex != null) { SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex); String noteGuid = (String)ix.values().toArray()[0]; if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) { listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition, newName); i=listManager.getNoteTableModel().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<listManager.getNoteTableModel().rowCount(); i++) { QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableNotebookPosition); if (modelIndex != null) { SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex); String tableName = (String)ix.values().toArray()[0]; if (tableName.equalsIgnoreCase(oldName)) { listManager.getNoteTableModel().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<listManager.getNoteTableModel().rowCount(); i++) { QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition); if (modelIndex != null) { SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex); String tableGuid = (String)ix.values().toArray()[0]; if (tableGuid.equals(guid)) { listManager.getNoteTableModel().setData(i, Global.noteTableCreationPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat())); noteTableView.proxyModel.invalidate(); 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<listManager.getNoteTableModel().rowCount(); i++) { QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition); if (modelIndex != null) { SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex); String tableGuid = (String)ix.values().toArray()[0]; if (tableGuid.equals(guid)) { listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false"); listManager.getNoteTableModel().setData(i, Global.noteTableSubjectDatePosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat())); noteTableView.proxyModel.invalidate(); return; } } } logger.log(logger.HIGH, "Leaving NeverNote.updateListDateCreated"); } private void updateListDateChanged(String guid, QDateTime date) { logger.log(logger.HIGH, "Entering NeverNote.updateListDateChanged"); for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) { QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition); if (modelIndex != null) { SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex); String tableGuid = (String)ix.values().toArray()[0]; if (tableGuid.equals(guid)) { listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false"); listManager.getNoteTableModel().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()); updateListDateChanged(currentNoteGuid, date); logger.log(logger.HIGH, "Leaving NeverNote.updateListDateChanged"); } // Redo scroll private void scrollToCurrentGuid() { //scrollToGuid(currentNoteGuid); List<QModelIndex> 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 the current GUID in tthe list. // 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<listManager.getNoteIndex().size(); i++) { if (!listManager.getNoteIndex().get(i).isActive()) { currentNote = listManager.getNoteIndex().get(i); currentNoteGuid = currentNote.getGuid(); i = listManager.getNoteIndex().size(); } } } if (!currentNote.isActive() && !Global.showDeleted) { for (int i=0; i<listManager.getNoteIndex().size(); i++) { if (listManager.getNoteIndex().get(i).isActive()) { currentNote = listManager.getNoteIndex().get(i); currentNoteGuid = currentNote.getGuid(); i = listManager.getNoteIndex().size(); } } } QModelIndex index; for (int i=0; i<noteTableView.model().rowCount(); i++) { index = noteTableView.model().index(i, Global.noteTableGuidPosition); if (currentNoteGuid.equals(index.data())) { // noteTableView.selectionModel().blockSignals(true); noteTableView.selectRow(i); // noteTableView.selectionModel().blockSignals(false); noteTableView.scrollTo(index, ScrollHint.EnsureVisible); // This should work, but it doesn't i=listManager.getNoteTableModel().rowCount(); } } noteTableView.repaint(); } // Show/Hide columns private void showColumns() { noteTableView.setColumnHidden(Global.noteTableCreationPosition, !Global.isColumnVisible("dateCreated")); noteTableView.setColumnHidden(Global.noteTableChangedPosition, !Global.isColumnVisible("dateChanged")); noteTableView.setColumnHidden(Global.noteTableSubjectDatePosition, !Global.isColumnVisible("dateSubject")); noteTableView.setColumnHidden(Global.noteTableAuthorPosition, !Global.isColumnVisible("author")); noteTableView.setColumnHidden(Global.noteTableSourceUrlPosition, !Global.isColumnVisible("sourceUrl")); noteTableView.setColumnHidden(Global.noteTableTagPosition, !Global.isColumnVisible("tags")); noteTableView.setColumnHidden(Global.noteTableNotebookPosition, !Global.isColumnVisible("notebook")); noteTableView.setColumnHidden(Global.noteTableSynchronizedPosition, !Global.isColumnVisible("synchronized")); noteTableView.setColumnHidden(Global.noteTableGuidPosition, !Global.isColumnVisible("guid")); noteTableView.setColumnHidden(Global.noteTableThumbnailPosition, !Global.isColumnVisible("thumbnail")); noteTableView.setColumnHidden(Global.noteTableTitlePosition, !Global.isColumnVisible("title")); noteTableView.setColumnHidden(Global.noteTablePinnedPosition, !Global.isColumnVisible("pinned")); } // Title color has changed @SuppressWarnings("unused") private void titleColorChanged(Integer color) { logger.log(logger.HIGH, "Entering NeverNote.titleColorChanged"); setNoteDirty(); QColor backgroundColor = new QColor(); QColor foregroundColor = new QColor(QColor.black); backgroundColor.setRgb(color); if (backgroundColor.rgb() == QColor.black.rgb() || backgroundColor.rgb() == QColor.blue.rgb()) foregroundColor.setRgb(QColor.white.rgb()); if (selectedNoteGUIDs.size() == 0) selectedNoteGUIDs.add(currentNoteGuid); for (int j=0; j<selectedNoteGUIDs.size(); j++) { for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) { QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition); if (modelIndex != null) { SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex); String tableGuid = (String)ix.values().toArray()[0]; if (tableGuid.equals(selectedNoteGUIDs.get(j))) { for (int k=0; k<Global.noteTableColumnCount; k++) { listManager.getNoteTableModel().setData(i, k, backgroundColor, Qt.ItemDataRole.BackgroundRole); listManager.getNoteTableModel().setData(i, k, foregroundColor, Qt.ItemDataRole.ForegroundRole); listManager.updateNoteTitleColor(selectedNoteGUIDs.get(j), backgroundColor.rgb()); } i=listManager.getNoteTableModel().rowCount(); } } } } logger.log(logger.HIGH, "Leaving NeverNote.titleColorChanged"); } // A note has been pinned or unpinned @SuppressWarnings("unused") private void notePinned() { logger.log(logger.EXTREME, "Entering NeverNote.notePinned()"); setNoteDirty(); for (int j=0; j<selectedNoteGUIDs.size(); j++) { NoteMetadata meta = listManager.getNoteMetadata().get(selectedNoteGUIDs.get(j)); boolean pinned = !meta.isPinned(); meta.setPinned(pinned); // Toggle the pinned/unpinned // Update the list & table listManager.updateNoteMetadata(meta); noteTableView.proxyModel.addGuid(selectedNoteGUIDs.get(j), meta); } logger.log(logger.EXTREME, "Leaving NeverNote.notePinned()"); } // Wide list was chosen public void narrowListView() { saveNoteColumnPositions(); saveNoteIndexWidth(); saveWindowState(); int sortCol = noteTableView.proxyModel.sortColumn(); int sortOrder = noteTableView.proxyModel.sortOrder().value(); Global.setSortColumn(sortCol); Global.setSortOrder(sortOrder); Global.setListView(Global.View_List_Narrow); menuBar.wideListView.blockSignals(true); menuBar.narrowListView.blockSignals(true); menuBar.wideListView.setChecked(false); menuBar.narrowListView.setChecked(true); menuBar.wideListView.blockSignals(false); menuBar.narrowListView.blockSignals(false); mainLeftRightSplitter.addWidget(noteTableView); mainLeftRightSplitter.addWidget(tabBrowser); restoreWindowState(false); noteTableView.repositionColumns(); noteTableView.resizeColumnWidths(); noteTableView.resizeRowHeights(); sortCol = Global.getSortColumn(); sortOrder = Global.getSortOrder(); noteTableView.proxyModel.blocked = true; noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder)); noteTableView.proxyModel.blocked = false; showColumns(); noteTableView.load(false); refreshEvernoteNote(true); scrollToCurrentGuid(); } public void wideListView() { int sortCol = noteTableView.proxyModel.sortColumn(); int sortOrder = noteTableView.proxyModel.sortOrder().value(); Global.setSortColumn(sortCol); Global.setSortOrder(sortOrder); saveWindowState(); saveNoteColumnPositions(); saveNoteIndexWidth(); Global.setListView(Global.View_List_Wide); menuBar.wideListView.blockSignals(true); menuBar.narrowListView.blockSignals(true); menuBar.wideListView.setChecked(true); menuBar.narrowListView.setChecked(false); menuBar.wideListView.blockSignals(false); menuBar.narrowListView.blockSignals(false); browserIndexSplitter.setVisible(true); browserIndexSplitter.addWidget(noteTableView); browserIndexSplitter.addWidget(tabBrowser); restoreWindowState(false); noteTableView.repositionColumns(); noteTableView.resizeColumnWidths(); noteTableView.resizeRowHeights(); sortCol = Global.getSortColumn(); sortOrder = Global.getSortOrder(); noteTableView.proxyModel.blocked = true; noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder)); noteTableView.proxyModel.blocked = false; showColumns(); noteTableView.load(false); scrollToCurrentGuid(); } // Sort order for the notebook has changed public void tableSortOrderChanged(Integer column, Integer order) { // Find what notebook (if any) is selected. We ignore stacks & the "All Notebooks". List<QTreeWidgetItem> selectedNotebook = notebookTree.selectedItems(); if (selectedNotebook.size() > 0 && !selectedNotebook.get(0).text(0).equalsIgnoreCase("All Notebooks") && !selectedNotebook.get(0).text(2).equalsIgnoreCase("STACK")) { QTreeWidgetItem currentSelectedNotebook = selectedNotebook.get(0); String notebook; notebook = currentSelectedNotebook.text(2); conn.getNotebookTable().setSortOrder(notebook, column, order); } } //*************************************************************** @SuppressWarnings("unused") private void evernoteLinkClick(String syncGuid, String locGuid) { String guid = null; if (conn.getNoteTable().guidExists(syncGuid)) { guid = syncGuid; } else { // If we didn't find it via the synchronized guid, look under the local guid // Iwe don't find it there, look to see if the GUID is posted under the local GUID, but was // later synchronized (that causes the guid to change so we need to find the new one). if (conn.getNoteTable().guidExists(locGuid)) guid = locGuid; else guid = conn.getNoteTable().findAlternateGuid(locGuid); } if (guid != null) { openExternalEditor(guid); return; } //If we've gotten this far, we can't find the note QMessageBox.information(this, tr("Note Not Found"), tr("Sorry, but I can't"+ " seem to find that note.")); } //*************************************************************** //*************************************************************** //** External editor window functions //*************************************************************** //*************************************************************** private void listDoubleClick() { saveNote(); openExternalEditor(currentNoteGuid); } private void openExternalEditor(String guid) { if (externalWindows.containsKey(guid)) { externalWindows.get(guid).raise(); return; } Note note = conn.getNoteTable().getNote(guid, true, true, false, true, true); // We have a new external editor to create QIcon appIcon = new QIcon(iconPath+"nevernote.png"); ExternalBrowse newBrowser = new ExternalBrowse(conn, cbObserver); newBrowser.setWindowIcon(appIcon); externalWindows.put(guid, newBrowser); showEditorButtons(newBrowser.getBrowserWindow()); loadNoteBrowserInformation(newBrowser.getBrowserWindow(), guid, note); setupBrowserWindowListeners(newBrowser.getBrowserWindow(), false); newBrowser.windowClosing.connect(this, "externalWindowClosing(String)"); //newBrowser.getBrowserWindow().noteSignal.titleChanged.connect(this, "externalWindowTitleEdited(String, String)"); newBrowser.getBrowserWindow().noteSignal.tagsChanged.connect(this, "externalWindowTagsEdited(String, List)"); newBrowser.contentsChanged.connect(this, "saveNoteExternalBrowser(String, String, Boolean, BrowserWindow)"); newBrowser.getBrowserWindow().blockApplication.connect(this, "blockApplication(BrowserWindow)"); newBrowser.getBrowserWindow().unblockApplication.connect(this, "unblockApplication()"); browserWindow.noteSignal.tagsChanged.connect(newBrowser, "updateTags(String, List)"); browserWindow.noteSignal.titleChanged.connect(newBrowser, "updateTitle(String, String)"); browserWindow.noteSignal.notebookChanged.connect(newBrowser, "updateNotebook(String, String)"); newBrowser.show(); } @SuppressWarnings({ "rawtypes", "unused" }) private void externalWindowTagsEdited(String guid, List values) { StringBuffer line = new StringBuffer(100); for (int i=0; i<values.size(); i++) { if (i>0) line.append(Global.tagDelimeter+" "); line.append(values.get(i)); } if (guid.equals(currentNoteGuid)) { browserWindow.setTag(line.toString()); } } @SuppressWarnings("unused") private void externalWindowClosing(String guid) { externalWindows.remove(guid); } // *************************************************************** // *************************************************************** // ** タブウィンドウの機能 // *************************************************************** // *************************************************************** @SuppressWarnings("unused") private void openNewTab() { saveNote(); // selectedNoteGUIDsをディープコピー List<String> copySelected = new ArrayList<String>(selectedNoteGUIDs); for (int i=0; i < copySelected.size() ; i++) { openTabEditor(copySelected.get(i)); } } // 連想ノートリストから新しいタブで開く @SuppressWarnings("unused") private void openNewTabFromRNL(){ if(rensoNotePressedItemGuid != null){ String prevCurrentNoteGuid = new String(currentNoteGuid); saveNote(); openTabEditor(rensoNotePressedItemGuid); // 連想ノートリストアイテムクリック操作を記録 conn.getHistoryTable().addHistory("rensoItemClick", prevCurrentNoteGuid, rensoNotePressedItemGuid); } } private void openTabEditor(String guid) { Note note = conn.getNoteTable().getNote(guid, true, true, false, true, true); // 新しいタブエディタを作成 TabBrowse newBrowser = new TabBrowse(conn, tabBrowser, cbObserver); showEditorButtons(newBrowser.getBrowserWindow()); String noteTitle = note.getTitle(); int index = tabBrowser.addNewTab(newBrowser, noteTitle); tabWindows.put(index, newBrowser); noteDirty.put(index, false); // noteTableViewの選択を変更するとselectionChangedが発生してしまうので一度切断 noteTableView.selectionModel().selectionChanged.disconnect(this, "noteTableSelection()"); loadNoteBrowserInformation(newBrowser.getBrowserWindow(), guid, note); // 再接続 noteTableView.selectionModel().selectionChanged.connect(this, "noteTableSelection()"); setupBrowserWindowListeners(newBrowser.getBrowserWindow(), false); // ExtendedInformationを必要があれば表示する toggleNoteInformation(); // Sourceを必要があれば表示する viewSource(); // EditorButtonsBarを必要があれば表示する toggleEditorButtonBar(); // 履歴記録のハッシュマップを初期化 ArrayList<String> histGuids = new ArrayList<String>(); historyGuids.put(index, histGuids); historyPosition.put(index, 0); fromHistory.put(index, false); // 履歴に今開いたノートを追加 histGuids.add(guid); historyPosition.put(index, histGuids.size()); tabBrowser.setCurrentIndex(index); if (guid != null && !guid.equals("")) { if (!Global.showDeleted) { // ゴミ箱じゃなければ addBrowseHistory(); } } } // タブが閉じられた @SuppressWarnings("unused") private void tabCloseRequested(int index) { tabWindowClosing((TabBrowse)tabBrowser.widget(index)); } // タブが閉じられた private void tabWindowClosing(TabBrowse tab) { // タブが1つしかなかったら閉じない if (tabBrowser.count() <= 1) { return; } int index = tabBrowser.indexOf(tab); // String guid = tab.getBrowserWindow().getNote().getGuid(); // String content = tab.getBrowserWindow().getContent(); BrowserWindow browser = tab.getBrowserWindow(); // // ノートが変更されていたら保存 // if (tab.getNoteDirty()) { // saveNoteTabBrowser(guid, content, true, browser); // } // シグナル切断 browser.noteSignal.tagsChanged.disconnect(); browser.noteSignal.titleChanged.disconnect(); browser.noteSignal.noteChanged.disconnect(); browser.noteSignal.notebookChanged.disconnect(); browser.noteSignal.createdDateChanged.disconnect(); browser.noteSignal.alteredDateChanged.disconnect(); // ノートを削除 tabBrowser.removeTab(index); tabWindows.remove(index); noteDirty.remove(index); inkNote.remove(index); readOnly.remove(index); // 履歴記録のハッシュマップを削除 historyGuids.remove(index); historyPosition.remove(index); fromHistory.remove(index); // タブのインデックスを更新(削除によって空いた部分を詰める) for(int i = index ; tabWindows.containsKey(i + 1) ; i++){ // tabWindows TabBrowse nextTab = tabWindows.get(i + 1); tabWindows.put(i, nextTab); tabWindows.remove(i + 1); // noteDirty boolean isNoteDirty = noteDirty.get(i + 1); noteDirty.put(i, isNoteDirty); noteDirty.remove(i + 1); // inkNote boolean isInkNote = inkNote.get(i + 1); inkNote.put(i, isInkNote); inkNote.remove(i + 1); // readOnly boolean isReadOnly = readOnly.get(i + 1); readOnly.put(i, isReadOnly); readOnly.remove(i + 1); // historyGuids ArrayList<String> histGuids = historyGuids.get(i + 1); historyGuids.put(i, histGuids); historyGuids.remove(i + 1); // historyPosition int histPosition = historyPosition.get(i + 1); historyPosition.put(i, histPosition); historyPosition.remove(i + 1); // fromHistory boolean fromHist = fromHistory.get(i + 1); fromHistory.put(i, fromHist); fromHistory.remove(i + 1); } // タブが残り1つになったら、閉じるボタンを消す if (tabBrowser.count() == 1) { tabBrowser.hideTabCloseButton(0); } // タブの閉じるボタンを押すと、tabWindowClosingより先にtabWindowChangedが呼ばれてしまうので、手動で呼びなおす tabWindowChanged(tabBrowser.currentIndex()); } @SuppressWarnings("unused") private void noteAddNewTab() { saveNote(); // ノートを何も開いていないときは現在のタブにノート追加 if (currentNoteGuid == null || currentNoteGuid.equals("")) { addNote(); return; } // ノート追加前に開いていたノートとの関連性を記録するためにguidをとっておく TabBrowse prevTab = (TabBrowse)tabBrowser.currentWidget(); String prevTabGuid = null; if (prevTab.getBrowserWindow() != null && prevTab.getBrowserWindow().getNote() != null) { prevTabGuid = prevTab.getBrowserWindow().getNote().getGuid(); } openEmptyTabEditor(); addNote(); // 追加されたノートのguidを取得し、ノート追加操作履歴としてデータベースに登録 if (prevTabGuid != null && !prevTabGuid.equals("")) { TabBrowse addedTab = (TabBrowse)tabBrowser.currentWidget(); String addedTabGuid = addedTab.getBrowserWindow().getNote().getGuid(); if (addedTabGuid != null && !addedTabGuid.equals("")) { if (!prevTabGuid.equals(addedTabGuid)) { conn.getHistoryTable().addHistory("addNewNote", prevTabGuid, addedTabGuid); } } } } private void openEmptyTabEditor() { // 新しいタブエディタを作成 TabBrowse newBrowser = new TabBrowse(conn, tabBrowser, cbObserver); showEditorButtons(newBrowser.getBrowserWindow()); setupBrowserWindowListeners(newBrowser.getBrowserWindow(), false); int index = tabBrowser.addNewTab(newBrowser, ""); tabWindows.put(index, newBrowser); noteDirty.put(index, false); // ExtendedInformationを必要があれば表示する toggleNoteInformation(); // Sourceを必要があれば表示する viewSource(); // EditorButtonsBarを必要があれば表示する toggleEditorButtonBar(); // 履歴記録のハッシュマップを初期化 ArrayList<String> histGuids = new ArrayList<String>(); historyGuids.put(index, histGuids); historyPosition.put(index, 0); fromHistory.put(index, false); tabBrowser.setCurrentIndex(index); } //*************************************************************** //*************************************************************** //** These functions deal with Note specific things //*************************************************************** //*************************************************************** private void setNoteDirty() { for (String guid: selectedNoteGUIDs) { setNoteDirty(guid); } } private void setNoteDirty(String targetGuid) { logger.log(logger.EXTREME, "Entering NeverNote.setNoteDirty()"); // Find if the note is being edited externally. If it is, update it. if (externalWindows.containsKey(targetGuid)) { QTextCodec codec = QTextCodec.codecForName("UTF-8"); QByteArray unicode = codec.fromUnicode(browserWindow.getContent()); ExternalBrowse window = externalWindows.get(targetGuid); window.getBrowserWindow().setContent(unicode); } // 他のタブで同じノートを開いていないか探す。もしあったら、内容を更新する。 Collection<Integer> tabIndexes = tabWindows.keySet(); Iterator<Integer> indexIterator = tabIndexes.iterator(); for (TabBrowse tab: tabWindows.values()) { int index = indexIterator.next(); String guid = tab.getBrowserWindow().getNote().getGuid(); QTextCodec codec = QTextCodec.codecForName("UTF-8"); QByteArray unicode = codec.fromUnicode(browserWindow.getContent()); if (guid.equals(guid)) { if (index != tabBrowser.currentIndex()) { TabBrowse window = tabWindows.get(index); window.getBrowserWindow().setContent(unicode); } } } // ターゲットノートがタブで開かれていて、かつDirty = trueかどうかを取得する // If the note is dirty, then it is unsynchronized by default. int index = -1; boolean isNoteDirty = false; for (TabBrowse tab: tabWindows.values()) { if (tab.getBrowserWindow().getNote().getGuid().equals(targetGuid)) { index = tabBrowser.indexOf(tab); isNoteDirty = noteDirty.get(index); break; } } if (isNoteDirty) { return; } // Set the note as dirty and check if its status is synchronized in the display table // まだダーティでなく、かつタブで開かれている場合にnoteDirty = trueにする if (index >= 0) { noteDirty.put(index, true); } if (listManager.getNoteMetadata().containsKey(targetGuid) && listManager.getNoteMetadata().get(targetGuid).isDirty()) { return; } // If this wasn't already marked as unsynchronized, then we need to update the table listManager.getNoteTableModel().updateNoteSyncStatus(targetGuid, false); // listManager.getUnsynchronizedNotes().add(targetGuid); for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) { QModelIndex modelIndex = listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition); if (modelIndex != null) { SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex); String tableGuid = (String)ix.values().toArray()[0]; if (tableGuid.equals(targetGuid)) { listManager.getNoteTableModel().proxyModel.setData(i, Global.noteTableSynchronizedPosition, "false"); return; } } } logger.log(logger.EXTREME, "Leaving NeverNote.setNoteDirty()"); } @SuppressWarnings("unused") private void saveNoteExternalBrowser(String guid, String content, Boolean save, BrowserWindow browser) { QTextCodec codec = QTextCodec.codecForName("UTF-8"); QByteArray unicode = codec.fromUnicode(content); noteCache.remove(guid); noteCache.put(guid, unicode.toString()); if (guid.equals(currentNoteGuid)) { int index = tabBrowser.currentIndex(); noteDirty.put(index, true); browserWindow.setContent(unicode); } if (save) { thumbnailRunner.addWork("GENERATE "+ guid); saveNote(guid, browser); } } // private void saveNoteTabBrowser(String guid, String content, Boolean save, // BrowserWindow browser) { // QTextCodec codec = QTextCodec.codecForName("UTF-8"); // QByteArray unicode = codec.fromUnicode(content); // noteCache.remove(guid); // noteCache.put(guid, unicode.toString()); // if (save) { // thumbnailRunner.addWork("GENERATE " + guid); // saveNote(guid, browser); // } // } private void saveNote() { // すべてのタブに対して、Dirtyを確認し、trueならセーブする Collection<Integer> dirtyIndex = noteDirty.keySet(); Iterator<Integer> indexIterator = dirtyIndex.iterator(); for (boolean isNoteDirty: noteDirty.values()) { int index = indexIterator.next(); if (isNoteDirty) { if (index < 0) { return; } BrowserWindow b = tabWindows.get(index).getBrowserWindow(); String guid = b.getNote().getGuid(); saveNote(guid, b); thumbnailRunner.addWork("GENERATE "+ guid); noteDirty.put(index, false); } } } private void saveNote(String guid, BrowserWindow window) { logger.log(logger.EXTREME, "Inside NeverNote.saveNote()"); waitCursor(true); logger.log(logger.EXTREME, "Saving to cache"); QTextCodec codec = QTextCodec.codecForLocale(); // QTextDecoder decoder = codec.makeDecoder(); codec = QTextCodec.codecForName("UTF-8"); QByteArray unicode = codec.fromUnicode(window.getContent()); noteCache.put(guid, unicode.toString()); logger.log(logger.EXTREME, "updating list manager"); listManager.updateNoteContent(guid, window.getContent()); logger.log(logger.EXTREME, "Updating title"); listManager.updateNoteTitle(guid, window.getTitle()); updateListDateChanged(); logger.log(logger.EXTREME, "Looking through note index for refreshed note"); for (int i=0; i<listManager.getNoteIndex().size(); i++) { if (listManager.getNoteIndex().get(i).getGuid().equals(guid)) { currentNote = listManager.getNoteIndex().get(i); i = listManager.getNoteIndex().size(); } } waitCursor(false); } // Get a note from Evernote (and put it in the browser) private void refreshEvernoteNote(boolean reload) { logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNote"); if (Global.disableViewing) { browserWindow.setEnabled(false); return; } inkNote.put(tabBrowser.currentIndex(), false); readOnly.put(tabBrowser.currentIndex(), false); if (Global.showDeleted || currentNoteGuid == null || currentNoteGuid.equals("")) { readOnly.put(tabBrowser.currentIndex(), true); } Global.cryptCounter =0; if (readOnly.get(tabBrowser.currentIndex())) { browserWindow.setReadOnly(true); } if (!reload) return; waitCursor(true); browserWindow.loadingData(true); currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true); if (currentNote == null) { waitCursor(false); return; } tabBrowser.setTabTitle(tabBrowser.currentIndex(), currentNote.getTitle()); loadNoteBrowserInformation(browserWindow, currentNoteGuid, currentNote); } private void loadNoteBrowserInformation(BrowserWindow browser, String guid, Note note) { NoteFormatter formatter = new NoteFormatter(logger, conn, tempFiles); formatter.setNote(note, Global.pdfPreview()); formatter.setHighlight(listManager.getEnSearch()); QByteArray js; int tabIndex = -1; // 対象のタブインデックスを取得 for (TabBrowse tab: tabWindows.values()) { if (tab.getBrowserWindow() == browser) { tabIndex = tabBrowser.indexOf(tab); break; } } if (!noteCache.containsKey(guid)) { js = new QByteArray(); // We need to prepend the note with <HEAD></HEAD> or encoded characters are ugly js.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"); js.append("<style type=\"text/css\">.en-crypt-temp { border-collapse:collapse; border-style:solid; border-color:blue; padding:0.0mm 0.0mm 0.0mm 0.0mm; }</style>"); js.append("<style type=\"text/css\">en-hilight { background-color: rgb(255,255,0) }</style>"); js.append("<style> img { height:auto; width:auto; max-height:auto; max-width:100%; }</style>"); if (Global.displayRightToLeft()) js.append("<style> body { direction:rtl; }</style>"); js.append("<style type=\"text/css\">en-spell { text-decoration: none; border-bottom: dotted 1px #cc0000; }</style>"); js.append("</head>"); formatter.setNote(note, Global.pdfPreview()); js.append(formatter.rebuildNoteHTML()); js.append("</HTML>"); js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml.dtd'>", ""); js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml2.dtd'>", ""); js.replace("<?xml version='1.0' encoding='UTF-8'?>", ""); // if (Global.enableHTMLEntitiesFix) { // browser.getBrowser().setContent(new QByteArray(StringEscapeUtils.unescapeHtml(js.toString()))); // } else browser.setContent(js); noteCache.put(guid, js.toString()); if (formatter.resourceError) resourceErrorMessage(tabIndex); if (formatter.formatError) { waitCursor(false); QMessageBox.information(this, tr("Error"), tr("NeighborNote had issues formatting this note." + " To protect your data this note is being marked as read-only.")); waitCursor(true); } if (tabIndex >= 0) { readOnly.put(tabIndex, formatter.readOnly); inkNote.put(tabIndex, formatter.inkNote); } if (tabIndex >= 0 && readOnly.get(tabIndex)) { readOnlyCache.put(guid, true); } if (tabIndex >= 0 && inkNote.get(tabIndex)) { inkNoteCache.put(guid, true); } } else { logger.log(logger.HIGH, "Note content is being pulled from the cache"); String cachedContent = formatter.modifyCachedTodoTags(noteCache.get(guid)); js = new QByteArray(cachedContent); browser.setContent(js); if (readOnlyCache.containsKey(guid) && tabIndex >= 0) { readOnly.put(tabIndex, true); } else { readOnly.put(tabIndex, false); } if (inkNoteCache.containsKey(guid) && tabIndex >= 0) { inkNote.put(tabIndex, true); } else { inkNote.put(tabIndex, false); } } if (conn.getNoteTable().isThumbnailNeeded(guid)) { thumbnailHTMLReady(guid, js, Global.calculateThumbnailZoom(js.toString())); } if (tabIndex >= 0 && (readOnly.get(tabIndex) || inkNote.get(tabIndex) || (note.getAttributes() != null && note.getAttributes().getContentClass() != null && note.getAttributes().getContentClass() != ""))) browser.getBrowser().page().setContentEditable(false); // We don't allow editing of ink notes else browser.getBrowser().page().setContentEditable(true); if (tabIndex >= 0) { browser.setReadOnly(readOnly.get(tabIndex)); deleteButton.setEnabled(!readOnly.get(tabIndex)); tagButton.setEnabled(!readOnly.get(tabIndex)); menuBar.noteDelete.setEnabled(!readOnly.get(tabIndex)); menuBar.noteTags.setEnabled(!readOnly.get(tabIndex)); } browser.setNote(note); if (note != null && note.getNotebookGuid() != null && conn.getNotebookTable().isLinked(note.getNotebookGuid())) { deleteButton.setEnabled(false); menuBar.notebookDeleteAction.setEnabled(false); } else { deleteButton.setEnabled(true); menuBar.notebookDeleteAction.setEnabled(true); } // Build a list of non-closed notebooks List<Notebook> nbooks = new ArrayList<Notebook>(); for (int i=0; i<listManager.getNotebookIndex().size(); i++) { boolean found=false; for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) { if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid())) found = true; } if (!found) nbooks.add(listManager.getNotebookIndex().get(i)); } browser.setTitle(note.getTitle()); browser.setTag(getTagNamesForNote(note)); browser.setAuthor(note.getAttributes().getAuthor()); browser.setAltered(note.getUpdated()); browser.setCreation(note.getCreated()); if (note.getAttributes().getSubjectDate() > 0) browser.setSubjectDate(note.getAttributes().getSubjectDate()); else browser.setSubjectDate(note.getCreated()); browser.setUrl(note.getAttributes().getSourceURL()); FilterEditorTags tagFilter = new FilterEditorTags(conn, logger); List<Tag> tagList = tagFilter.getValidTags(note); browser.setAllTags(tagList); browser.setCurrentTags(note.getTagNames()); for (TabBrowse tab: tabWindows.values()) { if (tab.getBrowserWindow().getNote().getGuid().equals(guid)) { int index = tabBrowser.indexOf(tab); noteDirty.put(index, false); break; } } scrollToGuid(guid); browser.loadingData(false); if (thumbnailViewer.isActiveWindow()) thumbnailView(); FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger); browser.setNotebookList(notebookFilter.getValidNotebooks(note, listManager.getNotebookIndex())); waitCursor(false); logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNote"); } @SuppressWarnings("unused") private void toggleNoteAttributes() { menuBar.noteAttributes.setChecked(!menuBar.noteAttributes.isChecked()); toggleNoteInformation(); } // Save a generated thumbnail private void toggleNoteInformation() { logger.log(logger.HIGH, "Entering NeverNote.toggleNoteInformation"); boolean isChecked = menuBar.noteAttributes.isChecked(); for(int i = 0; i < tabBrowser.count(); i++){ BrowserWindow browser = ((TabBrowse) tabBrowser.widget(i)).getBrowserWindow(); boolean isExtended = browser.isExtended(); if((isChecked && !isExtended) || (!isChecked && isExtended)){ browser.toggleInformation(); } } menuBar.noteAttributes.setChecked(browserWindow.isExtended()); Global.saveWindowVisible("noteInformation", 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()); url.addQueryItem("body", text2); 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 = "<b>" +text +"</b>"; 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"); indexRunner.addWork("REINDEXALL"); setMessage(tr("Database will be reindexed.")); logger.log(logger.HIGH, "Leaving NeverNote.fullReindex"); } // 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<selectedNoteGUIDs.size(); i++) { indexRunner.addWork("REINDEXNOTE "+selectedNoteGUIDs.get(i)); } if (selectedNotebookGUIDs.size() > 1) setMessage(tr("Notes will be reindexed.")); else setMessage(tr("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; String title = null; if (selectedNoteGUIDs.size() == 1) title = conn.getNoteTable().getNote(selectedNoteGUIDs.get(0),false,false,false,false,false).getTitle(); // If we are deleting non-trash notes if (currentNote.isActive()) { if (Global.verifyDelete()) { String msg; if (selectedNoteGUIDs.size() > 1) { msg = new String(tr("Delete ") +selectedNoteGUIDs.size() +" notes?"); } else { if (title != null) msg = new String(tr("Delete note \"") +title +"\"?"); else msg = new String(tr("Delete note selected note?")); } if (QMessageBox.question(this, tr("Confirmation"), msg, QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) { return; } } if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals("")) { selectedNoteGUIDs.add(currentNoteGuid); } List<String> deleteNoteGUIDs = new ArrayList<String>(selectedNoteGUIDs); // タブを閉じるとselectedNoteGUIDsが変わってしまうのでその前にコピー closeTabs(selectedNoteGUIDs); for (String guid : deleteNoteGUIDs) { listManager.deleteNote(guid); } closeExternalWindows(deleteNoteGUIDs); } else { // If we are deleting from the trash. if (Global.verifyDelete()) { String msg; if (selectedNoteGUIDs.size() > 1) { msg = new String(tr("Permanently delete ") +selectedNoteGUIDs.size() +" notes?"); } else { if (title != null) msg = new String(tr("Permanently delete note \"") +title +"\"?"); else msg = new String(tr("Permanently delete note selected note?")); } if (QMessageBox.question(this, "Confirmation", msg, QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No)==StandardButton.No.value()) { return; } } if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals("")) selectedNoteGUIDs.add(currentNoteGuid); List<String> deleteNoteGUIDs = new ArrayList<String>(selectedNoteGUIDs); // タブを閉じるとselectedNoteGUIDsが変わってしまうのでその前にコピー for (int i=deleteNoteGUIDs.size()-1; i>=0; i--) { for (int j=listManager.getNoteTableModel().rowCount()-1; j>=0; j--) { QModelIndex modelIndex = listManager.getNoteTableModel().index(j, Global.noteTableGuidPosition); if (modelIndex != null) { SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex); String tableGuid = (String)ix.values().toArray()[0]; if (tableGuid.equals(deleteNoteGUIDs.get(i))) { listManager.getNoteTableModel().removeRow(j); j=-1; } } } closeTab(deleteNoteGUIDs.get(i)); listManager.expungeNote(deleteNoteGUIDs.get(i)); conn.getHistoryTable().expungeHistory(deleteNoteGUIDs.get(i)); conn.getExcludedTable().expungeExcludedNote(deleteNoteGUIDs.get(i)); conn.getStaredTable().expungeStaredNote(deleteNoteGUIDs.get(i)); } closeExternalWindows(deleteNoteGUIDs); } if (currentNoteGuid == null || currentNoteGuid.equals("")) { menuBar.noteAddNewTab.setEnabled(false); } listManager.loadNotesIndex(); noteIndexUpdated(false); refreshEvernoteNote(true); scrollToGuid(currentNoteGuid); logger.log(logger.HIGH, "Leaving NeverNote.deleteNote"); } // 対象ノートをタブで開いていたら閉じる private void closeTabs(List<String> noteGUIDs) { for (String guid : noteGUIDs) { closeTab(guid); } } // 対象ノートをタブで開いていたら閉じる private void closeTab(String noteGUID) { List<TabBrowse> closeTabs = new ArrayList<TabBrowse>(); for (TabBrowse tab : tabWindows.values()) { String guid = tab.getBrowserWindow().getNote().getGuid(); if (guid.equals(noteGUID)) { closeTabs.add(tab); } } for (TabBrowse tab : closeTabs) { tabWindowClosing(tab); } } // 対象ノートを外部ウィンドウで開いていたら閉じる private void closeExternalWindows(List<String> noteGUIDs) { List<ExternalBrowse> closeWindows = new ArrayList<ExternalBrowse>(); for (Map.Entry<String, ExternalBrowse> e : externalWindows.entrySet()) { for (String guid : noteGUIDs) { if (guid.equals(e.getKey())) { closeWindows.add(e.getValue()); } } } for (ExternalBrowse externalBrowse : closeWindows) { externalBrowse.close(); } } // Add a new note private void addNote() { logger.log(logger.HIGH, "Inside NeverNote.addNote"); // browserWindow.setEnabled(true); browserWindow.setReadOnly(false); saveNote(); Calendar currentTime = new GregorianCalendar(); StringBuffer noteString = new StringBuffer(100); noteString.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">\n" + "<en-note>\n"); if (Global.overrideDefaultFont()) { noteString.append("<font face=\"" +Global.getDefaultFont() +"\" >"); noteString.append("<span style=\"font-size:" +Global.getDefaultFontSize() +"pt;\">"); noteString.append("<br clear=\"none\" />\n"); noteString.append("</span>\n</font>\n"); } else noteString.append("<br clear=\"none\" />\n"); noteString.append("</en-note>"); Long l = new Long(currentTime.getTimeInMillis()); String randint = new String(Long.toString(l)); // 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<QTreeWidgetItem> selectedNotebook = notebookTree.selectedItems(); if (selectedNotebook.size() > 0 && !selectedNotebook.get(0).text(0).equalsIgnoreCase("All Notebooks") && !selectedNotebook.get(0).text(2).equalsIgnoreCase("STACK")) { QTreeWidgetItem currentSelectedNotebook = selectedNotebook.get(0); notebook = currentSelectedNotebook.text(2); } else { boolean found = false; List<Notebook> goodNotebooks = new ArrayList<Notebook>(); for (int i=0; i<listManager.getNotebookIndex().size(); i++) { boolean match = false; for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) { if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid())) { match = true; j = listManager.getArchiveNotebookIndex().size(); } } if (!match) //goodNotebooks.add(listManager.getNotebookIndex().get(i).deepCopy()); goodNotebooks.add((Notebook)Global.deepCopy(listManager.getNotebookIndex().get(i))); } // Now we have a list of good notebooks, so we can look for the default found = false; for (int i=0; i<goodNotebooks.size(); i++) { if (goodNotebooks.get(i).isDefaultNotebook()) { notebook = goodNotebooks.get(i).getGuid(); found = true; i = goodNotebooks.size(); } } if (goodNotebooks.size() > 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("Untitled Note"); newNote.setContent(noteString.toString()); 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()); newNote.setTagGuids(new ArrayList<String>()); newNote.setTagNames(new ArrayList<String>()); // If new notes are to be created based upon the selected tags, then we need to assign the tags if (Global.newNoteWithSelectedTags()) { List<QTreeWidgetItem> selections = tagTree.selectedItems(); QTreeWidgetItem currentSelection; for (int i=0; i<selections.size(); i++) { currentSelection = selections.get(i); newNote.getTagGuids().add(currentSelection.text(2)); newNote.getTagNames().add(currentSelection.text(0)); } } conn.getNoteTable().addNote(newNote, true); NoteMetadata metadata = new NoteMetadata(); metadata.setGuid(newNote.getGuid()); metadata.setDirty(true); listManager.addNote(newNote, metadata); // noteTableView.insertRow(newNote, true, -1); String prevCurrentNoteGuid = new String(currentNoteGuid); currentNote = newNote; currentNoteGuid = currentNote.getGuid(); // IFIXED こいつのせいで、ノート追加時にcurrentNoteGuidが更新されないので消す // noteTableView.clearSelection(); // 新規に作成したノートとそれまで開いていたノートの関連性を追加 if (prevCurrentNoteGuid != null && !prevCurrentNoteGuid.equals("")) { if (currentNoteGuid != null && !currentNoteGuid.equals("")) { conn.getHistoryTable().addHistory("addNewNote", prevCurrentNoteGuid, currentNoteGuid); } } refreshEvernoteNote(true); listManager.countNotebookResults(listManager.getNoteIndex()); browserWindow.titleLabel.setFocus(); browserWindow.titleLabel.selectAll(); // notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter()); // If the window is hidden, then we want to popup this in an external window & if (!isVisible()) listDoubleClick(); waitCursor(false); 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<selectedNoteGUIDs.size(); i++) { listManager.restoreNote(selectedNoteGUIDs.get(i)); } currentNoteGuid = ""; listManager.loadNotesIndex(); noteIndexUpdated(false); waitCursor(false); } // Search a note for specific txt @SuppressWarnings("unused") private void findText() { find.show(); find.setFocusOnTextField(); } @SuppressWarnings("unused") private void doFindText() { browserWindow.getBrowser().page().findText(find.getText(), find.getFlags()); find.setFocus(); } @SuppressWarnings("unused") private void updateNoteTitle(String guid, String title) { listManager.setNoteSynchronized(guid, false); // We do this manually because if we've edited the note in an // external window we run into the possibility of signal recursion // looping. if (guid.equals(currentNoteGuid)) { browserWindow.titleLabel.blockSignals(true); browserWindow.titleLabel.setText(title); browserWindow.titleLabel.blockSignals(false); } } // Signal received that note content has changed. Normally we just need the guid to remove // it from the cache. @SuppressWarnings("unused") private void invalidateNoteCache(String guid, String content) { noteCache.remove(guid); refreshEvernoteNote(true); } // Signal received that a note guid has changed @SuppressWarnings("unused") private void noteGuidChanged(String oldGuid, String newGuid) { if (noteCache.containsKey(oldGuid)) { if (!oldGuid.equals(currentNoteGuid)) { String cache = noteCache.get(oldGuid); noteCache.put(newGuid, cache); noteCache.remove(oldGuid); } else { noteCache.remove(oldGuid); noteCache.put(newGuid, browserWindow.getContent()); } } listManager.updateNoteGuid(oldGuid, newGuid, false); if (currentNoteGuid.equals(oldGuid)) { if (currentNote != null) currentNote.setGuid(newGuid); currentNoteGuid = newGuid; } if (externalWindows.containsKey(oldGuid)) { ExternalBrowse b = externalWindows.get(oldGuid); externalWindows.remove(oldGuid); b.getBrowserWindow().getNote().setGuid(newGuid); externalWindows.put(newGuid, b); } for(int i = 0; i < tabBrowser.count(); i++){ TabBrowse b = (TabBrowse)tabBrowser.widget(i); if (b.getBrowserWindow().getNote().getGuid().equals(oldGuid)) { b.getBrowserWindow().getNote().setGuid(newGuid); } } for (int i=0; i<listManager.getNoteIndex().size(); i++) { if (listManager.getNoteIndex().get(i).getGuid().equals(newGuid)) { noteTableView.proxyModel.addGuid(newGuid, listManager.getNoteMetadata().get(newGuid)); i=listManager.getNoteIndex().size(); } } if (listManager.getNoteTableModel().metaData.containsKey(oldGuid)) { NoteMetadata meta = listManager.getNoteTableModel().metaData.get(oldGuid); listManager.getNoteTableModel().metaData.put(newGuid, meta); listManager.getNoteTableModel().metaData.remove(oldGuid); } } // Toggle the note editor button bar // すべてのタブに private void toggleEditorButtonBar() { boolean isChecked = menuBar.showEditorBar.isChecked(); for(int i = 0; i < tabBrowser.count(); i++){ BrowserWindow browser = ((TabBrowse) tabBrowser.widget(i)).getBrowserWindow(); boolean isVisible = browser.buttonsVisible; if (isChecked && !isVisible) { browser.buttonsVisible = true; showEditorButtons(browser); } else if(!isChecked && isVisible) { browser.hideButtons(); } } Global.saveWindowVisible("editorButtonBar", browserWindow.buttonsVisible); } // Show editor buttons private void showEditorButtons(BrowserWindow browser) { browser.buttonLayout.setVisible(true); browser.undoAction.setVisible(false); browser.undoButton.setVisible(false); browser.undoAction.setVisible(Global.isEditorButtonVisible("undo")); browser.redoAction.setVisible(Global.isEditorButtonVisible("redo")); browser.cutAction.setVisible(Global.isEditorButtonVisible("cut")); browser.copyAction.setVisible(Global.isEditorButtonVisible("copy")); browser.pasteAction.setVisible(Global.isEditorButtonVisible("paste")); browser.strikethroughAction.setVisible(Global.isEditorButtonVisible("strikethrough")); browser.underlineAction.setVisible(Global.isEditorButtonVisible("underline")); browser.boldAction.setVisible(Global.isEditorButtonVisible("bold")); browser.italicAction.setVisible(Global.isEditorButtonVisible("italic")); browser.hlineAction.setVisible(Global.isEditorButtonVisible("hline")); browser.indentAction.setVisible(Global.isEditorButtonVisible("indent")); browser.outdentAction.setVisible(Global.isEditorButtonVisible("outdent")); browser.bulletListAction.setVisible(Global.isEditorButtonVisible("bulletList")); browser.numberListAction.setVisible(Global.isEditorButtonVisible("numberList")); browser.fontListAction.setVisible(Global.isEditorButtonVisible("font")); browser.fontSizeAction.setVisible(Global.isEditorButtonVisible("fontSize")); browser.fontColorAction.setVisible(Global.isEditorButtonVisible("fontColor")); browser.fontHilightAction.setVisible(Global.isEditorButtonVisible("fontHilight")); browser.leftAlignAction.setVisible(Global.isEditorButtonVisible("alignLeft")); browser.centerAlignAction.setVisible(Global.isEditorButtonVisible("alignCenter")); browser.rightAlignAction.setVisible(Global.isEditorButtonVisible("alignRight")); browser.spellCheckAction.setVisible(Global.isEditorButtonVisible("spellCheck")); browser.todoAction.setVisible(Global.isEditorButtonVisible("todo")); } private void duplicateNote(String guid) { Note oldNote = conn.getNoteTable().getNote(guid, true, false,false,false,true); List<Resource> resList = conn.getNoteTable().noteResourceTable.getNoteResources(guid, true); oldNote.setContent(conn.getNoteTable().getNoteContentNoUTFConversion(guid)); 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(); Note newNote = (Note)Global.deepCopy(oldNote); newNote.setUpdateSequenceNum(0); newNote.setGuid(newGuid); newNote.setDeleted(0); newNote.setActive(true); /* List<String> tagNames = new ArrayList<String>(); List<String> tagGuids = new ArrayList<String>();; for (int i=0; i<oldNote.getTagGuidsSize(); i++) { tagNames.add(oldNote.getTagNames().get(i)); tagGuids.add(oldNote.getTagGuids().get(i)); } // Sort note Tags to make them look nice for (int i=0; i<tagNames.size()-1; i++) { if (tagNames.get(i).compareTo(tagNames.get(i+1))<0) { String n1 = tagNames.get(i); String n2 = tagNames.get(i+1); tagNames.set(i, n2); tagNames.set(i+1, n1); } } newNote.setTagGuids(tagGuids); newNote.setTagNames(tagNames); // Add tag guids to note */ // Duplicate resources List<Resource> resList = oldNote.getResources(); if (resList == null) resList = new ArrayList<Resource>(); long prevGuid = 0; for (int i=0; i<resList.size(); i++) { l = prevGuid; while (l == prevGuid) { currentTime = new GregorianCalendar(); l = new Long(currentTime.getTimeInMillis()); } prevGuid = l; String newResGuid = new String(Long.toString(l)); resList.get(i).setNoteGuid(newGuid); resList.get(i).setGuid(newResGuid); resList.get(i).setUpdateSequenceNum(0); resList.get(i).setActive(true); conn.getNoteTable().noteResourceTable.saveNoteResource( (Resource)Global.deepCopy(resList.get(i)), true); } newNote.setResources(resList); // 操作履歴と除外ノートとスター付きノートも複製する if(Global.getDuplicateRensoNote()) { conn.getHistoryTable().duplicateHistory(newGuid, oldNote.getGuid()); conn.getExcludedTable().duplicateExcludedNotes(newGuid, oldNote.getGuid()); conn.getStaredTable().duplicateStaredNotes(newGuid, oldNote.getGuid()); } // Add note to the database conn.getNoteTable().addNote(newNote, true); NoteMetadata metaData = new NoteMetadata(); NoteMetadata oldMeta = listManager.getNoteMetadata().get(oldNote.getGuid()); metaData.copy(oldMeta); metaData.setGuid(newNote.getGuid()); listManager.addNote(newNote, metaData); noteTableView.insertRow(newNote, metaData, true, -1); currentNoteGuid = newNote.getGuid(); currentNote = newNote; refreshEvernoteNote(true); listManager.countNotebookResults(listManager.getNoteIndex()); waitCursor(false); } // View all notes @SuppressWarnings("unused") private void allNotes() { clearAttributeFilter(); clearNotebookFilter(); clearSavedSearchFilter(); clearTrashFilter(); clearTagFilter(); searchField.clear(); if (Global.mimicEvernoteInterface) { notebookTree.selectGuid(""); } notebookTreeSelection(); refreshEvernoteNote(true); // ゴミ箱から元の画面に戻す。連想ノートリストをONに。 if (!rensoNoteListDock.isEnabled()) { rensoNoteListDock.setEnabled(true); } } // Merge notes @SuppressWarnings("unused") private void mergeNotes() { logger.log(logger.HIGH, "Merging notes"); waitCursor(true); saveNote(); String masterGuid = null; List<String> sources = new ArrayList<String>(); QModelIndex index; for (int i=0; i<noteTableView.selectionModel().selectedRows().size(); i++) { int r = noteTableView.selectionModel().selectedRows().get(i).row(); index = noteTableView.proxyModel.index(r, Global.noteTableGuidPosition); SortedMap<Integer, Object> 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; // 操作履歴と除外ノートとスター付きノートをマージ if(Global.getMergeRensoNote()) { for (int i = 0; i < sources.size(); i++) { String childGuid = sources.get(i); if(masterGuid != null && childGuid != null) { if(!masterGuid.equals(childGuid)) { conn.getHistoryTable().mergeHistoryGuid(masterGuid, childGuid); conn.getExcludedTable().mergeHistoryGuid(masterGuid, childGuid); conn.getStaredTable().mergeHistoryGuid(masterGuid, childGuid); } } } } // マージしたノート(child)を外部ウィンドウで開いていたら、閉じる Collection<ExternalBrowse> windows = externalWindows.values(); Iterator<ExternalBrowse> windowIterator = windows.iterator(); Collection<String> guids = externalWindows.keySet(); Iterator<String> guidIterator = guids.iterator(); List<ExternalBrowse> closeWindows = new ArrayList<ExternalBrowse>(); while (windowIterator.hasNext()) { ExternalBrowse browser = windowIterator.next(); String guid = guidIterator.next(); for (int i = 0; i < sources.size(); i++) { if (guid.equals(sources.get(i))) { closeWindows.add(browser); } } } for (int i = closeWindows.size() - 1; i >= 0; i--) { closeWindows.get(i).close(); } // マージしたノート(child)をタブで開いていたら、閉じる List<TabBrowse> closeTabs = new ArrayList<TabBrowse>(); for (TabBrowse tab : tabWindows.values()) { String guid = tab.getBrowserWindow().getNote().getGuid(); for (String source : sources) { if (guid.equals(source)) { closeTabs.add(tab); } } } for (TabBrowse tab : closeTabs) { tabWindowClosing(tab); } noteIndexUpdated(false); // IFIXED // マージ後の新しいノートコンテンツを表示するためキャッシュを削除 noteCache.remove(masterGuid); refreshEvernoteNote(true); waitCursor(false); } private void mergeNoteContents(String targetGuid, List<String> sources) { Note target = conn.getNoteTable().getNote(targetGuid, true, false, false, false, false); String newContent = target.getContent(); newContent = newContent.replace("</en-note>", "<br></br>"); for (int i=0; i<sources.size(); i++) { Note source = conn.getNoteTable().getNote(sources.get(i), true, true, false, false, false); if (source.isSetTitle()) { newContent = newContent +("<table bgcolor=\"lightgrey\"><tr><td><font size=\"6\"><b>" +source.getTitle() +"</b></font></td></tr></table>"); } 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("<en-note>"); sourceContent = sourceContent.substring(startOfNote+9); int endOfNote = sourceContent.indexOf("</en-note>"); 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<source.getResourcesSize(); j++) { logger.log(logger.EXTREME, "Reassigning resource: "+source.getResources().get(j).getGuid()); Resource r = source.getResources().get(j); Resource newRes = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), true); Calendar currentTime = new GregorianCalendar(); Long l = new Long(currentTime.getTimeInMillis()); long prevGuid = 0; l = prevGuid; while (l == prevGuid) { currentTime = new GregorianCalendar(); l = new Long(currentTime.getTimeInMillis()); } String newResGuid = new String(Long.toString(l)); newRes.setNoteGuid(targetGuid); newRes.setGuid(newResGuid); newRes.setUpdateSequenceNum(0); newRes.setActive(true); conn.getNoteTable().noteResourceTable.saveNoteResource(newRes, true); } } logger.log(logger.EXTREME, "Updating note"); conn.getNoteTable().updateNoteContent(targetGuid, newContent +"</en-note>"); for (int i=0; i<sources.size(); i++) { logger.log(logger.EXTREME, "Deleting note " +sources.get(i)); listManager.deleteNote(sources.get(i)); } logger.log(logger.EXTREME, "Exiting merge note"); } // A resource within a note has had a guid change @SuppressWarnings("unused") private void noteResourceGuidChanged(String noteGuid, String oldGuid, String newGuid) { if (oldGuid != null && !oldGuid.equals(newGuid)) Global.resourceMap.put(oldGuid, newGuid); } // View a thumbnail of the note public void thumbnailView() { String thumbnailName = Global.getFileManager().getResDirPath("thumbnail-" + currentNoteGuid + ".png"); QFile thumbnail = new QFile(thumbnailName); if (!thumbnail.exists()) { QImage img = new QImage(); img.loadFromData(conn.getNoteTable().getThumbnail(currentNoteGuid)); thumbnailViewer.setThumbnail(img); } else thumbnailViewer.setThumbnail(thumbnailName); if (!thumbnailViewer.isVisible()) thumbnailViewer.showFullScreen(); } // An error happened while saving a note. Inform the user @SuppressWarnings("unused") private void saveRunnerError(String guid, String msg) { if (msg == null) { String title = "*Unknown*"; for (int i=0; i<listManager.getMasterNoteIndex().size(); i++) { if (listManager.getMasterNoteIndex().get(i).getGuid().equals(guid)) { title = listManager.getMasterNoteIndex().get(i).getTitle(); i=listManager.getMasterNoteIndex().size(); } } msg = tr("An error has happened while saving the note \"") +title+ tr("\".\n\nThis is probably due to a document that is too complex for NeighborNote to process. "+ "As a result, changes to the note may not be saved properly in the database."+ "\n\nA cached copy is being preserved so you can recover any data, but data may" + "\nbe lost. Please review the note to recover any critical data before restarting."); QMessageBox.information(this, tr("Error Saving Note"), tr(msg)); } } private void thumbnailHTMLReady(String guid, QByteArray html, Integer zoom) { logger.log(logger.HIGH, "Entering thumnailHTMLReady()"); logger.log(logger.HIGH, "Thumbnail ready for " +guid); // Find an idle preview object for (int i=0; i<thumbGenerators.size(); i++) { if (thumbGenerators.get(i).mutex.tryLock()) { logger.log(logger.EXTREME, "Idle generator found - loading thumbnail for " +guid); thumbGenerators.get(i).loadContent(guid, html, zoom); return; } } if (thumbGenerators.size() >= 1) { logger.log(logger.EXTREME, "No available thumbnail generators. Aborting " +guid); return; } logger.log(logger.EXTREME, "Creating new thumbnail generator " +guid); Thumbnailer preview = new Thumbnailer(logger, conn, listManager, thumbnailRunner); thumbGenerators.add(preview); if (preview.mutex.tryLock()) { logger.log(logger.EXTREME, "Loading thumbnail for " +guid); preview.loadContent(guid, html, zoom); } logger.log(logger.HIGH, "Exiting thumnailHTMLReady()"); } //********************************************************** //********************************************************** //* Online user actions //********************************************************** //********************************************************** private void setupOnlineMenu() { if (!Global.isConnected) { menuBar.noteOnlineHistoryAction.setEnabled(false); menuBar.selectiveSyncAction.setEnabled(false); return; } else { menuBar.noteOnlineHistoryAction.setEnabled(true); menuBar.selectiveSyncAction.setEnabled(true); } } @SuppressWarnings("unused") private void viewNoteHistory() { if (currentNoteGuid == null || currentNoteGuid.equals("")) return; if (currentNote.getUpdateSequenceNum() == 0) { setMessage(tr("Note has never been synchronized.")); QMessageBox.information(this, tr("Error"), tr("This note has never been sent to Evernote, so there is no history.")); return; } setMessage(tr("Getting Note History")); waitCursor(true); Note currentOnlineNote = null; versions = null; try { if (Global.isPremium()) versions = syncRunner.localNoteStore.listNoteVersions(syncRunner.authToken, currentNoteGuid); else versions = new ArrayList<NoteVersionId>(); currentOnlineNote = syncRunner.localNoteStore.getNote(syncRunner.authToken, currentNoteGuid, true, true, false, false); } catch (EDAMUserException e) { setMessage("EDAMUserException: " +e.getMessage()); return; } catch (EDAMSystemException e) { if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) { QMessageBox.warning(this, tr("Rate limit reached"), tr("Evernote usage has been temporarily exceeded. Please try again in ") + + e.getRateLimitDuration() + tr(" seconds.")); } setMessage("EDAMSystemException: " +e.getMessage()); return; } catch (EDAMNotFoundException e) { setMessage(tr("Note not found on server.")); QMessageBox.information(this, tr("Error"), tr("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(logger, conn, cbObserver); 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(tr("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<versions.size(); i++) { StringBuilder versionDate = new StringBuilder(simple.format(versions.get(i).getSaved())); if (versionDate.toString().equals(selection)) index = i; } if (index > -1 || selection.indexOf("Current") > -1) { Note historyNote = null; try { if (index > -1) { usn = versions.get(index).getUpdateSequenceNum(); historyNote = syncRunner.localNoteStore.getNoteVersion(syncRunner.authToken, currentNoteGuid, usn, true, true, true); } else historyNote = syncRunner.localNoteStore.getNote(syncRunner.authToken, currentNoteGuid, true,true,true,true); } catch (EDAMUserException e) { setMessage("EDAMUserException: " +e.getMessage()); waitCursor(false); return null; } catch (EDAMSystemException e) { if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) { QMessageBox.warning(this, tr("Rate limit reached"), tr("Evernote usage has been temporarily exceeded. Please try again in ") + + e.getRateLimitDuration() + tr(" seconds.")); } 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(tr("Restoring as new note.")); duplicateNote(reloadHistoryWindow(historyWindow.historyCombo.currentText())); setMessage(tr("Note has been restored as a new note.")); } @SuppressWarnings("unused") private void restoreHistoryNote() { setMessage(tr("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<n.getResourcesSize(); i++) { n.getResources().get(i).setActive(true); conn.getNoteTable().noteResourceTable.saveNoteResource(n.getResources().get(i), true); } NoteMetadata metadata = new NoteMetadata(); metadata.setGuid(n.getGuid()); listManager.addNote(n, metadata); conn.getNoteTable().addNote(n, true); refreshEvernoteNote(true); setMessage(tr("Note has been restored.")); } @SuppressWarnings("unused") private void setupSelectiveSync() { // Get a list of valid notebooks List<Notebook> notebooks = null; List<Tag> tags = null; List<LinkedNotebook> linkedNotebooks = null; try { notebooks = syncRunner.localNoteStore.listNotebooks(syncRunner.authToken); tags = syncRunner.localNoteStore.listTags(syncRunner.authToken); linkedNotebooks = syncRunner.localNoteStore.listLinkedNotebooks(syncRunner.authToken); } catch (EDAMUserException e) { setMessage("EDAMUserException: " +e.getMessage()); return; } catch (EDAMSystemException e) { if (e.getErrorCode() == EDAMErrorCode.RATE_LIMIT_REACHED) { QMessageBox.warning(this, tr("Rate limit reached"), tr("Evernote usage has been temporarily exceeded. Please try again in ") + + e.getRateLimitDuration() + tr(" seconds.")); } setMessage("EDAMSystemException: " +e.getMessage()); return; } catch (TException e) { setMessage("EDAMTransactionException: " +e.getMessage()); return; } catch (EDAMNotFoundException e) { setMessage("EDAMNotFoundException: " +e.getMessage()); return; } // Split up notebooks into synchronized & non-synchronized List<Notebook> ignoredBooks = new ArrayList<Notebook>(); List<String> dbIgnoredNotebooks = conn.getSyncTable().getIgnoreRecords("NOTEBOOK"); for (int i=notebooks.size()-1; i>=0; i--) { for (int j=0; j<dbIgnoredNotebooks.size(); j++) { if (notebooks.get(i).getGuid().equalsIgnoreCase(dbIgnoredNotebooks.get(j))) { ignoredBooks.add(notebooks.get(i)); j=dbIgnoredNotebooks.size(); } } } // split up tags into synchronized & non-synchronized List<Tag> ignoredTags = new ArrayList<Tag>(); List<String> dbIgnoredTags = conn.getSyncTable().getIgnoreRecords("TAG"); for (int i=tags.size()-1; i>=0; i--) { for (int j=0; j<dbIgnoredTags.size(); j++) { if (tags.get(i).getGuid().equalsIgnoreCase(dbIgnoredTags.get(j))) { ignoredTags.add(tags.get(i)); j=dbIgnoredTags.size(); } } } // split up linked notebooks into synchronized & non-synchronized List<LinkedNotebook> ignoredLinkedNotebooks = new ArrayList<LinkedNotebook>(); List<String> dbIgnoredLinkedNotebooks = conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK"); for (int i=linkedNotebooks.size()-1; i>=0; i--) { String notebookGuid = linkedNotebooks.get(i).getGuid(); for (int j=0; j<dbIgnoredLinkedNotebooks.size(); j++) { if (notebookGuid.equalsIgnoreCase(dbIgnoredLinkedNotebooks.get(j))) { ignoredLinkedNotebooks.add(linkedNotebooks.get(i)); j=dbIgnoredLinkedNotebooks.size(); } } } IgnoreSync ignore = new IgnoreSync(notebooks, ignoredBooks, tags, ignoredTags, linkedNotebooks, ignoredLinkedNotebooks); ignore.exec(); if (!ignore.okClicked()) return; waitCursor(true); // Clear out old notebooks & add the new ones List<String> oldIgnoreNotebooks = conn.getSyncTable().getIgnoreRecords("NOTEBOOK"); for (int i=0; i<oldIgnoreNotebooks.size(); i++) { conn.getSyncTable().deleteRecord("IGNORENOTEBOOK-"+oldIgnoreNotebooks.get(i)); } List<String> newNotebooks = new ArrayList<String>(); for (int i=ignore.getIgnoredBookList().count()-1; i>=0; i--) { String text = ignore.getIgnoredBookList().takeItem(i).text(); for (int j=0; j<notebooks.size(); j++) { if (notebooks.get(j).getName().equalsIgnoreCase(text)) { Notebook n = notebooks.get(j); conn.getSyncTable().addRecord("IGNORENOTEBOOK-"+n.getGuid(), n.getGuid()); j=notebooks.size(); newNotebooks.add(n.getGuid()); } } } // Clear out old tags & add new ones List<String> oldIgnoreTags = conn.getSyncTable().getIgnoreRecords("TAG"); for (int i=0; i<oldIgnoreTags.size(); i++) { conn.getSyncTable().deleteRecord("IGNORETAG-"+oldIgnoreTags.get(i)); } List<String> newTags = new ArrayList<String>(); for (int i=ignore.getIgnoredTagList().count()-1; i>=0; i--) { String text = ignore.getIgnoredTagList().takeItem(i).text(); for (int j=0; j<tags.size(); j++) { if (tags.get(j).getName().equalsIgnoreCase(text)) { Tag t = tags.get(j); conn.getSyncTable().addRecord("IGNORETAG-"+t.getGuid(), t.getGuid()); newTags.add(t.getGuid()); j=tags.size(); } } } // Clear out old tags & add new ones List<String> oldIgnoreLinkedNotebooks = conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK"); for (int i=0; i<oldIgnoreLinkedNotebooks.size(); i++) { conn.getSyncTable().deleteRecord("IGNORELINKEDNOTEBOOK-"+oldIgnoreLinkedNotebooks.get(i)); } List<String> newLinked = new ArrayList<String>(); for (int i=ignore.getIgnoredLinkedNotebookList().count()-1; i>=0; i--) { String text = ignore.getIgnoredLinkedNotebookList().takeItem(i).text(); for (int j=0; j<linkedNotebooks.size(); j++) { if (linkedNotebooks.get(j).getShareName().equalsIgnoreCase(text)) { LinkedNotebook t = linkedNotebooks.get(j); conn.getSyncTable().addRecord("IGNORELINKEDNOTEBOOK-"+t.getGuid(), t.getGuid()); newLinked.add(t.getGuid()); j=linkedNotebooks.size(); } } } conn.getNoteTable().expungeIgnoreSynchronizedNotes(newNotebooks, newTags, newLinked); waitCursor(false); refreshLists(); } //********************************************************** //********************************************************** //* XML Modifying methods //********************************************************** //********************************************************** // An error has happended fetching a resource. let the user know private void resourceErrorMessage(int tabIndex) { if (tabIndex < 0) { return; } if (inkNote.get(tabIndex)) return; waitCursor(false); 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.put(tabIndex, true); browserWindow.setReadOnly(true); waitCursor(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) { thumbnailRunner.interrupt = true; saveNoteIndexWidth(); saveNoteColumnPositions(); 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(tr("Finalizing Synchronization")); syncThreadsReady++; syncRunning = false; syncRunner.syncNeeded = false; synchronizeAnimationTimer.stop(); synchronizeButton.setIcon(new QIcon(iconPath+"synchronize.png")); saveNote(); if (currentNote == null) { currentNote = conn.getNoteTable().getNote(currentNoteGuid, false, false, false, false, true); } listManager.refreshNoteMetadata(); noteIndexUpdated(true); noteTableView.selectionModel().blockSignals(true); scrollToGuid(currentNoteGuid); noteTableView.selectionModel().blockSignals(false); refreshEvernoteNote(false); scrollToGuid(currentNoteGuid); waitCursor(false); // Check to see if there were any shared notebook errors if (syncRunner.error && syncRunner.errorSharedNotebooks.size() > 0) { String guid = syncRunner.errorSharedNotebooks.get(0); String notebookGuid = conn.getLinkedNotebookTable().getLocalNotebookGuid(guid); String localName = listManager.getNotebookNameByGuid(notebookGuid); SharedNotebookSyncError syncDialog = new SharedNotebookSyncError(localName); syncDialog.exec(); if (syncDialog.okPressed()) { if (syncDialog.doNothing.isChecked()) { syncRunner.errorSharedNotebooksIgnored.put(guid, guid); evernoteSync(); } if (syncDialog.deleteNotebook.isChecked()) { conn.getNoteTable().expungeNotesByNotebook(notebookGuid, true, false); conn.getNotebookTable().expungeNotebook(notebookGuid, false); conn.getLinkedNotebookTable().expungeNotebook(guid, false); conn.getLinkedNotebookTable().expungeNotebook(guid, false); evernoteSync(); } refreshLists(); return; } } // Finalize the synchronization if (!syncRunner.error) setMessage(tr("Synchronization Complete")); else setMessage(tr("Synchronization completed with errors. Please check the log for details.")); logger.log(logger.MEDIUM, "Sync complete."); } public void saveUploadAmount(long t) { Global.saveUploadAmount(t); } public void saveUserInformation(User user) { Global.saveUserInformation(user); } public void saveEvernoteUpdateCount(int i) { Global.saveEvernoteUpdateCount(i); } public void refreshLists() { logger.log(logger.EXTREME, "Entering NeverNote.refreshLists"); updateQuotaBar(); // すべてのタブのノートを調べて、Dirtyならばセーブする。その後refreshListsする。 Collection<Integer> tabIndex = noteDirty.keySet(); Iterator<Integer> indexIterator = tabIndex.iterator(); HashMap<Integer, Note> saveNotes = new HashMap<Integer, Note>(); HashMap<Integer, String> saveContents = new HashMap<Integer, String>(); for (boolean isNoteDirty: noteDirty.values()) { int index = indexIterator.next(); if (isNoteDirty) { saveNotes.put(index, tabWindows.get(index).getBrowserWindow().getNote()); saveContents.put(index, tabWindows.get(index).getBrowserWindow().getContent()); } } listManager.saveUpdatedNotes(saveNotes, saveContents); listManager.refreshLists(); tagIndexUpdated(true); notebookIndexUpdated(); savedSearchIndexUpdated(); listManager.loadNotesIndex(); noteTableView.selectionModel().blockSignals(true); noteIndexUpdated(true); noteTableView.selectionModel().blockSignals(false); logger.log(logger.EXTREME, "Leaving NeverNote.refreshLists"); } @SuppressWarnings("unused") private void authTimer() { Calendar cal = Calendar.getInstance(); // If we are not connected let's get out of here if (!Global.isConnected) return; // If this is the first time through, then we need to set this // if (syncRunner.authRefreshTime == 0 || cal.getTimeInMillis() > 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; if (!indexDisabled && indexRunner.idle) { thumbnailRunner.interrupt = true; indexRunner.addWork("SCAN"); } logger.log(logger.EXTREME, "Leaving NeighborNote index timer"); } @SuppressWarnings("unused") private void indexStarted() { setMessage(tr("Indexing notes")); } @SuppressWarnings("unused") private void indexComplete() { setMessage(tr("Index complete")); } @SuppressWarnings("unused") private synchronized void toggleNoteIndexing() { logger.log(logger.HIGH, "Entering NeverNote.toggleIndexing"); indexDisabled = !indexDisabled; if (!indexDisabled) setMessage(tr("Indexing is now enabled.")); else setMessage(tr("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 && !disableTagThreadCheck) { QMessageBox.information(this, tr("A thread has died."), tr("It appears as the tag counter thread has died. I recommend "+ "checking stopping NeighborNote, saving the logs for later viewing, and restarting. Sorry.")); disableTagThreadCheck = true; } } else tagDeadCount=0; alive = listManager.threadCheck(Global.notebookCounterThreadId); if (!alive) { notebookThreadDeadCount++; if (notebookThreadDeadCount > MAX && !disableNotebookThreadCheck) { QMessageBox.information(this, tr("A thread has died."), tr("It appears as the notebook counter thread has died. I recommend "+ "checking stopping NeighborNote, saving the logs for later viewing, and restarting. Sorry.")); disableNotebookThreadCheck=true; } } else notebookThreadDeadCount=0; alive = listManager.threadCheck(Global.trashCounterThreadId); if (!alive) { trashDeadCount++; if (trashDeadCount > MAX && !disableTrashThreadCheck) { QMessageBox.information(this, tr("A thread has died."), ("It appears as the trash counter thread has died. I recommend "+ "checking stopping NeighborNote, saving the logs for later viewing, and restarting. Sorry.")); disableTrashThreadCheck = true; } } else trashDeadCount = 0; alive = listManager.threadCheck(Global.saveThreadId); if (!alive) { saveThreadDeadCount++; if (saveThreadDeadCount > MAX && !disableSaveThreadCheck) { QMessageBox.information(this, tr("A thread has died."), tr("It appears as the note saver thread has died. I recommend "+ "checking stopping NeighborNote, saving the logs for later viewing, and restarting. Sorry.")); disableSaveThreadCheck = true; } } else saveThreadDeadCount=0; if (!syncThread.isAlive()) { syncThreadDeadCount++; if (syncThreadDeadCount > MAX && !disableSyncThreadCheck) { QMessageBox.information(this, tr("A thread has died."), tr("It appears as the synchronization thread has died. I recommend "+ "checking stopping NeighborNote, saving the logs for later viewing, and restarting. Sorry.")); disableSyncThreadCheck = true; } } else syncThreadDeadCount=0; if (!indexThread.isAlive()) { indexThreadDeadCount++; if (indexThreadDeadCount > MAX && !disableIndexThreadCheck) { QMessageBox.information(this, tr("A thread has died."), tr("It appears as the index thread has died. I recommend "+ "checking stopping NeighborNote, saving the logs for later viewing, and restarting. Sorry.")); disableIndexThreadCheck = true; } } else indexThreadDeadCount=0; if (!rensoNoteListDock.getRensoNoteList().getEnRelatedNotesThread().isAlive()) { enRelatedNotesThreadDeadCount++; if (enRelatedNotesThreadDeadCount > MAX && !disableENRelatedNotesThreadCheck) { QMessageBox.information(this, tr("A thread has died."), tr("It appears as the Evernote Related Notes thread has died. I recommend "+ "checking stopping NeighborNote, saving the logs for later viewing, and restarting. Sorry.")); disableENRelatedNotesThreadCheck = true; } } else enRelatedNotesThreadDeadCount=0; } private void thumbnailTimer() { if (Global.enableThumbnails() && !syncRunning && indexRunner.idle) { thumbnailRunner.addWork("SCAN"); } } //************************************************** //* Backup & Restore //************************************************** @SuppressWarnings("unused") private void databaseBackup() { QFileDialog fd = new QFileDialog(this); fd.setFileMode(FileMode.AnyFile); fd.setConfirmOverwrite(true); fd.setWindowTitle(tr("Backup Database")); fd.setFilter(tr("NixNote Export (*.nnex);;All Files (*.*)")); fd.setAcceptMode(AcceptMode.AcceptSave); if (saveLastPath == null || saveLastPath.equals("")) fd.setDirectory(System.getProperty("user.home")); else fd.setDirectory(saveLastPath); if (fd.exec() == 0 || fd.selectedFiles().size() == 0) { return; } waitCursor(true); saveLastPath = fd.selectedFiles().get(0); saveLastPath = saveLastPath.substring(0,saveLastPath.lastIndexOf("/")); setMessage(tr("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(tr("Database backup completed.")); waitCursor(false); } @SuppressWarnings("unused") private void databaseRestore() { if (QMessageBox.question(this, tr("Confirmation"), tr("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(tr("Restore Database")); fd.setFilter(tr("NixNote Export (*.nnex);;All Files (*.*)")); fd.setAcceptMode(AcceptMode.AcceptOpen); if (saveLastPath == null || saveLastPath.equals("")) fd.setDirectory(System.getProperty("user.home")); else fd.setDirectory(saveLastPath); if (fd.exec() == 0 || fd.selectedFiles().size() == 0) { return; } waitCursor(true); saveLastPath = fd.selectedFiles().get(0); saveLastPath = saveLastPath.substring(0,saveLastPath.lastIndexOf("/")); setMessage(tr("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(tr("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(tr("Backup Database")); fd.setFilter(tr("NixNote 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(tr("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(tr("Export completed.")); waitCursor(false); } @SuppressWarnings("unused") private void importNotes() { QFileDialog fd = new QFileDialog(this); fd.setFileMode(FileMode.ExistingFile); fd.setConfirmOverwrite(true); fd.setWindowTitle(tr("Import Notes")); fd.setFilter(tr("NixNote Export (*.nnex);;Evernote Export (*.enex);;All Files (*.*)")); fd.setAcceptMode(AcceptMode.AcceptOpen); if (saveLastPath == null || saveLastPath.equals("")) fd.setDirectory(System.getProperty("user.home")); else fd.setDirectory(saveLastPath); if (fd.exec() == 0 || fd.selectedFiles().size() == 0) { return; } waitCursor(true); setMessage(tr("Importing Notes")); saveNote(); if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals("")) selectedNoteGUIDs.add(currentNoteGuid); String fileName = fd.selectedFiles().get(0); // saveLastPath.substring(0,fileName.lastIndexOf("/")); if (fileName.endsWith(".nnex")) { ImportData noteReader = new ImportData(conn, false); 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; } } else { if (fileName.endsWith(".enex")) { ImportEnex noteReader = new ImportEnex(conn, false); if (selectedNotebookGUIDs != null && selectedNotebookGUIDs.size() > 0) noteReader.setNotebookGuid(selectedNotebookGUIDs.get(0)); else noteReader.setNotebookGuid(listManager.getNotebookIndex().get(0).getGuid()); waitCursor(false); if (QMessageBox.question(this, tr("Confirmation"), tr("Create new tags from import?"), QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No) == StandardButton.Yes.value()) { noteReader.createNewTags = true; } else noteReader.createNewTags = false; waitCursor(true); 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(tr("Notes have been imported.")); waitCursor(false); setMessage(tr("Import completed.")); waitCursor(false); } //************************************************** //* Duplicate a note //************************************************** @SuppressWarnings("unused") private void duplicateNote() { saveNote(); duplicateNote(currentNoteGuid); } //************************************************** //* Action from when a user clicks Copy As URL //************************************************** @SuppressWarnings("unused") private void copyAsUrlClicked() { QClipboard clipboard = QApplication.clipboard(); QMimeData mime = new QMimeData(); String url; mime.setText(currentNoteGuid); List<QUrl> urls = new ArrayList<QUrl>(); // Start building the URL User user = Global.getUserInformation(); // Check that we have everything we need if ((user.getShardId().equals("") || user.getId() == 0) && !Global.bypassSynchronizationWarning()) { SynchronizationRequiredWarning warning = new SynchronizationRequiredWarning(this); warning.exec(); if (!warning.neverSynchronize()) return; else { Global.setBypassSynchronizationWarning(true); user.setShardId("s0"); user.setId(0); } } // Start building a list of URLs based upon the selected notes noteTableView.showColumn(Global.noteTableGuidPosition); List<QModelIndex> selections = noteTableView.selectionModel().selectedRows(); if (!Global.isColumnVisible("guid")) noteTableView.hideColumn(Global.noteTableGuidPosition); // Check that the note is either synchronized, or in a local notebook for (int i=0; i<selections.size(); i++) { QModelIndex index; int row = selections.get(i).row(); index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition); SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index); String selectedGuid = (String)ix.values().toArray()[0]; Note n = conn.getNoteTable().getNote(selectedGuid, false, false, false, false, false); if (n.getUpdateSequenceNum() == 0 && !conn.getNotebookTable().isNotebookLocal(n.getNotebookGuid())) { QMessageBox.critical(this, tr("Please Synchronize") ,tr("Please either synchronize or move any " + "new notes to a local notebook.")); return; } } // Start building the URLs for (int i=0; i<selections.size(); i++) { QModelIndex index; int row = selections.get(i).row(); index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition); SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index); String selectedGuid = (String)ix.values().toArray()[0]; mime.setText(selectedGuid); String lid; String gid; Note selectedNote = conn.getNoteTable().getNote(selectedGuid, false, false, false, false, false); if (selectedNote.getUpdateSequenceNum() > 0) { gid = selectedGuid; lid = selectedGuid; } else { gid = "00000000-0000-0000-0000-000000000000"; lid = selectedGuid; } url = new String("evernote://///view/") + new String(user.getId() + "/" +user.getShardId() +"/" +gid+"/"+lid +"/"); urls.add(new QUrl(url)); } mime.setUrls(urls); clipboard.setMimeData(mime); } //************************************************** //* Folder Imports //************************************************** public void setupFolderImports() { List<WatchFolderRecord> records = conn.getWatchFolderTable().getAll(); if (importKeepWatcher == null) importKeepWatcher = new QFileSystemWatcher(); if (importDeleteWatcher == null) { importDeleteWatcher = new QFileSystemWatcher(); for (int i=0; i<records.size(); i++) { if (!records.get(i).keep) folderImportDelete(records.get(i).folder); } } // importKeepWatcher.addPath(records.get(i).folder.replace('\\', '/')); for (int i=0; i<records.size(); i++) { logger.log(logger.LOW, "Adding file monitor: " +records.get(i).folder); if (records.get(i).keep) importKeepWatcher.addPath(records.get(i).folder); else importDeleteWatcher.addPath(records.get(i).folder); } logger.log(logger.EXTREME, "List of directories being watched (kept)..."); List<String> monitorDelete = importKeepWatcher.directories(); for (int i=0; i<monitorDelete.size(); i++) { logger.log(logger.EXTREME, monitorDelete.get(i)); } logger.log(logger.EXTREME, "<end of list>"); logger.log(logger.EXTREME, "List of directories being watched (delete)..."); monitorDelete = importDeleteWatcher.directories(); for (int i=0; i<monitorDelete.size(); i++) { logger.log(logger.EXTREME, monitorDelete.get(i)); } logger.log(logger.EXTREME, "<end of list>"); importKeepWatcher.directoryChanged.connect(this, "folderImportKeep(String)"); importDeleteWatcher.directoryChanged.connect(this, "folderImportDelete(String)"); // Look at the files already there so we don't import them again if a new file is created if (importedFiles == null) { importedFiles = new ArrayList<String>(); for (int j=0; j<records.size(); j++) { QDir dir = new QDir(records.get(j).folder); List<QFileInfo> list = dir.entryInfoList(); for (int k=0; k<list.size(); k++) { if (list.get(k).isFile()) importedFiles.add(list.get(k).absoluteFilePath()); } } } } // Menu folderImport action triggered public void folderImport() { List<WatchFolderRecord> 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<dialog.table.rowCount(); i++) { QTableWidgetItem item = dialog.table.item(i, 0); String dir = item.text(); item = dialog.table.item(i, 1); String notebook = item.text(); item = dialog.table.item(i, 2); boolean keep; if (item.text().equalsIgnoreCase("Keep")) keep = true; else keep = false; String guid = conn.getNotebookTable().findNotebookByName(notebook); conn.getWatchFolderTable().addWatchFolder(dir, guid, keep, 0); } setupFolderImports(); } public void folderImportKeep(String dirName) throws NoSuchAlgorithmException { logger.log(logger.LOW, "Inside folderImportKeep"); String whichOS = System.getProperty("os.name"); if (whichOS.contains("Windows")) dirName = dirName.replace('/','\\'); FileImporter importer = new FileImporter(logger, conn); QDir dir = new QDir(dirName); List<QFileInfo> list = dir.entryInfoList(); String notebook = conn.getWatchFolderTable().getNotebook(dirName); for (int i=0; i<list.size(); i++){ logger.log(logger.LOW, "File found: " +list.get(i).fileName()); boolean redundant = false; // Check if we've already imported this one or if it existed before for (int j=0; j<importedFiles.size(); j++) { logger.log(logger.LOW, "redundant file list: " +list.get(i).absoluteFilePath()); if (importedFiles.get(j).equals(list.get(i).absoluteFilePath())) redundant = true; } logger.log(logger.LOW, "Checking if redundant: " +redundant); if (!redundant) { importer.setFileInfo(list.get(i)); importer.setFileName(list.get(i).absoluteFilePath()); logger.log(logger.LOW, "File importing is a file: " +list.get(i).isFile()); logger.log(logger.LOW, "File importing is a valid: " +importer.isValidType()); if (list.get(i).isFile() && importer.isValidType()) { if (!importer.importFile()) { // 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."); importFilesKeep.add(list.get(i).absoluteFilePath()); } else { Note newNote = importer.getNote(); newNote.setNotebookGuid(notebook); newNote.setTitle(dir.at(i)); NoteMetadata metadata = new NoteMetadata(); metadata.setDirty(true); metadata.setGuid(newNote.getGuid()); listManager.addNote(newNote, metadata); conn.getNoteTable().addNote(newNote, true); noteTableView.insertRow(newNote, metadata, true, -1); listManager.updateNoteContent(newNote.getGuid(), importer.getNoteContent()); listManager.countNotebookResults(listManager.getNoteIndex()); importedFiles.add(list.get(i).absoluteFilePath()); } } } } } public void folderImportDelete(String dirName) { logger.log(logger.LOW, "Inside folderImportDelete"); String whichOS = System.getProperty("os.name"); if (whichOS.contains("Windows")) dirName = dirName.replace('/','\\'); FileImporter importer = new FileImporter(logger, conn); QDir dir = new QDir(dirName); List<QFileInfo> list = dir.entryInfoList(); String notebook = conn.getWatchFolderTable().getNotebook(dirName); for (int i=0; i<list.size(); i++){ logger.log(logger.LOW, "File found: " +list.get(i).fileName()); importer.setFileInfo(list.get(i)); importer.setFileName(list.get(i).absoluteFilePath()); logger.log(logger.LOW, "File importing is a file: " +list.get(i).isFile()); logger.log(logger.LOW, "File importing is a valid: " +importer.isValidType()); if (list.get(i).isFile() && importer.isValidType()) { if (!importer.importFile()) { // 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."); importFilesKeep.add(list.get(i).absoluteFilePath()); } else { Note newNote = importer.getNote(); newNote.setNotebookGuid(notebook); newNote.setTitle(dir.at(i)); NoteMetadata metadata = new NoteMetadata(); metadata.setDirty(true); metadata.setGuid(newNote.getGuid()); listManager.addNote(newNote, metadata); conn.getNoteTable().addNote(newNote, true); noteTableView.insertRow(newNote, metadata, true, -1); listManager.updateNoteContent(newNote.getGuid(), importer.getNoteContent()); listManager.countNotebookResults(listManager.getNoteIndex()); dir.remove(dir.at(i)); } } } } //************************************************** //* External events //************************************************** private void externalFileEdited(String fileName) throws NoSuchAlgorithmException { logger.log(logger.HIGH, "Entering exernalFileEdited"); // Strip URL prefix and base dir path String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath()); String name = fileName.replace(dPath, ""); int pos = name.lastIndexOf('.'); String guid = name; if (pos > -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(browserWindow, r.getGuid(), oldHash, newHash); } if (externalWindows.containsKey(r.getNoteGuid())) { updateResourceContentHash(externalWindows.get(r.getNoteGuid()).getBrowserWindow(), r.getGuid(), oldHash, newHash); } conn.getNoteTable().updateResourceContentHash(r.getNoteGuid(), oldHash, newHash); Data data = r.getData(); 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); } if (externalWindows.containsKey(r.getNoteGuid())) { QWebSettings.setMaximumPagesInCache(0); QWebSettings.setObjectCacheCapacities(0, 0, 0); externalWindows.get(r.getNoteGuid()).getBrowserWindow().getBrowser().triggerPageAction(WebAction.Reload); } logger.log(logger.HIGH, "Exiting externalFielEdited"); } // This is a timer event that tries to save any external files that were edited. This // 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<importFilesKeep.size(); i++) { try { logger.log(logger.MEDIUM, "Trying to save " +importFilesKeep.get(i)); folderImportKeep(importFilesKeep.get(i)); importFilesKeep.remove(i); } catch (NoSuchAlgorithmException e) {e.printStackTrace();} } for (int i=0; i<importFilesDelete.size(); i++) { logger.log(logger.MEDIUM, "Trying to save " +importFilesDelete.get(i)); folderImportDelete(importFilesDelete.get(i)); importFilesDelete.remove(i); } } // If an attachment on the current note was edited, we need to update the current notes's hash // Update a note content's hash. This happens if a resource is edited outside of NN public void updateResourceContentHash(BrowserWindow browser, String guid, String oldHash, String newHash) { int position = browserWindow.getContent().indexOf("en-tag=\"en-media\" guid=\""+guid+"\" type="); int endPos; for (;position>-1;) { endPos = browser.getContent().indexOf(">", position+1); String oldSegment = browser.getContent().substring(position,endPos); int hashPos = oldSegment.indexOf("hash=\""); int hashEnd = oldSegment.indexOf("\"", hashPos+7); String hash = oldSegment.substring(hashPos+6, hashEnd); if (hash.equalsIgnoreCase(oldHash)) { String newSegment = oldSegment.replace(oldHash, newHash); String content = browser.getContent().substring(0,position) + newSegment + browser.getContent().substring(endPos); browser.setContent(new QByteArray(content));; } position = browser.getContent().indexOf("en-tag=\"en-media\" guid=\""+guid+"\" type=", position+1); } } //************************************************* //* Minimize to tray //************************************************* @Override public void changeEvent(QEvent e) { if (e.type() == QEvent.Type.WindowStateChange) { if (QSystemTrayIcon.isSystemTrayAvailable()) { if (isMinimized() && (Global.showTrayIcon() || Global.showTrayIcon())) { e.accept(); QTimer.singleShot(10, this, "hide()"); return; } if (isMaximized()) windowMaximized = true; else windowMaximized = false; } } } //************************************************* //* Check database userid & passwords //************************************************* private static 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; } //************************************************* //* View / Hide source HTML for a note //************************************************* public void viewSource() { // すべてのタブに対して for(int i = 0; i < tabBrowser.count(); i++){ BrowserWindow browser = ((TabBrowse) tabBrowser.widget(i)).getBrowserWindow(); browser.showSource(menuBar.viewSource.isChecked()); } } //************************************************* // Block the program. This is used for things // like async web calls. //************************************************* @SuppressWarnings("unused") private void blockApplication(BrowserWindow b) { // Block all signals waitCursor(true); blockSignals(true); blockTimer = new QTimer(); blockTimer.setSingleShot(true); blockTimer.setInterval(15000); blockTimer.timeout.connect(this, "unblockApplication()"); blockingWindow = b; blockTimer.start(); } @SuppressWarnings("unused") private void unblockApplication() { waitCursor(false); if (blockingWindow != null && new GregorianCalendar().getTimeInMillis() > blockingWindow.unblockTime && blockingWindow.unblockTime != -1) { QMessageBox.critical(null, tr("No Response from CodeCogs") ,tr("Unable to contact CodeCogs for LaTeX formula.")); blockingWindow.unblockTime = -1; blockingWindow.awaitingHttpResponse = false; } blockingWindow = null; blockSignals(false); } // タブが変更された private void tabWindowChanged(int index) { if (index < 0 || index >= tabBrowser.count()) { return; } saveNote(); TabBrowse tab = (TabBrowse) tabBrowser.widget(index); if (tab.getBrowserWindow().getNote() != null) { currentNoteGuid = tab.getBrowserWindow().getNote().getGuid(); currentNote = tab.getBrowserWindow().getNote(); } else { currentNoteGuid = ""; currentNote = null; } // 選択ノートを更新 selectedNoteGUIDs.clear(); if (currentNoteGuid != null && !currentNoteGuid.equals("")) { selectedNoteGUIDs.add(currentNoteGuid); } // browserWindowを更新 browserWindow.noteSignal.noteChanged.disconnect(this,"setNoteDirty()"); browserWindow.focusLost.disconnect(this, "saveNote()"); browserWindow = tab.getBrowserWindow(); browserWindow.noteSignal.noteChanged.connect(this, "setNoteDirty()"); browserWindow.focusLost.connect(this, "saveNote()"); // メニューバーのボタンを新しいbrowserWindowに合わせる menuBar.refreshTargetWindow(); // 現在ゴミ箱かつ移るタブがアクティブなら通常テーブルに、現在通常テーブルかつこれから非アクティブのタブに移るならゴミ箱を表示させる boolean nextIsActive; if (tab.getBrowserWindow().getNote() != null) { nextIsActive = tab.getBrowserWindow().getNote().isActive(); } else { nextIsActive = true; } if (Global.showDeleted && nextIsActive) { switchNoteTable(false); } else if (!Global.showDeleted && !nextIsActive) { switchNoteTable(true); } // noteTableViewの選択を変更するとselectionChangedが発生してしまうので一度切断 noteTableView.selectionModel().selectionChanged.disconnect(this,"noteTableSelection()"); scrollToGuid(currentNoteGuid); // 再接続 noteTableView.selectionModel().selectionChanged.connect(this,"noteTableSelection()"); menuBar.noteDuplicateAction.setEnabled(true); menuBar.noteOnlineHistoryAction.setEnabled(true); menuBar.noteMergeAction.setEnabled(true); if (Global.showDeleted) { menuBar.noteDuplicateAction.setEnabled(false); } if (!Global.isConnected) { menuBar.noteOnlineHistoryAction.setEnabled(false); } menuBar.noteMergeAction.setEnabled(false); try { int row = noteTableView.selectionModel().selectedRows().get(0).row(); if (row == 0) upButton.setEnabled(false); else upButton.setEnabled(true); if (row < listManager.getNoteTableModel().rowCount() - 1) downButton.setEnabled(true); else downButton.setEnabled(false); } catch (Exception e) { upButton.setEnabled(false); downButton.setEnabled(false); } int currentIndex = tabBrowser.currentIndex(); ArrayList<String> histGuids = historyGuids.get(currentIndex); int histPosition = historyPosition.get(currentIndex); // prev, nextボタンの有効・無効化 nextButton.setEnabled(true); prevButton.setEnabled(true); if (histPosition <= 1){ prevButton.setEnabled(false); } if (histPosition == histGuids.size()){ nextButton.setEnabled(false); } refreshEvernoteNote(true); // 連想ノートリストを更新 rensoNoteListDock.getRensoNoteList().refreshRensoNoteList(currentNoteGuid); } // 生存ノートテーブル→ゴミ箱(またはその逆)に切り替える private void switchNoteTable(boolean toDeleted) { clearNotebookFilter(); clearTagFilter(); clearAttributeFilter(); clearSavedSearchFilter(); listManager.getSelectedNotebooks().clear(); listManager.getSelectedTags().clear(); listManager.setSelectedSavedSearch(""); // toggle the add buttons newButton.setEnabled(!newButton.isEnabled()); menuBar.noteAdd.setEnabled(newButton.isEnabled()); menuBar.noteAddNewTab.setEnabled(newButton.isEnabled()); if (currentNoteGuid == null || currentNoteGuid.equals("")) { menuBar.noteAddNewTab.setEnabled(false); } menuBar.noteAdd.setVisible(true); if (!toDeleted) { // 生存ノートテーブルへ trashTree.itemSelectionChanged.disconnect(this, "trashTreeSelection()"); trashTree.clearSelection(); trashTree.itemSelectionChanged.connect(this, "trashTreeSelection()"); Global.showDeleted = false; menuBar.noteRestoreAction.setEnabled(false); menuBar.noteRestoreAction.setVisible(false); // ゴミ箱から元の画面に戻す。連想ノートリストをONに。 rensoNoteListDock.setEnabled(true); } else { // ゴミ箱へ trashTree.itemSelectionChanged.disconnect(this, "trashTreeSelection()"); trashTree.setCurrentItem(trashTree.getTrashItem()); trashTree.itemSelectionChanged.connect(this, "trashTreeSelection()"); Global.showDeleted = true; menuBar.noteRestoreAction.setEnabled(true); menuBar.noteRestoreAction.setVisible(true); // ゴミ箱を開く。連想ノートリストをOFFに。 rensoNoteListDock.setEnabled(false); } listManager.loadNotesIndex(); // noteTableViewの選択を変更するとselectionChangedが発生してしまうので一度切断 noteTableView.selectionModel().selectionChanged.disconnect(this,"noteTableSelection()"); noteIndexUpdated(false); // 再接続 noteTableView.selectionModel().selectionChanged.connect(this,"noteTableSelection()"); browserWindow.setReadOnly(!newButton.isEnabled()); } // ユーザが連想ノートリストのアイテムを選択した時の処理 @SuppressWarnings("unused") private void rensoNoteItemPressed(QListWidgetItem current) { logger.log(logger.HIGH, "Nevernote.rensoNoteSelectionChangeに入った"); rensoNotePressedItemGuid = rensoNoteListDock.getRensoNoteList().getNoteGuid(current); // 右クリックだったら終了 if (QApplication.mouseButtons().isSet(MouseButton.RightButton)) { return; } saveNote(); String prevCurrentNoteGuid = new String(currentNoteGuid); for (int i = 0; i < noteTableView.model().rowCount(); i++) { QModelIndex modelIndex = noteTableView.model().index(i, Global.noteTableGuidPosition); if (modelIndex != null) { SortedMap<Integer, Object> ix = noteTableView.model().itemData( modelIndex); String tableGuid = (String) ix.values().toArray()[0]; if (tableGuid.equals(rensoNotePressedItemGuid)) { noteTableView.selectRow(i); break; } } } // 連想ノートリストアイテムクリック操作を記録 conn.getHistoryTable().addHistory("rensoItemClick", prevCurrentNoteGuid, currentNoteGuid); logger.log(logger.HIGH, "Nevernote.rensoNoteSelectionChangeを出た"); } // 関連ノートリストからノートを除外する @SuppressWarnings("unused") private void excludeNote() { if (rensoNotePressedItemGuid != null) { saveNote(); excludeNote(rensoNotePressedItemGuid); } } // 関連ノートリストからノートを除外する private void excludeNote(String guid) { if (Global.verifyExclude()) { String msg; Note note = conn.getNoteTable().getNote(guid, false, false, false, false, false); String title = note.getTitle(); if (title != null) { msg = new String(tr("Exclude note \"") +title +"\"?"); } else { msg = new String(tr("Exclude note selected note?")); } if (QMessageBox.question(this, tr("Confirmation"), msg, QMessageBox.StandardButton.Yes, QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) { return; } } // Historyデータベースから除外するノートのデータを削除 conn.getHistoryTable().expungeHistory(guid, currentNoteGuid); // 除外ノートテーブルに追加 conn.getExcludedTable().addExclusion(guid, currentNoteGuid); rensoNoteListDock.getRensoNoteList().refreshRensoNoteList(currentNoteGuid); } // 関連ノートリストのノートにスターを付ける @SuppressWarnings("unused") private void starNote() { if (rensoNotePressedItemGuid != null) { saveNote(); starNote(rensoNotePressedItemGuid); } } // 関連ノートリストのノートにスターを付ける private void starNote(String guid) { // スター付きノートテーブルに追加 conn.getStaredTable().addStaredItem(currentNoteGuid, guid); rensoNoteListDock.getRensoNoteList().refreshRensoNoteList(currentNoteGuid); } // 関連ノートリストのノートからスターを外す @SuppressWarnings("unused") private void unstarNote() { if (rensoNotePressedItemGuid != null) { saveNote(); unstarNote(rensoNotePressedItemGuid); } } // 関連ノートリストのノートからスターを外す private void unstarNote(String guid) { // スター付きノートテーブルから削除 conn.getStaredTable().removeStaredItem(currentNoteGuid, guid); rensoNoteListDock.getRensoNoteList().refreshRensoNoteList(currentNoteGuid); } // currentNoteGuidを返す public String getCurrentNoteGuid() { return currentNoteGuid; } @SuppressWarnings("unused") // タブ入れ替えによってタブインデックスが変わったので、インデックスで管理しているハッシュマップ達も入れ替える private void tabIndexChanged(int from, int to) { // tabWindows TabBrowse tab = tabWindows.get(from); tabWindows.put(from, tabWindows.get(to)); tabWindows.put(to, tab); // noteDirty boolean isNoteDirty = noteDirty.get(from); noteDirty.put(from, noteDirty.get(to)); noteDirty.put(to, isNoteDirty); // inkNote boolean isInkNote = inkNote.get(from); inkNote.put(from, inkNote.get(to)); inkNote.put(to, isInkNote); // readOnly boolean isReadOnly = readOnly.get(from); readOnly.put(from, readOnly.get(to)); readOnly.put(to, isReadOnly); // historyGuids ArrayList<String> histGuids = historyGuids.get(from); historyGuids.put(from, historyGuids.get(to)); historyGuids.put(to, histGuids); // historyPosition int histPosition = historyPosition.get(from); historyPosition.put(from, historyPosition.get(to)); historyPosition.put(to, histPosition); // fromHistory boolean fromHist = fromHistory.get(from); fromHistory.put(from, fromHistory.get(to)); fromHistory.put(to, fromHist); } // 連想ノートリストのgetter public RensoNoteList getRensoNoteList() { return rensoNoteListDock.getRensoNoteList(); } // 帯域制限の超過をユーザに通知 @SuppressWarnings("unused") private void informRateLimit(Integer rateLimitDuration) { QMessageBox.warning(this, tr("Rate limit reached"), tr("Evernote usage has been temporarily exceeded. Please try again in ") + + rateLimitDuration + tr(" seconds.")); } // ツールバーの「新規」ボタンの接続スロットを設定 public void connectNewButtonSlot(String slot) { newButton.triggered.disconnect(); newButton.triggered.connect(this, slot); } }