X-Git-Url: http://git.sourceforge.jp/view?p=neighbornote%2FNeighborNote.git;a=blobdiff_plain;f=src%2Fcx%2Ffbn%2Fnevernote%2FNeverNote.java;h=a0322c9d14c9afe05a9505577ca1055c85653edb;hp=7511f2f9e5b143122b1aadeaf89bbdeefa691487;hb=297fc95a72f3d23fbeeb63304042bf370f9cc13d;hpb=103ec22789cde26aa22a78c554b9d173755543ba diff --git a/src/cx/fbn/nevernote/NeverNote.java b/src/cx/fbn/nevernote/NeverNote.java index 7511f2f..a0322c9 100644 --- a/src/cx/fbn/nevernote/NeverNote.java +++ b/src/cx/fbn/nevernote/NeverNote.java @@ -1,6 +1,7 @@ /* - * This file is part of NixNote + * 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''). @@ -21,6 +22,7 @@ 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; @@ -45,7 +47,6 @@ import java.util.Vector; import org.apache.log4j.Level; import org.apache.log4j.Logger; -import org.apache.thrift.TException; import org.h2.tools.ChangeFileEncryption; import com.evernote.edam.error.EDAMNotFoundException; @@ -64,6 +65,7 @@ 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; @@ -80,12 +82,14 @@ 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; @@ -102,6 +106,7 @@ import com.trolltech.qt.gui.QComboBox; import com.trolltech.qt.gui.QCursor; import com.trolltech.qt.gui.QDesktopServices; import com.trolltech.qt.gui.QDialog; +import com.trolltech.qt.gui.QDockWidget; import com.trolltech.qt.gui.QFileDialog; import com.trolltech.qt.gui.QFileDialog.AcceptMode; import com.trolltech.qt.gui.QFileDialog.FileMode; @@ -111,6 +116,7 @@ import com.trolltech.qt.gui.QIcon; import com.trolltech.qt.gui.QImage; import com.trolltech.qt.gui.QKeySequence; import com.trolltech.qt.gui.QLabel; +import com.trolltech.qt.gui.QListWidgetItem; import com.trolltech.qt.gui.QMainWindow; import com.trolltech.qt.gui.QMenu; import com.trolltech.qt.gui.QMessageBox; @@ -133,6 +139,8 @@ import com.trolltech.qt.gui.QTextEdit; import com.trolltech.qt.gui.QToolBar; import com.trolltech.qt.gui.QTreeWidgetItem; 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; @@ -148,7 +156,6 @@ 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.LoginDialog; import cx.fbn.nevernote.dialog.NotebookArchive; import cx.fbn.nevernote.dialog.NotebookEdit; import cx.fbn.nevernote.dialog.OnlineNoteHistory; @@ -173,13 +180,19 @@ 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.SavedSearchTreeWidget; import cx.fbn.nevernote.gui.SearchPanel; +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.controls.QuotaProgressBar; +import cx.fbn.nevernote.neighbornote.ClipBoardObserver; +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; @@ -195,6 +208,7 @@ import cx.fbn.nevernote.xml.ExportData; import cx.fbn.nevernote.xml.ImportData; import cx.fbn.nevernote.xml.ImportEnex; import cx.fbn.nevernote.xml.NoteFormatter; +//import org.apache.thrift.TException; public class NeverNote extends QMainWindow{ @@ -237,9 +251,10 @@ public class NeverNote extends QMainWindow{ NoteFilter filter; // Note filter String currentNoteGuid; // GUID of the current note Note currentNote; // The currently viewed note - boolean noteDirty; // Has the note been changed? - boolean inkNote; // if this is an ink note, it is read only - boolean readOnly; // Is this note read-only? + // ICHANGED + HashMap noteDirty; // Has the note been changed? + HashMap inkNote; // if this is an ink note, it is read only + HashMap readOnly; // Is this note read-only? ListManager listManager; // DB runnable task @@ -261,6 +276,7 @@ public class NeverNote extends QMainWindow{ QTimer authTimer; // Refresh authentication QTimer externalFileSaveTimer; // Save files altered externally QTimer thumbnailTimer; // Wakeup & scan for thumbnails + QTimer debugTimer; List externalFiles; // External files to save later List importFilesKeep; // Auto-import files to save later List importFilesDelete; // Auto-import files to save later @@ -313,26 +329,30 @@ public class NeverNote extends QMainWindow{ 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 noteCache; // Cash of note content HashMap readOnlyCache; // List of cashe notes that are read-only HashMap inkNoteCache; // List of cache notes that are ink notes - List historyGuids; // GUIDs of previously viewed items - int historyPosition; // Position within the viewed items - boolean fromHistory; // Is this from the history queue? + // ICHANGED + HashMap> historyGuids; // タブごとの以前見たノートのGUID + HashMap historyPosition; // Position within the viewed items + HashMap fromHistory; // Is this from the history queue? + String trashNoteGuid; // Guid to restore / set into or out of trash to save position List 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; + //Signal0 minimizeToTray; boolean windowMaximized = false; // Keep track of the window state for restores List pdfReadyQueue; // Queue of PDFs that are ready to be rendered. List syncIcons; // Array of icons used in sync animation @@ -343,6 +363,14 @@ public class NeverNote extends QMainWindow{ private QTimer blockTimer; BrowserWindow blockingWindow; + // ICHANGED + private final TabBrowserWidget tabBrowser; // ブラウザウィンドウをタブ化 + private final HashMap tabWindows; // タブウィンドウ + private final RensoNoteList rensoNoteList; // 連想ノートリスト + private final QDockWidget rensoNoteListDock; // 連想ノートリストドックウィジェット + ClipBoardObserver cbObserver; + String rensoNotePressedItemGuid; + String iconPath = new String("classpath:cx/fbn/nevernote/icons/"); @@ -354,11 +382,14 @@ public class NeverNote extends QMainWindow{ // Application Constructor @SuppressWarnings("static-access") public NeverNote(DatabaseConnection dbConn) { + // ICHANGED + 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 NixNote is already running.\n\n" + - "Please end any other process or shutdown the other NixNote before starting.\n\nExiting program.")); + "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); @@ -386,16 +417,19 @@ public class NeverNote extends QMainWindow{ logger.log(logger.EXTREME, "Starting GUI build"); QTranslator nevernoteTranslator = new QTranslator(); - nevernoteTranslator.load(Global.getFileManager().getTranslateFilePath("nevernote_" + QLocale.system().name() + ".qm")); + 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("NixNote")); + setWindowTitle(tr("NeighborNote")); mainLeftRightSplitter = new QSplitter(); + // ICHANGED + mainLeftRightSplitter.setOrientation(Qt.Orientation.Horizontal); + setCentralWidget(mainLeftRightSplitter); leftSplitter1 = new QSplitter(); leftSplitter1.setOrientation(Qt.Orientation.Vertical); @@ -412,15 +446,19 @@ public class NeverNote extends QMainWindow{ 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.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword); + // ICHANGED Global.getBehaviorDatabaseUrl()を追加 + 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(); +// indexRunner.indexNoteBody = Global.indexNoteBody(); +// indexRunner.indexNoteTitle = Global.indexNoteTitle(); +// indexRunner.specialIndexCharacters = Global.getSpecialIndexCharacters(); indexThread.start(); synchronizeAnimationTimer = new QTimer(); @@ -435,9 +473,12 @@ public class NeverNote extends QMainWindow{ logger.log(logger.EXTREME, "Setting sync thread & timers"); syncThreadsReady=1; - syncRunner = new SyncRunner("syncRunner.log", - Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), - Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword); + // ICHANGED Global.getBehaviorDatabaseUrl()を追加 + 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()"); @@ -459,9 +500,13 @@ public class NeverNote extends QMainWindow{ logger.log(logger.EXTREME, "Starting thumnail thread"); pdfReadyQueue = new ArrayList(); - thumbnailRunner = new ThumbnailRunner("thumbnailRunner.log", - Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), - Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword); + // ICHANGED Global.getBehaviorDatabaseUrl()を追加 + 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(); @@ -472,6 +517,10 @@ public class NeverNote extends QMainWindow{ 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()"); @@ -501,7 +550,8 @@ public class NeverNote extends QMainWindow{ tagTree = new TagTreeWidget(conn); savedSearchTree = new SavedSearchTreeWidget(); trashTree = new TrashTreeWidget(); - noteTableView = new TableView(logger, listManager); + // ICHANGED + noteTableView = new TableView(logger, listManager, this); searchField = new QComboBox(); searchField.setObjectName("searchField"); @@ -540,18 +590,62 @@ public class NeverNote extends QMainWindow{ noteCache = new HashMap(); readOnlyCache = new HashMap(); inkNoteCache = new HashMap(); - browserWindow = new BrowserWindow(conn); - + // ICHANGED + browserWindow = new BrowserWindow(conn, cbObserver); + + // ICHANGED 下から移動してきた。 + historyGuids = new HashMap>(); + historyPosition = new HashMap(); + fromHistory = new HashMap(); + + // ICHANGED タブブラウザ作成 + tabWindows = new HashMap(); + tabBrowser = new TabBrowserWidget(this); + tabBrowser.setStyleSheet("QTabBar::tab{width:150px;}"); + tabBrowser.setMovable(true); + TabBrowse tab = new TabBrowse(conn, tabBrowser, cbObserver); + browserWindow = tab.getBrowserWindow(); + int index = tabBrowser.addNewTab(tab, ""); + tabWindows.put(index, tab); + tabBrowser.setTabsClosable(true); + tabBrowser.currentChanged.connect(this, "tabWindowChanged(int)"); + tabBrowser.tabCloseRequested.connect(this, "tabWindowClosing(int)"); + + noteDirty = new HashMap(); + noteDirty.put(index, false); + + inkNote = new HashMap(); + readOnly = new HashMap(); + + // ICHANGED + // 履歴記録のハッシュマップを初期化 + historyGuids.put(index, new ArrayList()); + historyPosition.put(index, 0); + fromHistory.put(index, false); + mainLeftRightSplitter.addWidget(leftSplitter1); mainLeftRightSplitter.addWidget(browserIndexSplitter); - if (Global.getListView() == Global.View_List_Wide) { - browserIndexSplitter.addWidget(noteTableView); - browserIndexSplitter.addWidget(browserWindow); - } else { - mainLeftRightSplitter.addWidget(noteTableView); - mainLeftRightSplitter.addWidget(browserWindow); - } + // ICHANGED + // 連想ノートリストをセットアップ + rensoNoteList = new RensoNoteList(conn, this, syncRunner); + rensoNoteList.itemPressed.connect(this, + "rensoNoteItemPressed(QListWidgetItem)"); + rensoNoteListDock = new QDockWidget(tr("Renso Note List"), this); + rensoNoteListDock.setWidget(rensoNoteList); + addDockWidget(DockWidgetArea.RightDockWidgetArea, rensoNoteListDock); + + if (Global.getListView() == Global.View_List_Wide) { + browserIndexSplitter.addWidget(noteTableView); + // ICHANGED + browserIndexSplitter.addWidget(tabBrowser); + // browserIndexSplitter.addWidget(browserWindow); + } else { + mainLeftRightSplitter.addWidget(noteTableView); + // ICHANGED + mainLeftRightSplitter.addWidget(tabBrowser); + // mainLeftRightSplitter.addWidget(browserWindow); + } // Setup the thumbnail viewer thumbnailViewer = new ThumbnailViewer(); @@ -613,8 +707,15 @@ public class NeverNote extends QMainWindow{ savedSearchTree.itemSelectionChanged.connect(this, "updateSavedSearchSelection()"); savedSearchTree.setVisible(Global.isWindowVisible("savedSearchTree")); menuBar.hideSavedSearches.setChecked(Global.isWindowVisible("savedSearchTree")); + + // ICHANGED noteTableViewに新しいタブで開くを追加 + noteTableView.setOpenNewTabAction(menuBar.noteOpenNewTab); noteTableView.setAddAction(menuBar.noteAdd); + + // ICHANGED noteTableViewに新しいタブでノート追加を追加 + noteTableView.setAddNoteNewTabAction(menuBar.noteAddNewTab); + noteTableView.setDeleteAction(menuBar.noteDelete); noteTableView.setRestoreAction(menuBar.noteRestoreAction); noteTableView.setNoteDuplicateAction(menuBar.noteDuplicateAction); @@ -640,17 +741,31 @@ public class NeverNote extends QMainWindow{ noteTableView.setVisible(Global.isWindowVisible("noteList")); menuBar.hideNoteList.setChecked(Global.isWindowVisible("noteList")); - if (!Global.isWindowVisible("editorButtonBar")) + // ICHANGED + if (!Global.isWindowVisible("editorButtonBar")) { + menuBar.showEditorBar.setChecked(false); toggleEditorButtonBar(); + } + if (!Global.isWindowVisible("leftPanel")) menuBar.hideLeftSide.setChecked(true); - if (Global.isWindowVisible("noteInformation")) + + // ICHANGED + if (Global.isWindowVisible("noteInformation")) { + menuBar.noteAttributes.setChecked(true); toggleNoteInformation(); + } + quotaBar.setVisible(Global.isWindowVisible("quota")); - if (!quotaBar.isVisible()) + // IFIXED quotaBar.isVisible() → Global.isWindowVisible("quota") + // なぜかquotaBar.isVisible()が常にfalseを返すようなので修正 + if (!Global.isWindowVisible("quota")) menuBar.hideQuota.setChecked(false); + searchField.setVisible(Global.isWindowVisible("searchField")); - if (!searchField.isVisible()) + // IFIXED !searchField.isVisible() → !Global.isWindowVisible("searchField") + // なぜかsearchField.isVisible()が常にfalseを返すようなので修正 + if (!Global.isWindowVisible("searchField")) menuBar.hideSearch.setChecked(false); if (searchField.isHidden() && quotaBar.isHidden() && zoomSpinner.isHidden() && notebookTree.isHidden()) @@ -677,16 +792,22 @@ public class NeverNote extends QMainWindow{ trayIcon = new QSystemTrayIcon(this); - trayIcon.setToolTip(tr("NixNote")); + trayIcon.setToolTip(tr("NeighborNote")); trayIcon.setContextMenu(trayMenu); trayIcon.activated.connect(this, "trayActivated(com.trolltech.qt.gui.QSystemTrayIcon$ActivationReason)"); currentNoteGuid=""; currentNoteGuid = Global.getLastViewedNoteGuid(); - historyGuids = new ArrayList(); - historyPosition = 0; - fromHistory = false; - noteDirty = false; + if (currentNoteGuid.equals("")) + currentNote = new Note(); + + // ICHANGED + /* 上に移動したので要らない + historyGuids = new ArrayList(); + historyPosition = 0; + fromHistory = false; + */ + if (!currentNoteGuid.trim().equals("")) { currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true); } @@ -709,12 +830,14 @@ public class NeverNote extends QMainWindow{ tagTree.showAllTags(true); QIcon appIcon = new QIcon(iconPath+"nevernote.png"); - setWindowIcon(appIcon); - trayIcon.setIcon(appIcon); - if (Global.showTrayIcon()) - trayIcon.show(); - else - trayIcon.hide(); + if (QSystemTrayIcon.isSystemTrayAvailable()) { + setWindowIcon(appIcon); + trayIcon.setIcon(appIcon); + if (Global.showTrayIcon() || Global.minimizeOnClose()) + trayIcon.show(); + else + trayIcon.hide(); + } scrollToGuid(currentNoteGuid); if (Global.automaticLogin()) { @@ -735,8 +858,12 @@ public class NeverNote extends QMainWindow{ threadMonitorTimer.timeout.connect(this, "threadMonitorCheck()"); threadMonitorTimer.start(1000*10); // Check for threads every 10 seconds; - historyGuids.add(currentNoteGuid); - historyPosition = 1; + // ICHANGED たぶんこれはいらない + // IFIXED ? + /* + historyGuids.add(currentNoteGuid); + historyPosition = 1; + */ menuBar.blockSignals(true); menuBar.narrowListView.blockSignals(true); @@ -750,14 +877,18 @@ public class NeverNote extends QMainWindow{ menuBar.blockSignals(false); menuBar.narrowListView.blockSignals(false); menuBar.wideListView.blockSignals(false); - - if (Global.getListView() == Global.View_List_Wide) { - browserIndexSplitter.addWidget(noteTableView); - browserIndexSplitter.addWidget(browserWindow); - } else { - mainLeftRightSplitter.addWidget(noteTableView); - mainLeftRightSplitter.addWidget(browserWindow); - } + + // IFIXED + // 上に同じコードがあるよね? とりあえずコメントアウト + /* + * if (Global.getListView() == Global.View_List_Wide) { + * browserIndexSplitter.addWidget(noteTableView); // ICHANGED // + * browserIndexSplitter.addWidget(tabBrowser); + * browserIndexSplitter.addWidget(browserWindow); } else { + * mainLeftRightSplitter.addWidget(noteTableView); // ICHANGED // + * mainLeftRightSplitter.addWidget(tabBrowser); + * mainLeftRightSplitter.addWidget(browserWindow); } + */ messageTimer = new QTimer(); messageTimer.timeout.connect(this, "clearMessage()"); @@ -767,12 +898,44 @@ public class NeverNote extends QMainWindow{ 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)"); - if (Global.checkVersionUpgrade()) + // Set the startup notebook + String defaultNotebook = Global.getStartupNotebook(); + if (!defaultNotebook.equals("AllNotebooks") && !defaultNotebook.equals("")) { + for (int k=0; k dirty = conn.getNoteTable().getDirty(); + logger.log(logger.LOW, "------ Dirty Notes List Begin ------"); + for (int i=0; i it = tabWindows.keySet().iterator(); + while (it.hasNext()) { + tabWindows.get(it.next()).getBrowserWindow() + .setNotebookList(filteredBooks); + } + waitCursor(false); } // Change the notebook's icon @@ -2090,9 +2381,12 @@ public class NeverNote extends QMainWindow{ if (currentNote != null && currentNote.getTagGuids().contains(guid)) browserWindow.setTag(getTagNamesForNote(currentNote)); logger.log(logger.HIGH, "Leaving NeverNote.editTag"); - return; + //return; } } + listManager.reloadNoteTagNames(guid, edit.getTag()); + noteIndexUpdated(true); + refreshEvernoteNote(true); browserWindow.setTag(getTagNamesForNote(currentNote)); logger.log(logger.HIGH, "Leaving NeverNote.editTag..."); } @@ -2157,6 +2451,11 @@ public class NeverNote extends QMainWindow{ menuBar.noteRestoreAction.setVisible(false); + // ICHANGED ゴミ箱から元の画面に戻す。連想ノートリストをONに。 + if (!rensoNoteListDock.isEnabled()) { + rensoNoteListDock.setEnabled(true); + } + List selections = tagTree.selectedItems(); QTreeWidgetItem currentSelection; selectedTagGUIDs.clear(); @@ -2236,7 +2535,7 @@ public class NeverNote extends QMainWindow{ newTags.add(tags.get(i)); } - listManager.saveNoteTags(guid, tags); + listManager.saveNoteTags(guid, tags, true); listManager.countTagResults(listManager.getNoteIndex()); StringBuffer names = new StringBuffer(""); for (int i=0; i selections = savedSearchTree.selectedItems(); QTreeWidgetItem currentSelection; selectedSavedSearchGUID = ""; @@ -2656,6 +2969,7 @@ public class NeverNote extends QMainWindow{ status.setTagCount(listManager.getTagIndex().size()); status.setResourceCount(conn.getNoteTable().noteResourceTable.getResourceCount()); status.setWordCount(conn.getWordsTable().getWordCount()); + status.setHistoryCount(conn.getHistoryTable().getHistoryCount()); waitCursor(false); status.exec(); } @@ -2665,7 +2979,7 @@ public class NeverNote extends QMainWindow{ 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 NixNote will be unresponsive until it is complete. Do you wish to continue?"), + "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; @@ -2692,11 +3006,16 @@ public class NeverNote extends QMainWindow{ QTextEdit textBox = new QTextEdit(); layout.addWidget(textBox); textBox.setReadOnly(true); - QFile file = new QFile(Global.getFileManager().getHomeDirPath("release.txt")); + QFile file = new QFile(Global.getFileManager().getProgramDirPath("release.txt")); if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly, QIODevice.OpenModeFlag.Text))) return; - textBox.setText(file.readAll().toString()); + // ICHANGED 日本語文字化け対策 + 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); @@ -2715,14 +3034,16 @@ public class NeverNote extends QMainWindow{ @SuppressWarnings("unused") private void about() { logger.log(logger.HIGH, "Entering NeverNote.about"); + // ICHANGED based on...の記述を付加 QMessageBox.about(this, - tr("About NixNote"), - tr("

NixNote


Version ") - +Global.version + tr("About NeighborNote"), + tr("

NeighborNote


Version ") + +Global.version + "(based on NixNote 1.5)" + //+"1.2.120724" +tr("
" +"Open Source Evernote Client.

" +"Licensed under GPL v2.


" - +"
Evernote is copyright 2001-2010 by Evernote Corporation
" + +"
Evernote is copyright 2001-2012 by Evernote Corporation
" +"Jambi and QT are the licensed trademark of Nokia Corporation
" +"PDFRenderer is licened under the LGPL
" +"JTidy is copyrighted under the World Wide Web Consortium
" @@ -2892,8 +3213,10 @@ public class NeverNote extends QMainWindow{ listManager.setEnSearch(text.trim()); listManager.loadNotesIndex(); noteIndexUpdated(false); + refreshEvernoteNote(true); searchPerformed = true; + waitCursor(false); logger.log(logger.HIGH, "Leaving NeverNote.searchFieldChanged"); } @@ -2957,7 +3280,7 @@ public class NeverNote extends QMainWindow{ attributeButton = toolBar.addAction(tr("Attributes")); QIcon attributeIcon = new QIcon(iconPath+"attribute.png"); attributeButton.setIcon(attributeIcon); - attributeButton.triggered.connect(this, "toggleNoteInformation()"); + attributeButton.triggered.connect(this, "toggleNoteAttributes()"); toggleAttributeButton(Global.isToolbarButtonVisible("attribute")); emailButton = toolBar.addAction(tr("Email")); @@ -3260,14 +3583,25 @@ public class NeverNote extends QMainWindow{ Global.showDeleted = false; menuBar.noteRestoreAction.setEnabled(false); menuBar.noteRestoreAction.setVisible(false); + // ICHANGED ゴミ箱から元の画面に戻す。連想ノートリストをONに。 + rensoNoteListDock.setEnabled(true); } else { + trashNoteGuid = tempGuid; currentNoteGuid = trashNoteGuid; - trashNoteGuid = tempGuid; menuBar.noteRestoreAction.setEnabled(true); menuBar.noteRestoreAction.setVisible(true); + // ICHANGED ゴミ箱を開く。連想ノートリストを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()); @@ -3287,6 +3621,10 @@ public class NeverNote extends QMainWindow{ 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(); @@ -3301,6 +3639,11 @@ public class NeverNote extends QMainWindow{ listManager.loadNotesIndex(); noteIndexUpdated(false); + + // ICHANGED ゴミ箱から元の画面に戻す。連想ノートリストをONに。 + if (!rensoNoteListDock.isEnabled()) { + rensoNoteListDock.setEnabled(true); + } } } // Show/Hide trash window @@ -3320,6 +3663,11 @@ public class NeverNote extends QMainWindow{ 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(); @@ -3345,8 +3693,10 @@ public class NeverNote extends QMainWindow{ } // 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(); @@ -3355,13 +3705,15 @@ public class NeverNote extends QMainWindow{ return; } + OAuthTokenizer tokenizer = new OAuthTokenizer(); AESEncrypter aes = new AESEncrypter(); try { - aes.decrypt(new FileInputStream(Global.getFileManager().getHomeDirFile("secure.txt"))); + aes.decrypt(new FileInputStream(Global.getFileManager().getHomeDirFile("oauth.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", "") ; @@ -3388,43 +3740,54 @@ public class NeverNote extends QMainWindow{ syncRunner.userStoreUrl = Global.userStoreUrl; syncRunner.noteStoreUrl = Global.noteStoreUrl; syncRunner.noteStoreUrlBase = Global.noteStoreUrlBase; - - String userid = aes.getUserid(); - String password = aes.getPassword(); - if (!userid.equals("") && !password.equals("")) { - Global.username = userid; - Global.password = password; - syncRunner.username = Global.username; - syncRunner.password = Global.password; + + + + String authString = aes.getString(); + if (!authString.equals("")) { + tokenizer.tokenize(authString); + syncRunner.authToken = tokenizer.oauth_token; syncRunner.enConnect(); } Global.isConnected = syncRunner.isConnected; if (!Global.isConnected) { - // Show the login dialog box - if (!Global.automaticLogin() || userid.equals("")|| password.equals("")) { - LoginDialog login = new LoginDialog(); - login.exec(); - - if (!login.okPressed()) { - return; - } - - Global.username = login.getUserid(); - Global.password = login.getPassword(); + 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("oauth.txt"))); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } - syncRunner.username = Global.username; - syncRunner.password = Global.password; + syncRunner.authToken = tokenizer.oauth_token; syncRunner.enConnect(); Global.isConnected = syncRunner.isConnected; } - +// Global.username = syncRunner.username; + if (!Global.isConnected) return; setupOnlineMenu(); setupConnectMenuOptions(); logger.log(logger.HIGH, "Leaving NeverNote.remoteConnect"); + + } private void setupConnectMenuOptions() { logger.log(logger.HIGH, "entering NeverNote.setupConnectMenuOptions"); @@ -3454,6 +3817,11 @@ public class NeverNote extends QMainWindow{ // clearNotebookFilter(); clearTrashFilter(); // clearSavedSearchFilter(); + + // ICHANGED ゴミ箱から元の画面に戻す。連想ノートリストをONに。 + if (!rensoNoteListDock.isEnabled()) { + rensoNoteListDock.setEnabled(true); + } if (attributeTreeSelected == null || item.nativeId() != attributeTreeSelected.nativeId()) { if (item.childCount() > 0) { @@ -3565,6 +3933,23 @@ public class NeverNote extends QMainWindow{ saveNote(); + // ICHANGED + // 右クリックだったときの処理 + if (QApplication.mouseButtons().isSet(MouseButton.RightButton)) { + // 選択されたノートのguidをselectedNoteGUIDsにセット + List 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 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 selections = noteTableView.selectionModel().selectedRows(); if (selections.size() > 1) @@ -3574,14 +3959,28 @@ public class NeverNote extends QMainWindow{ // If the ctrl key is pressed, then they are selecting multiple // entries and we don't want to change the currently viewed note. - if (QApplication.keyboardModifiers().isSet(KeyboardModifier.ControlModifier) && - QApplication.mouseButtons().isSet(MouseButton.LeftButton)) + // ICHANGED + // Shiftキーを押しながらの場合の処理も追加 + if ((QApplication.keyboardModifiers().isSet(KeyboardModifier.ControlModifier) || + QApplication.keyboardModifiers().isSet(KeyboardModifier.ShiftModifier)) && + QApplication.mouseButtons().isSet(MouseButton.LeftButton)){ + selectedNoteGUIDs.clear(); + for (int i=0; i ix = noteTableView.proxyModel.itemData(index); + selectedNoteGUIDs.add((String)ix.values().toArray()[0]); + } return; - - if (historyGuids.size() == 0) { + } + + // ICHANGED たぶんこれは不要 + // IFIXED ? + /*if (historyGuids.size() == 0) { historyGuids.add(currentNoteGuid); historyPosition = 1; - } + }*/ + noteTableView.showColumn(Global.noteTableGuidPosition); if (!Global.isColumnVisible("guid")) @@ -3593,6 +3992,9 @@ public class NeverNote extends QMainWindow{ 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); } @@ -3614,31 +4016,87 @@ public class NeverNote extends QMainWindow{ downButton.setEnabled(false); index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition); SortedMap ix = noteTableView.proxyModel.itemData(index); - currentNoteGuid = (String)ix.values().toArray()[0]; + + currentNoteGuid = (String)ix.values().toArray()[0]; selectedNoteGUIDs.add(currentNoteGuid); } } nextButton.setEnabled(true); prevButton.setEnabled(true); - if (!fromHistory) { - int endPosition = historyGuids.size()-1; - for (int j=historyPosition; j<=endPosition; j++) { - historyGuids.remove(historyGuids.size()-1); - } - historyGuids.add(currentNoteGuid); - historyPosition = historyGuids.size(); - } - if (historyPosition <= 1) - prevButton.setEnabled(false); - if (historyPosition == historyGuids.size()) - nextButton.setEnabled(false); - - fromHistory = false; + + // ICHANGED + int currentIndex = tabBrowser.currentIndex(); + ArrayList histGuids = historyGuids.get(currentIndex); + int histPosition = historyPosition.get(currentIndex); + boolean fromHist = fromHistory.get(currentIndex); + + // ICHANGED + 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); + + // ICHANGED + if (currentNoteGuid != null && !currentNoteGuid.equals("")) { + if (!Global.showDeleted) { // ゴミ箱じゃなければ + addBrowseHistory(); + } + } + + // ICHANGED + // 連想ノートリストを更新 + rensoNoteList.refreshRensoNoteList(currentNoteGuid); + + waitCursor(false); logger.log(logger.HIGH, "Leaving NeverNote.noteTableSelection"); - } + } + + + // ICHANGED + // 複数ノートの同時閲覧履歴をデータベースに保存 + private void addBrowseHistory() { + // このノートと他のタブウィンドウノートの関連性を内部データベースのHistoryテーブルに登録 + if (tabWindows.size() >= 2) { + Iterator 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 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"); @@ -3676,9 +4134,13 @@ public class NeverNote extends QMainWindow{ String saveCurrentNoteGuid = new String(); String tempNoteGuid = new String(); - - historyGuids.clear(); - historyPosition = 0; + + // ICHANGED + int currentIndex = tabBrowser.currentIndex(); + ArrayList histGuids = historyGuids.get(currentIndex); + histGuids.clear(); + historyPosition.put(currentIndex, 0); + prevButton.setEnabled(false); nextButton.setEnabled(false); @@ -3698,59 +4160,86 @@ public class NeverNote extends QMainWindow{ 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 = ""; + currentNoteGuid = ""; } reloadTagTree(false); logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNoteList"); } - // Called when the previous arrow button is clicked - @SuppressWarnings("unused") + + // ICHANGED + // Called when the previous arrow button is clicked + @SuppressWarnings("unused") private void previousViewedAction() { - if (!prevButton.isEnabled()) - return; - if (historyPosition == 0) - return; - historyPosition--; - if (historyPosition <= 0) - return; - String historyGuid = historyGuids.get(historyPosition-1); - fromHistory = true; - for (int i=0; i ix = noteTableView.model().itemData(modelIndex); - String tableGuid = (String)ix.values().toArray()[0]; - if (tableGuid.equals(historyGuid)) { - noteTableView.selectRow(i); - return; - } - } - } - } + int currentIndex = tabBrowser.currentIndex(); + ArrayList 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 ix = noteTableView.model().itemData( + modelIndex); + String tableGuid = (String) ix.values().toArray()[0]; + if (tableGuid.equals(historyGuid)) { + noteTableView.selectRow(i); + return; + } + } + } + } + @SuppressWarnings("unused") private void nextViewedAction() { if (!nextButton.isEnabled()) return; - String historyGuid = historyGuids.get(historyPosition); - historyPosition++; - fromHistory = true; - for (int i=0; i ix = noteTableView.model().itemData(modelIndex); - String tableGuid = (String)ix.values().toArray()[0]; - if (tableGuid.equals(historyGuid)) { - noteTableView.selectRow(i); - return; - } - } - } + // ICHANGED + int currentIndex = tabBrowser.currentIndex(); + ArrayList 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 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") @@ -4099,8 +4588,7 @@ public class NeverNote extends QMainWindow{ listManager.updateNoteMetadata(meta); noteTableView.proxyModel.addGuid(selectedNoteGUIDs.get(j), meta); } - - logger.log(logger.EXTREME, "Leaving NeverNote.setNoteDirty()"); + logger.log(logger.EXTREME, "Leaving NeverNote.notePinned()"); } // Wide list was chosen public void narrowListView() { @@ -4124,7 +4612,9 @@ public class NeverNote extends QMainWindow{ menuBar.narrowListView.blockSignals(false); mainLeftRightSplitter.addWidget(noteTableView); - mainLeftRightSplitter.addWidget(browserWindow); + // ICHANGED browserWindow → tabBrowser + mainLeftRightSplitter.addWidget(tabBrowser); + restoreWindowState(false); noteTableView.repositionColumns(); noteTableView.resizeColumnWidths(); @@ -4163,7 +4653,9 @@ public class NeverNote extends QMainWindow{ menuBar.narrowListView.blockSignals(false); browserIndexSplitter.setVisible(true); browserIndexSplitter.addWidget(noteTableView); - browserIndexSplitter.addWidget(browserWindow); + // ICHANGED browserWindow → tabBrowser + browserIndexSplitter.addWidget(tabBrowser); + restoreWindowState(false); noteTableView.repositionColumns(); noteTableView.resizeColumnWidths(); @@ -4231,10 +4723,13 @@ public class NeverNote extends QMainWindow{ 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); + // ICHANGED + ExternalBrowse newBrowser = new ExternalBrowse(conn, cbObserver); + newBrowser.setWindowIcon(appIcon); externalWindows.put(guid, newBrowser); showEditorButtons(newBrowser.getBrowserWindow()); @@ -4269,45 +4764,289 @@ public class NeverNote extends QMainWindow{ private void externalWindowClosing(String guid) { externalWindows.remove(guid); } - - - //*************************************************************** - //*************************************************************** - //** These functions deal with Note specific things - //*************************************************************** - //*************************************************************** - private void setNoteDirty() { - logger.log(logger.EXTREME, "Entering NeverNote.setNoteDirty()"); + // *************************************************************** + // *************************************************************** + // ** タブウィンドウの機能 + // *************************************************************** + // *************************************************************** + @SuppressWarnings("unused") + private void openNewTab() { + saveNote(); + + // selectedNoteGUIDsをディープコピー + List copySelected = new ArrayList(selectedNoteGUIDs); - // Find if the note is being edited externally. If it is, update it. - if (externalWindows.containsKey(currentNoteGuid)) { - QTextCodec codec = QTextCodec.codecForName("UTF-8"); - QByteArray unicode = codec.fromUnicode(browserWindow.getContent()); - ExternalBrowse window = externalWindows.get(currentNoteGuid); - window.getBrowserWindow().setContent(unicode); + for (int i=0; i < copySelected.size() ; i++) { + openTabEditor(copySelected.get(i)); + } + } + + // ICHANGED 連想ノートリストから新しいタブで開く + @SuppressWarnings("unused") + private void openNewTabFromRNL(){ + if(rensoNotePressedItemGuid != null){ + String prevCurrentNoteGuid = new String(currentNoteGuid); + + saveNote(); + openTabEditor(rensoNotePressedItemGuid); + + // 連想ノートリストアイテムクリック操作を記録 + conn.getHistoryTable().addHistory("rensoItemClick", prevCurrentNoteGuid, rensoNotePressedItemGuid); } + } + + // ICHANGED + private void openTabEditor(String guid) { - // If the note is dirty, then it is unsynchronized by default. - if (noteDirty) - return; + Note note = conn.getNoteTable().getNote(guid, true, true, false, true, true); + // 新しいタブエディタを作成 + TabBrowse newBrowser = new TabBrowse(conn, tabBrowser, cbObserver); + showEditorButtons(newBrowser.getBrowserWindow()); - // Set the note as dirty and check if its status is synchronized in the display table - noteDirty = true; - if (listManager.getNoteMetadata().containsKey(currentNoteGuid) && - listManager.getNoteMetadata().get(currentNoteGuid).isDirty()) { - return; - } + String noteTitle = note.getTitle(); + int index = tabBrowser.addNewTab(newBrowser, noteTitle); + tabWindows.put(index, newBrowser); + noteDirty.put(index, false); - // If this wasn't already marked as unsynchronized, then we need to update the table - listManager.getNoteTableModel().updateNoteSyncStatus(currentNoteGuid, false); -// listManager.getUnsynchronizedNotes().add(currentNoteGuid); - for (int i=0; i histGuids = new ArrayList(); + 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(); + } + } + } + + // ICHANGED タブが閉じられた + private void tabWindowClosing(int index) { + // タブが1つしかなかったら閉じない + if (tabBrowser.count() <= 1) { + return; + } + + TabBrowse t = (TabBrowse) tabBrowser.widget(index); + String guid = t.getBrowserWindow().getNote().getGuid(); + String content = t.getBrowserWindow().getContent(); + BrowserWindow browser = t.getBrowserWindow(); + // ノートが変更されていたら保存 + if (t.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(); + + // ノートを削除 + tabWindows.remove(index); + tabBrowser.removeTab(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 tab = tabWindows.get(i + 1); + tabWindows.put(i, tab); + 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 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); + } + + // タブの閉じるボタンを押すと、tabWindowClosingより先にtabWindowChangedが呼ばれてしまうので、手動で呼びなおす + tabWindowChanged(tabBrowser.currentIndex()); + } + + @SuppressWarnings("unused") + private void noteAddNewTab() { + saveNote(); + + // ノート追加前に開いていたノートとの関連性を記録するために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); + } + } + } + } + + // ICHANGED + 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 histGuids = new ArrayList(); + historyGuids.put(index, histGuids); + historyPosition.put(index, 0); + fromHistory.put(index, false); + + tabBrowser.setCurrentIndex(index); + } + + //*************************************************************** + //*************************************************************** + //** These functions deal with Note specific things + //*************************************************************** + //*************************************************************** + // ICHANGED + private void setNoteDirty() { + for (String guid: selectedNoteGUIDs) { + setNoteDirty(guid); + } + } + + // ICHANGED + 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 tabIndexes = tabWindows.keySet(); + Iterator 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 ix = listManager.getNoteTableModel().itemData(modelIndex); String tableGuid = (String)ix.values().toArray()[0]; - if (tableGuid.equals(currentNoteGuid)) { + if (tableGuid.equals(targetGuid)) { listManager.getNoteTableModel().proxyModel.setData(i, Global.noteTableSynchronizedPosition, "false"); return; } @@ -4323,7 +5062,9 @@ public class NeverNote extends QMainWindow{ noteCache.remove(guid); noteCache.put(guid, unicode.toString()); if (guid.equals(currentNoteGuid)) { - noteDirty = true; + // ICHANGED + int index = tabBrowser.currentIndex(); + noteDirty.put(index, true); browserWindow.setContent(unicode); } if (save) { @@ -4332,12 +5073,38 @@ public class NeverNote extends QMainWindow{ } } + + // ICHANGED + 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() { - if (noteDirty) { - saveNote(currentNoteGuid, browserWindow); - thumbnailRunner.addWork("GENERATE "+ currentNoteGuid); - noteDirty = false; - } + // ICHANGED + // すべてのタブに対して、Dirtyを確認し、trueならセーブする + Collection dirtyIndex = noteDirty.keySet(); + Iterator 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()"); @@ -4373,14 +5140,16 @@ public class NeverNote extends QMainWindow{ browserWindow.setEnabled(false); return; } - inkNote = false; - readOnly = false; - if (Global.showDeleted || currentNoteGuid == null || currentNoteGuid.equals("")) - readOnly = true; + // ICHANGED + 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) { + if (readOnly.get(tabBrowser.currentIndex())) { browserWindow.setReadOnly(true); - return; } if (!reload) @@ -4390,23 +5159,40 @@ public class NeverNote extends QMainWindow{ browserWindow.loadingData(true); currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true); - if (currentNote == null) + if (currentNote == null) { + waitCursor(false); return; + } + + // ICHANGED + tabBrowser.setTabTitle(tabBrowser.currentIndex(), currentNote.getTitle()); + loadNoteBrowserInformation(browserWindow, currentNoteGuid, currentNote); } + // ICHANGED 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 or encoded characters are ugly js.append(""); js.append(""); js.append(""); - js.append(""); + js.append(""); if (Global.displayRightToLeft()) js.append(""); js.append(""); @@ -4424,42 +5210,58 @@ public class NeverNote extends QMainWindow{ noteCache.put(guid, js.toString()); if (formatter.resourceError) - resourceErrorMessage(); + resourceErrorMessage(tabIndex); if (formatter.formatError) { waitCursor(false); QMessageBox.information(this, tr("Error"), - tr("NixNote had issues formatting this note." + + tr("NeighborNote had issues formatting this note." + " To protect your data this note is being marked as read-only.")); waitCursor(true); } - readOnly = formatter.readOnly; - inkNote = formatter.inkNote; - if (readOnly) + + if (tabIndex >= 0) { + readOnly.put(tabIndex, formatter.readOnly); + inkNote.put(tabIndex, formatter.inkNote); + } + + if (tabIndex >= 0 && readOnly.get(tabIndex)) { readOnlyCache.put(guid, true); - if (inkNote) + } + 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)) - readOnly = true; - if (inkNoteCache.containsKey(guid)) - inkNote = true; + 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 (readOnly || inkNote) + 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); - browser.setReadOnly(readOnly); - deleteButton.setEnabled(!readOnly); - tagButton.setEnabled(!readOnly); - menuBar.noteDelete.setEnabled(!readOnly); - menuBar.noteTags.setEnabled(!readOnly); + 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 && @@ -4500,7 +5302,15 @@ public class NeverNote extends QMainWindow{ browser.setAllTags(tagList); browser.setCurrentTags(note.getTagNames()); - noteDirty = false; + // ICHANGED + 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); @@ -4513,14 +5323,34 @@ public class NeverNote extends QMainWindow{ waitCursor(false); logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNote"); } + + // ICHANGED + @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"); - browserWindow.toggleInformation(); + + // ICHANGED + 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() { @@ -4627,6 +5457,7 @@ public class NeverNote extends QMainWindow{ } if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals("")) selectedNoteGUIDs.add(currentNoteGuid); + closeTabs(selectedNoteGUIDs); for (int i=0; i noteGUIDs) { + Collection tabBrowsers = tabWindows.values(); + Iterator tabIterator = tabBrowsers.iterator(); + Collection tabIndexes = tabWindows.keySet(); + Iterator indexIterator = tabIndexes.iterator(); + List closeIndexes = new ArrayList(); //イテレータ操作中に中身をいじっちゃダメなので + + while (tabIterator.hasNext()) { + TabBrowse tab = tabIterator.next(); + int index = indexIterator.next(); + String guid = tab.getBrowserWindow().getNote().getGuid(); + + for(int i = 0; i < noteGUIDs.size(); i++){ + if(guid.equals(noteGUIDs.get(i))){ + closeIndexes.add(index); + } + } + } + + for(int i = closeIndexes.size() - 1; i >= 0; i--){ + tabWindowClosing(closeIndexes.get(i)); + } + } + + // 対象ノートを外部ウィンドウで開いていたら閉じる + private void closeExternalWindows(List noteGUIDs) { + Collection windows = externalWindows.values(); + Iterator windowIterator = windows.iterator(); + Collection guids = externalWindows.keySet(); + Iterator guidIterator = guids.iterator(); + List closeWindows = new ArrayList(); // イテレータ操作中に中身をいじっちゃダメなので + + while (windowIterator.hasNext()) { + ExternalBrowse browser = windowIterator.next(); + String guid = guidIterator.next(); + + for (int i = 0; i < noteGUIDs.size(); i++) { + if (guid.equals(noteGUIDs.get(i))) { + closeWindows.add(browser); + } + } + } + + for (int i = closeWindows.size() - 1; i >= 0; i--) { + closeWindows.get(i).close(); + } + } + // Add a new note - @SuppressWarnings("unused") private void addNote() { logger.log(logger.HIGH, "Inside NeverNote.addNote"); // browserWindow.setEnabled(true); @@ -4775,9 +5667,21 @@ public class NeverNote extends QMainWindow{ listManager.addNote(newNote, metadata); // noteTableView.insertRow(newNote, true, -1); + // ICHANGED + String prevCurrentNoteGuid = new String(currentNoteGuid); + currentNote = newNote; currentNoteGuid = currentNote.getGuid(); - noteTableView.clearSelection(); + // IFIXED こいつのせいで、ノート追加時にcurrentNoteGuidが更新されないので消す + // noteTableView.clearSelection(); + + // ICHANGED 新規に作成したノートとそれまで開いていたノートの関連性を追加 + 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(); @@ -4818,6 +5722,15 @@ public class NeverNote extends QMainWindow{ @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. @@ -4853,6 +5766,14 @@ public class NeverNote extends QMainWindow{ b.getBrowserWindow().getNote().setGuid(newGuid); externalWindows.put(newGuid, b); } + + // ICHANGED + 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 windows = externalWindows.values(); + Iterator windowIterator = windows.iterator(); + Collection guids = externalWindows.keySet(); + Iterator guidIterator = guids.iterator(); + List closeWindows = new ArrayList(); // イテレータ操作中に中身をいじっちゃダメなので + + 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(); + } + // ICHANGED ↑↑↑ここまで↑↑↑ + + // ICHANGED ↓↓↓ここから↓↓↓ + // マージしたノート(child)をタブで開いていたら、閉じる + Collection tabBrowsers = tabWindows.values(); + Iterator tabIterator = tabBrowsers.iterator(); + Collection tabIndexes = tabWindows.keySet(); + Iterator indexIterator = tabIndexes.iterator(); + List closeIndexes = new ArrayList(); //イテレータ操作中に中身をいじっちゃダメなので + + while (tabIterator.hasNext()) { + TabBrowse tab = tabIterator.next(); + int tabIndex = indexIterator.next(); + String guid = tab.getBrowserWindow().getNote().getGuid(); + + for(int i = 0; i < sources.size(); i++){ + if(guid.equals(sources.get(i))){ + closeIndexes.add(tabIndex); + } + } + } + + for(int i = closeIndexes.size() - 1; i >= 0; i--){ + tabWindowClosing(closeIndexes.get(i)); + } + // ICHANGED ↑↑↑ここまで↑↑↑ + noteIndexUpdated(false); + // IFIXED + // ICHANGED マージ後の新しいノートコンテンツを表示するためキャッシュを削除 + noteCache.remove(masterGuid); + refreshEvernoteNote(true); waitCursor(false); } @@ -5120,7 +6132,7 @@ public class NeverNote extends QMainWindow{ } } 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 NixNote to process. "+ + 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."); @@ -5209,7 +6221,9 @@ public class NeverNote extends QMainWindow{ // If we've gotten this far, we have a good note. if (historyWindow == null) { - historyWindow = new OnlineNoteHistory(logger, conn); + // ICHANGED + 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()"); @@ -5443,8 +6457,12 @@ public class NeverNote extends QMainWindow{ //********************************************************** //********************************************************** // An error has happended fetching a resource. let the user know - private void resourceErrorMessage() { - if (inkNote) + // ICHANGED + 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."+ @@ -5457,7 +6475,7 @@ public class NeverNote extends QMainWindow{ "Don't get angry. I'm doing it to prevent you from messing up\n"+ "this note on the Evernote servers. Sorry."+ "\n\nP.S. You might want to re-synchronize to see if it corrects this problem.\nWho knows, you might get lucky.")); - inkNote = true; + inkNote.put(tabIndex, true); browserWindow.setReadOnly(true); waitCursor(true); } @@ -5563,7 +6581,23 @@ public class NeverNote extends QMainWindow{ public void refreshLists() { logger.log(logger.EXTREME, "Entering NeverNote.refreshLists"); updateQuotaBar(); - listManager.refreshLists(currentNote, noteDirty, browserWindow.getContent()); + // ICHANGED + // すべてのタブのノートを調べて、Dirtyならばセーブする。その後refreshListsする。 + Collection tabIndex = noteDirty.keySet(); + Iterator indexIterator = tabIndex.iterator(); + HashMap saveNotes = new HashMap(); + HashMap saveContents = new HashMap(); + 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(); @@ -5621,7 +6655,7 @@ public class NeverNote extends QMainWindow{ thumbnailRunner.interrupt = true; indexRunner.addWork("SCAN"); } - logger.log(logger.EXTREME, "Leaving NixNote index timer"); + logger.log(logger.EXTREME, "Leaving NeighborNote index timer"); } @SuppressWarnings("unused") @@ -5655,7 +6689,7 @@ public class NeverNote extends QMainWindow{ 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 NixNote, saving the logs for later viewing, and restarting. Sorry.")); + "checking stopping NeighborNote, saving the logs for later viewing, and restarting. Sorry.")); disableTagThreadCheck = true; } } else @@ -5666,7 +6700,7 @@ public class NeverNote extends QMainWindow{ 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 NixNote, saving the logs for later viewing, and restarting. Sorry.")); + "checking stopping NeighborNote, saving the logs for later viewing, and restarting. Sorry.")); disableNotebookThreadCheck=true; } } else @@ -5677,7 +6711,7 @@ public class NeverNote extends QMainWindow{ 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 NixNote, saving the logs for later viewing, and restarting. Sorry.")); + "checking stopping NeighborNote, saving the logs for later viewing, and restarting. Sorry.")); disableTrashThreadCheck = true; } } else @@ -5688,7 +6722,7 @@ public class NeverNote extends QMainWindow{ 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 NixNote, saving the logs for later viewing, and restarting. Sorry.")); + "checking stopping NeighborNote, saving the logs for later viewing, and restarting. Sorry.")); disableSaveThreadCheck = true; } } else @@ -5698,7 +6732,7 @@ public class NeverNote extends QMainWindow{ 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 NixNote, saving the logs for later viewing, and restarting. Sorry.")); + "checking stopping NeighborNote, saving the logs for later viewing, and restarting. Sorry.")); disableSyncThreadCheck = true; } } else @@ -5708,13 +6742,21 @@ public class NeverNote extends QMainWindow{ 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 NixNote, saving the logs for later viewing, and restarting. Sorry.")); + "checking stopping NeighborNote, saving the logs for later viewing, and restarting. Sorry.")); disableIndexThreadCheck = true; } } else indexThreadDeadCount=0; - + if (!rensoNoteList.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() { @@ -5893,6 +6935,15 @@ public class NeverNote extends QMainWindow{ 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) { @@ -6025,12 +7076,26 @@ public class NeverNote extends QMainWindow{ // importKeepWatcher.addPath(records.get(i).folder.replace('\\', '/')); for (int i=0; i monitorDelete = importKeepWatcher.directories(); + for (int i=0; i"); + logger.log(logger.EXTREME, "List of directories being watched (delete)..."); + monitorDelete = importDeleteWatcher.directories(); + for (int i=0; i"); + importKeepWatcher.directoryChanged.connect(this, "folderImportKeep(String)"); importDeleteWatcher.directoryChanged.connect(this, "folderImportDelete(String)"); @@ -6047,6 +7112,8 @@ public class NeverNote extends QMainWindow{ } } } + + // Menu folderImport action triggered public void folderImport() { List recs = conn.getWatchFolderTable().getAll(); WatchFolder dialog = new WatchFolder(recs, listManager.getNotebookIndex()); @@ -6080,8 +7147,9 @@ public class NeverNote extends QMainWindow{ 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('/','\\'); @@ -6093,40 +7161,44 @@ public class NeverNote extends QMainWindow{ String notebook = conn.getWatchFolderTable().getNotebook(dirName); for (int i=0; i= 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 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); + + // 連想ノートリストを更新 + rensoNoteList.refreshRensoNoteList(currentNoteGuid); + } + + // ICHANGD + // 生存ノートテーブル→ゴミ箱(またはその逆)に切り替える + 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); + // ICHANGED ゴミ箱から元の画面に戻す。連想ノートリストを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); + // ICHANGED ゴミ箱を開く。連想ノートリストを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()); + } + + // ICHANGED + // ユーザが連想ノートリストのアイテムを選択した時の処理 + @SuppressWarnings("unused") + private void rensoNoteItemPressed(QListWidgetItem current) { + logger.log(logger.HIGH, "Nevernote.rensoNoteSelectionChangeに入った"); + + rensoNotePressedItemGuid = rensoNoteList.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 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を出た"); + } + + // ICHANGED + // 関連ノートリストからノートを除外する + @SuppressWarnings("unused") + private void excludeNote() { + if (rensoNotePressedItemGuid != null) { + saveNote(); + excludeNote(rensoNotePressedItemGuid); + } + } + + // ICHANGED + // 関連ノートリストからノートを除外する + 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); + + rensoNoteList.refreshRensoNoteList(currentNoteGuid); + } + + // ICHANGED + // 関連ノートリストのノートにスターを付ける + @SuppressWarnings("unused") + private void starNote() { + if (rensoNotePressedItemGuid != null) { + saveNote(); + starNote(rensoNotePressedItemGuid); + } + } + + // ICHANGED + // 関連ノートリストのノートにスターを付ける + private void starNote(String guid) { + // スター付きノートテーブルに追加 + conn.getStaredTable().addStaredItem(currentNoteGuid, guid); + + rensoNoteList.refreshRensoNoteList(currentNoteGuid); + } + + // ICHANGED + // 関連ノートリストのノートからスターを外す + @SuppressWarnings("unused") + private void unstarNote() { + if (rensoNotePressedItemGuid != null) { + saveNote(); + unstarNote(rensoNotePressedItemGuid); + } + } + + // ICHANGED + // 関連ノートリストのノートからスターを外す + private void unstarNote(String guid) { + // スター付きノートテーブルから削除 + conn.getStaredTable().removeStaredItem(currentNoteGuid, guid); + + rensoNoteList.refreshRensoNoteList(currentNoteGuid); + } + + // ICHANGED + // 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 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 rensoNoteList; + } }