OSDN Git Service

リリースノートの日本語が文字化けしていたのを修正。
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / NeverNote.java
1 /*
2   * This file is part of NixNote/NeighborNote 
3  * Copyright 2009 Randy Baumgarte
4  * Copyright 2013 Yuki Takahashi
5  * 
6  * This file may be licensed under the terms of of the
7  * GNU General Public License Version 2 (the ``GPL'').
8  *
9  * Software distributed under the License is distributed
10  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
11  * express or implied. See the GPL for the specific language
12  * governing rights and limitations.
13  *
14  * You should have received a copy of the GPL along with this
15  * program. If not, go to http://www.gnu.org/licenses/gpl.html
16  * or write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19 */
20 package cx.fbn.nevernote;
21 import java.awt.Desktop;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileNotFoundException;
25 import java.io.FileOutputStream;
26 import java.net.Authenticator;
27 import java.net.PasswordAuthentication;
28 import java.security.MessageDigest;
29 import java.security.NoSuchAlgorithmException;
30 import java.sql.Connection;
31 import java.sql.DriverManager;
32 import java.sql.SQLException;
33 import java.sql.Statement;
34 import java.text.SimpleDateFormat;
35 import java.util.ArrayList;
36 import java.util.Calendar;
37 import java.util.Collection;
38 import java.util.Collections;
39 import java.util.Comparator;
40 import java.util.Date;
41 import java.util.GregorianCalendar;
42 import java.util.HashMap;
43 import java.util.Iterator;
44 import java.util.List;
45 import java.util.SortedMap;
46 import java.util.Vector;
47
48 import org.apache.log4j.Level;
49 import org.apache.log4j.Logger;
50 import org.apache.thrift.TException;
51 import org.h2.tools.ChangeFileEncryption;
52
53 import com.evernote.edam.error.EDAMNotFoundException;
54 import com.evernote.edam.error.EDAMSystemException;
55 import com.evernote.edam.error.EDAMUserException;
56 import com.evernote.edam.notestore.NoteFilter;
57 import com.evernote.edam.notestore.NoteVersionId;
58 import com.evernote.edam.type.Data;
59 import com.evernote.edam.type.LinkedNotebook;
60 import com.evernote.edam.type.Note;
61 import com.evernote.edam.type.NoteAttributes;
62 import com.evernote.edam.type.Notebook;
63 import com.evernote.edam.type.Publishing;
64 import com.evernote.edam.type.QueryFormat;
65 import com.evernote.edam.type.Resource;
66 import com.evernote.edam.type.SavedSearch;
67 import com.evernote.edam.type.Tag;
68 import com.evernote.edam.type.User;
69 import com.trolltech.qt.QThread;
70 import com.trolltech.qt.core.QByteArray;
71 import com.trolltech.qt.core.QDateTime;
72 import com.trolltech.qt.core.QDir;
73 import com.trolltech.qt.core.QEvent;
74 import com.trolltech.qt.core.QFile;
75 import com.trolltech.qt.core.QFileInfo;
76 import com.trolltech.qt.core.QFileSystemWatcher;
77 import com.trolltech.qt.core.QIODevice;
78 import com.trolltech.qt.core.QIODevice.OpenModeFlag;
79 import com.trolltech.qt.core.QLocale;
80 import com.trolltech.qt.core.QMimeData;
81 import com.trolltech.qt.core.QModelIndex;
82 import com.trolltech.qt.core.QSize;
83 import com.trolltech.qt.core.QTemporaryFile;
84 import com.trolltech.qt.core.QTextCodec;
85 import com.trolltech.qt.core.QTextStream;
86 import com.trolltech.qt.core.QThreadPool;
87 import com.trolltech.qt.core.QTimer;
88 import com.trolltech.qt.core.QTranslator;
89 import com.trolltech.qt.core.QUrl;
90 import com.trolltech.qt.core.Qt;
91 import com.trolltech.qt.core.Qt.BGMode;
92 import com.trolltech.qt.core.Qt.DockWidgetArea;
93 import com.trolltech.qt.core.Qt.ItemDataRole;
94 import com.trolltech.qt.core.Qt.KeyboardModifier;
95 import com.trolltech.qt.core.Qt.MouseButton;
96 import com.trolltech.qt.core.Qt.SortOrder;
97 import com.trolltech.qt.core.Qt.WidgetAttribute;
98 import com.trolltech.qt.gui.QAbstractItemView;
99 import com.trolltech.qt.gui.QAbstractItemView.ScrollHint;
100 import com.trolltech.qt.gui.QAction;
101 import com.trolltech.qt.gui.QApplication;
102 import com.trolltech.qt.gui.QClipboard;
103 import com.trolltech.qt.gui.QCloseEvent;
104 import com.trolltech.qt.gui.QColor;
105 import com.trolltech.qt.gui.QComboBox;
106 import com.trolltech.qt.gui.QCursor;
107 import com.trolltech.qt.gui.QDesktopServices;
108 import com.trolltech.qt.gui.QDialog;
109 import com.trolltech.qt.gui.QDockWidget;
110 import com.trolltech.qt.gui.QFileDialog;
111 import com.trolltech.qt.gui.QFileDialog.AcceptMode;
112 import com.trolltech.qt.gui.QFileDialog.FileMode;
113 import com.trolltech.qt.gui.QGridLayout;
114 import com.trolltech.qt.gui.QHBoxLayout;
115 import com.trolltech.qt.gui.QIcon;
116 import com.trolltech.qt.gui.QImage;
117 import com.trolltech.qt.gui.QKeySequence;
118 import com.trolltech.qt.gui.QLabel;
119 import com.trolltech.qt.gui.QListWidgetItem;
120 import com.trolltech.qt.gui.QMainWindow;
121 import com.trolltech.qt.gui.QMenu;
122 import com.trolltech.qt.gui.QMessageBox;
123 import com.trolltech.qt.gui.QMessageBox.StandardButton;
124 import com.trolltech.qt.gui.QPainter;
125 import com.trolltech.qt.gui.QPalette.ColorRole;
126 import com.trolltech.qt.gui.QPixmap;
127 import com.trolltech.qt.gui.QPrintDialog;
128 import com.trolltech.qt.gui.QPrinter;
129 import com.trolltech.qt.gui.QShortcut;
130 import com.trolltech.qt.gui.QSizePolicy;
131 import com.trolltech.qt.gui.QSizePolicy.Policy;
132 import com.trolltech.qt.gui.QSpinBox;
133 import com.trolltech.qt.gui.QSplashScreen;
134 import com.trolltech.qt.gui.QSplitter;
135 import com.trolltech.qt.gui.QStatusBar;
136 import com.trolltech.qt.gui.QSystemTrayIcon;
137 import com.trolltech.qt.gui.QTableWidgetItem;
138 import com.trolltech.qt.gui.QTextEdit;
139 import com.trolltech.qt.gui.QToolBar;
140 import com.trolltech.qt.gui.QTreeWidgetItem;
141 import com.trolltech.qt.network.QNetworkAccessManager;
142 import com.trolltech.qt.network.QNetworkProxy;
143 import com.trolltech.qt.network.QNetworkProxy.ProxyType;
144 import com.trolltech.qt.network.QNetworkReply;
145 import com.trolltech.qt.network.QNetworkRequest;
146 import com.trolltech.qt.webkit.QWebPage.WebAction;
147 import com.trolltech.qt.webkit.QWebSettings;
148
149 import cx.fbn.nevernote.config.InitializationException;
150 import cx.fbn.nevernote.config.StartupConfig;
151 import cx.fbn.nevernote.dialog.AccountDialog;
152 import cx.fbn.nevernote.dialog.ConfigDialog;
153 import cx.fbn.nevernote.dialog.DBEncryptDialog;
154 import cx.fbn.nevernote.dialog.DatabaseLoginDialog;
155 import cx.fbn.nevernote.dialog.DatabaseStatus;
156 import cx.fbn.nevernote.dialog.FindDialog;
157 import cx.fbn.nevernote.dialog.IgnoreSync;
158 import cx.fbn.nevernote.dialog.LogFileDialog;
159 import cx.fbn.nevernote.dialog.NotebookArchive;
160 import cx.fbn.nevernote.dialog.NotebookEdit;
161 import cx.fbn.nevernote.dialog.OnlineNoteHistory;
162 import cx.fbn.nevernote.dialog.PublishNotebook;
163 import cx.fbn.nevernote.dialog.SavedSearchEdit;
164 import cx.fbn.nevernote.dialog.SetIcon;
165 import cx.fbn.nevernote.dialog.ShareNotebook;
166 import cx.fbn.nevernote.dialog.SharedNotebookSyncError;
167 import cx.fbn.nevernote.dialog.StackNotebook;
168 import cx.fbn.nevernote.dialog.SynchronizationRequiredWarning;
169 import cx.fbn.nevernote.dialog.TagEdit;
170 import cx.fbn.nevernote.dialog.TagMerge;
171 import cx.fbn.nevernote.dialog.ThumbnailViewer;
172 import cx.fbn.nevernote.dialog.UpgradeAvailableDialog;
173 import cx.fbn.nevernote.dialog.WatchFolder;
174 import cx.fbn.nevernote.evernote.NoteMetadata;
175 import cx.fbn.nevernote.filters.FilterEditorNotebooks;
176 import cx.fbn.nevernote.filters.FilterEditorTags;
177 import cx.fbn.nevernote.gui.AttributeTreeWidget;
178 import cx.fbn.nevernote.gui.BrowserWindow;
179 import cx.fbn.nevernote.gui.DateAttributeFilterTable;
180 import cx.fbn.nevernote.gui.ExternalBrowse;
181 import cx.fbn.nevernote.gui.MainMenuBar;
182 import cx.fbn.nevernote.gui.NotebookTreeWidget;
183 import cx.fbn.nevernote.gui.RensoNoteList;
184 import cx.fbn.nevernote.gui.SavedSearchTreeWidget;
185 import cx.fbn.nevernote.gui.SearchPanel;
186 import cx.fbn.nevernote.gui.TabBrowse;
187 import cx.fbn.nevernote.gui.TabBrowserWidget;
188 import cx.fbn.nevernote.gui.TableView;
189 import cx.fbn.nevernote.gui.TagTreeWidget;
190 import cx.fbn.nevernote.gui.Thumbnailer;
191 import cx.fbn.nevernote.gui.TrashTreeWidget;
192 import cx.fbn.nevernote.gui.controls.QuotaProgressBar;
193 import cx.fbn.nevernote.neighbornote.ClipBoardObserver;
194 import cx.fbn.nevernote.oauth.OAuthTokenizer;
195 import cx.fbn.nevernote.oauth.OAuthWindow;
196 import cx.fbn.nevernote.sql.DatabaseConnection;
197 import cx.fbn.nevernote.sql.WatchFolderRecord;
198 import cx.fbn.nevernote.threads.IndexRunner;
199 import cx.fbn.nevernote.threads.SyncRunner;
200 import cx.fbn.nevernote.threads.ThumbnailRunner;
201 import cx.fbn.nevernote.utilities.AESEncrypter;
202 import cx.fbn.nevernote.utilities.ApplicationLogger;
203 import cx.fbn.nevernote.utilities.FileImporter;
204 import cx.fbn.nevernote.utilities.FileUtils;
205 import cx.fbn.nevernote.utilities.ListManager;
206 import cx.fbn.nevernote.utilities.SyncTimes;
207 import cx.fbn.nevernote.xml.ExportData;
208 import cx.fbn.nevernote.xml.ImportData;
209 import cx.fbn.nevernote.xml.ImportEnex;
210 import cx.fbn.nevernote.xml.NoteFormatter;
211
212
213 public class NeverNote extends QMainWindow{
214         
215         QStatusBar                              statusBar;                                      // Application status bar
216         
217         DatabaseConnection              conn;
218         
219         MainMenuBar                             menuBar;                                        // Main menu bar
220         FindDialog                              find;                                           // Text search in note dialog
221         List<String>                    emitLog;                                        // Messages displayed in the status bar;
222         QSystemTrayIcon                 trayIcon;                                       // little tray icon
223         QMenu                                   trayMenu;                                       // System tray menu
224         QAction                                 trayExitAction;                         // Exit the application
225         QAction                                 trayShowAction;                         // toggle the show/hide action          
226         QAction                                 trayAddNoteAction;                      // Add a note from the system tray
227         QNetworkAccessManager   versionChecker;                         // Used when checking for new versions
228         
229     NotebookTreeWidget          notebookTree;                           // List of notebooks
230     AttributeTreeWidget         attributeTree;                          // List of note attributes
231     TagTreeWidget                       tagTree;                                        // list of user created tags
232     SavedSearchTreeWidget       savedSearchTree;                        // list of saved searches
233     TrashTreeWidget                     trashTree;                                      // Trashcan
234     TableView                           noteTableView;                          //      List of notes (the widget).
235
236     public BrowserWindow        browserWindow;                          // Window containing browser & labels
237     public QToolBar             toolBar;                                        // The tool bar under the menu
238     QComboBox                           searchField;                            // search filter bar on the toolbar;
239     QShortcut                           searchShortcut;                         // Shortcut to search bar
240     boolean                                     searchPerformed = false;        // Search was done?
241     QuotaProgressBar            quotaBar;                                       // The current quota usage
242     
243     ApplicationLogger           logger;
244     List<String>                        selectedNotebookGUIDs;          // List of notebook GUIDs
245     List<String>                        selectedTagGUIDs;                       // List of selected tag GUIDs
246     List<String>                        selectedNoteGUIDs;                      // List of selected notes
247     String                                      selectedSavedSearchGUID;        // Currently selected saved searches
248     private final HashMap<String, ExternalBrowse>       externalWindows;        // Notes being edited by an external window;
249     
250     NoteFilter                          filter;                                         // Note filter
251     String                                      currentNoteGuid;                        // GUID of the current note 
252     Note                                        currentNote;                            // The currently viewed note
253     // ICHANGED
254     HashMap<Integer, Boolean>   noteDirty;                              // Has the note been changed?
255     HashMap<Integer, Boolean>   inkNote;                // if this is an ink note, it is read only
256     HashMap<Integer, Boolean>   readOnly;                               // Is this note read-only?
257         
258   
259     ListManager                         listManager;                                    // DB runnable task
260     
261     List<QTemporaryFile>        tempFiles;                                      // Array of temporary files;
262     
263     QTimer                                      indexTimer;                                     // timer to start the index thread
264     IndexRunner                         indexRunner;                            // thread to index notes
265     QThread                                     indexThread;
266     
267     QTimer                                      syncTimer;                                      // Sync on an interval
268     QTimer                                      syncDelayTimer;                         // Sync delay to free up database
269     SyncRunner                          syncRunner;                                     // thread to do a sync.
270     QThread                                     syncThread;                                     // Thread which talks to evernote
271     ThumbnailRunner                     thumbnailRunner;                        // Runner for thumbnail thread
272     QThread                                     thumbnailThread;                        // Thread that generates pretty pictures
273     QTimer                                      saveTimer;                                      // Timer to save note contents
274     
275     QTimer                                      authTimer;                                      // Refresh authentication
276     QTimer                                      externalFileSaveTimer;          // Save files altered externally
277     QTimer                                      thumbnailTimer;                         // Wakeup & scan for thumbnails
278     QTimer                                      debugTimer;
279     List<String>                        externalFiles;                          // External files to save later
280     List<String>                        importFilesKeep;                        // Auto-import files to save later
281     List<String>                        importFilesDelete;                      // Auto-import files to save later
282     
283     int                                         indexTime;                                      // how often to try and index
284     boolean                                     indexRunning;                           // Is indexing running?
285     boolean                                     indexDisabled;                          // Is indexing disabled?
286     
287     int                                         syncThreadsReady;                       // number of sync threads that are free
288     int                                         syncTime;                                       // Sync interval
289     boolean                                     syncRunning;                            // Is sync running?
290     boolean                                     automaticSync;                          // do sync automatically?
291     QTreeWidgetItem                     attributeTreeSelected;
292
293     QAction                             prevButton;                                     // Go to the previous item viewed
294     QAction                             nextButton;                                     // Go to the next item in the history
295     QAction                             downButton;                                     // Go to the next item in the list
296     QAction                             upButton;                                       // Go to the prev. item in the list;
297     QAction                             synchronizeButton;                      // Synchronize with Evernote
298     QAction                             allNotesButton;                         // Reset & view all notes
299     QTimer                              synchronizeAnimationTimer;      // Timer to change animation button
300     int                                 synchronizeIconAngle;           // Used to rotate sync icon
301     QAction                     printButton;                            // Print Button
302     QAction                             tagButton;                                      // Tag edit button
303     QAction                             attributeButton;                        // Attribute information button
304     QAction                     emailButton;                            // Email button
305     QAction                     deleteButton;                           // Delete button
306     QAction                             newButton;                                      // new Note Button;
307     QSpinBox                    zoomSpinner;                            // Zoom zoom
308     QAction                             searchClearButton;                      // Clear the search field
309     
310     SearchPanel                 searchLayout;                           // Widget to hold search field, zoom, & quota
311     
312     QSplitter                   mainLeftRightSplitter;          // main splitter for left/right side
313     QSplitter                   leftSplitter1;                          // first left hand splitter
314     QSplitter                   browserIndexSplitter;           // splitter between note index & note text
315     
316     QFileSystemWatcher  importKeepWatcher;                      // Watch & keep auto-import
317     QFileSystemWatcher  importDeleteWatcher;            // Watch & Delete auto-import
318     List<String>                importedFiles;                          // History of imported files (so we don't import twice)
319     
320     OnlineNoteHistory   historyWindow;                          // online history window 
321     List<NoteVersionId> versions;                                       // history versions
322     
323     QTimer                              threadMonitorTimer;                     // Timer to watch threads.
324     int                                 dbThreadDeadCount=0;            // number of consecutive dead times for the db thread
325     int                                 syncThreadDeadCount=0;          // number of consecutive dead times for the sync thread
326     int                                 indexThreadDeadCount=0;         // number of consecutive dead times for the index thread
327     int                                 notebookThreadDeadCount=0;      // number of consecutive dead times for the notebook thread
328     int                                 tagDeadCount=0;                         // number of consecutive dead times for the tag thread
329     int                                 trashDeadCount=0;                       // number of consecutive dead times for the trash thread
330     int                                 saveThreadDeadCount=0;          // number of consecutive dead times for the save thread
331     boolean                             disableTagThreadCheck=false;
332     boolean                             disableNotebookThreadCheck=false;
333     boolean                             disableTrashThreadCheck=false;
334     boolean                             disableSaveThreadCheck=false;
335     boolean                             disableSyncThreadCheck=false;
336     boolean                             disableIndexThreadCheck=false;
337     
338     HashMap<String, String>             noteCache;                      // Cash of note content 
339     HashMap<String, Boolean>    readOnlyCache;          // List of cashe notes that are read-only
340     HashMap<String, Boolean>    inkNoteCache;           // List of cache notes that are ink notes 
341         // ICHANGED
342         HashMap<Integer, ArrayList<String>> historyGuids;  // タブごとの以前見たノートのGUID
343         HashMap<Integer, Integer> historyPosition; // Position within the viewed items
344         HashMap<Integer, Boolean> fromHistory; // Is this from the history queue?
345         
346     String                              trashNoteGuid;                          // Guid to restore / set into or out of trash to save position
347     List<Thumbnailer>   thumbGenerators;                                // generate preview image
348     ThumbnailViewer             thumbnailViewer;                        // View preview thumbnail; 
349     boolean                             encryptOnShutdown;                      // should I encrypt when I close?
350     boolean                             decryptOnShutdown;                      // should I decrypt on shutdown;
351     String                              encryptCipher;                          // What cipher should I use?
352     //Signal0                   minimizeToTray;
353     boolean                             windowMaximized = false;        // Keep track of the window state for restores
354     List<String>                pdfReadyQueue;                          // Queue of PDFs that are ready to be rendered.
355     List<QPixmap>               syncIcons;                                      // Array of icons used in sync animation
356     private boolean             closeAction = false;            // Used to say when to close or when to minimize
357     private static Logger log = Logger.getLogger(NeverNote.class); 
358     private String              saveLastPath;                           // last path we used
359     private final QTimer                messageTimer;                           // Timer to clear the status message.
360     private QTimer              blockTimer;
361     BrowserWindow               blockingWindow;
362     
363         // ICHANGED
364         private final TabBrowserWidget tabBrowser; // ブラウザウィンドウをタブ化
365         private final HashMap<Integer, TabBrowse> tabWindows; // タブウィンドウ
366         private final RensoNoteList rensoNoteList; // 連想ノートリスト
367         private final QDockWidget rensoNoteListDock; // 連想ノートリストドックウィジェット
368         ClipBoardObserver cbObserver;
369         String rensoNotePressedItemGuid;
370         
371     String iconPath = new String("classpath:cx/fbn/nevernote/icons/");
372         
373         
374     //***************************************************************
375     //***************************************************************
376     //** Constructor & main entry point
377     //***************************************************************
378     //***************************************************************
379     // Application Constructor  
380         @SuppressWarnings("static-access")
381         public NeverNote(DatabaseConnection dbConn)  {
382                 // ICHANGED
383                 cbObserver = new ClipBoardObserver();
384                 
385                 conn = dbConn;          
386                 if (conn.getConnection() == null) {
387                         String msg = new String(tr("Unable to connect to the database.\n\nThe most probable reason is that some other process\n" +
388                                 "is accessing the database or NeighborNote is already running.\n\n" +
389                                 "Please end any other process or shutdown the other NeighborNote before starting.\n\nExiting program."));
390                         
391             QMessageBox.critical(null, tr("Database Connection Error") ,msg);
392                         System.exit(16);
393                 }
394                 setObjectName("mainWindow");
395 //              thread().setPriority(Thread.MAX_PRIORITY);
396                 
397                 logger = new ApplicationLogger("nevernote.log");
398                 logger.log(logger.HIGH, "Starting Application");
399                 
400                 decryptOnShutdown = false;
401                 encryptOnShutdown = false;
402                 conn.checkDatabaseVersion();
403                 
404                 
405                 
406                 // Start building the invalid XML tables
407                 Global.invalidElements = conn.getInvalidXMLTable().getInvalidElements();
408                 List<String> elements = conn.getInvalidXMLTable().getInvalidAttributeElements();
409                 
410                 for (int i=0; i<elements.size(); i++) {
411                         Global.invalidAttributes.put(elements.get(i), conn.getInvalidXMLTable().getInvalidAttributes(elements.get(i)));
412                 }
413                 
414                 logger.log(logger.EXTREME, "Starting GUI build");
415
416                 QTranslator nevernoteTranslator = new QTranslator();
417                 nevernoteTranslator.load(Global.getFileManager().getTranslateFilePath("nevernote_" + QLocale.system().name() + ".qm"));
418                 QApplication.instance().installTranslator(nevernoteTranslator);
419
420                 Global.originalPalette = QApplication.palette();
421                 QApplication.setStyle(Global.getStyle());
422                 if (Global.useStandardPalette())
423                         QApplication.setPalette(QApplication.style().standardPalette());
424         setWindowTitle(tr("NeighborNote"));
425
426         mainLeftRightSplitter = new QSplitter();
427                 // ICHANGED
428                 mainLeftRightSplitter.setOrientation(Qt.Orientation.Horizontal);
429                 
430         setCentralWidget(mainLeftRightSplitter);
431         leftSplitter1 = new QSplitter();
432         leftSplitter1.setOrientation(Qt.Orientation.Vertical);
433                 
434         browserIndexSplitter = new QSplitter();
435         browserIndexSplitter.setOrientation(Qt.Orientation.Vertical);
436         
437         //* Setup threads & thread timers
438 //        int indexRunnerCount = Global.getIndexThreads();
439 //       indexRunnerCount = 1;
440         QThreadPool.globalInstance().setMaxThreadCount(Global.threadCount);     // increase max thread count
441
442                 logger.log(logger.EXTREME, "Building list manager");
443         listManager = new ListManager(conn, logger);
444         
445                 logger.log(logger.EXTREME, "Building index runners & timers");
446                 // ICHANGED Global.getBehaviorDatabaseUrl()を追加
447                 indexRunner = new IndexRunner("indexRunner.log",
448                                 Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(),
449                                 Global.getResourceDatabaseUrl(),
450                                 Global.getBehaviorDatabaseUrl(), Global.getDatabaseUserid(),
451                                 Global.getDatabaseUserPassword(), Global.cipherPassword);
452                 
453                 indexThread = new QThread(indexRunner, "Index Thread");
454         indexRunner.indexAttachmentsLocally = Global.indexAttachmentsLocally();
455         indexRunner.indexImageRecognition = Global.indexImageRecognition();
456         indexRunner.indexNoteBody = Global.indexNoteBody();
457         indexRunner.indexNoteTitle = Global.indexNoteTitle();
458         indexRunner.specialIndexCharacters = Global.getSpecialIndexCharacters();
459                 indexThread.start();
460                 
461         synchronizeAnimationTimer = new QTimer();
462         synchronizeAnimationTimer.timeout.connect(this, "updateSyncButton()");
463         
464                 indexTimer = new QTimer();
465                 indexTime = 1000*Global.getIndexThreadSleepInterval();  
466                 indexTimer.start(indexTime);  // Start indexing timer
467                 indexTimer.timeout.connect(this, "indexTimer()");
468                 indexDisabled = false;
469                 indexRunning = false;
470                                 
471                 logger.log(logger.EXTREME, "Setting sync thread & timers");
472                 syncThreadsReady=1;
473                 // ICHANGED Global.getBehaviorDatabaseUrl()を追加
474                 syncRunner = new SyncRunner("syncRunner.log", Global.getDatabaseUrl(),
475                                 Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(),
476                                 Global.getBehaviorDatabaseUrl(), Global.getDatabaseUserid(),
477                                 Global.getDatabaseUserPassword(), Global.cipherPassword);
478                 
479                 syncTime = new SyncTimes().timeValue(Global.getSyncInterval());
480                 syncTimer = new QTimer();
481                 syncTimer.timeout.connect(this, "syncTimer()");
482         syncRunner.status.message.connect(this, "setMessage(String)");
483         syncRunner.syncSignal.finished.connect(this, "syncThreadComplete(Boolean)");
484         syncRunner.syncSignal.errorDisconnect.connect(this, "remoteErrorDisconnect()");
485         syncRunning = false;    
486                 if (syncTime > 0) {
487                         automaticSync = true;
488                         syncTimer.start(syncTime*60*1000);
489                 } else {
490                         automaticSync = false;
491                         syncTimer.stop();
492                 }
493                 syncRunner.setEvernoteUpdateCount(Global.getEvernoteUpdateCount());
494                 syncThread = new QThread(syncRunner, "Synchronization Thread");
495                 syncThread.start();
496                 
497                 
498                 logger.log(logger.EXTREME, "Starting thumnail thread");
499                 pdfReadyQueue = new ArrayList<String>();
500                 // ICHANGED Global.getBehaviorDatabaseUrl()を追加
501                 thumbnailRunner = new ThumbnailRunner("thumbnailRunner.log",
502                                 Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(),
503                                 Global.getResourceDatabaseUrl(),
504                                 Global.getBehaviorDatabaseUrl(), Global.getDatabaseUserid(),
505                                 Global.getDatabaseUserPassword(), Global.cipherPassword);
506                 
507                 thumbnailThread = new QThread(thumbnailRunner, "Thumbnail Thread");
508                 thumbnailRunner.noteSignal.thumbnailPageReady.connect(this, "thumbnailHTMLReady(String,QByteArray,Integer)");
509                 thumbnailThread.start();
510                 thumbGenerators = new ArrayList<Thumbnailer>();
511                 thumbnailTimer = new QTimer();
512                 thumbnailTimer.timeout.connect(this, "thumbnailTimer()");
513                 thumbnailTimer();
514                 thumbnailTimer.setInterval(500*1000);  // Thumbnail every minute
515                 thumbnailTimer.start();
516                 
517 //              debugTimer = new QTimer();
518 //              debugTimer.timeout.connect(this, "debugDirty()");
519 //              debugTimer.start(1000*60);
520                 
521                 logger.log(logger.EXTREME, "Starting authentication timer");
522                 authTimer = new QTimer();
523                 authTimer.timeout.connect(this, "authTimer()");
524                 authTimer.start(1000*60*15);
525                 syncRunner.syncSignal.authRefreshComplete.connect(this, "authRefreshComplete(boolean)");
526                 
527                 logger.log(logger.EXTREME, "Setting save note timer");
528                 saveTimer = new QTimer();
529                 saveTimer.timeout.connect(this, "saveNote()");
530                 if (Global.getAutoSaveInterval() > 0) {
531                         saveTimer.setInterval(1000*60*Global.getAutoSaveInterval()); 
532                         saveTimer.start();
533                 }
534                 listManager.saveRunner.noteSignals.noteSaveRunnerError.connect(this, "saveRunnerError(String, String)");
535                 
536                 logger.log(logger.EXTREME, "Starting external file monitor timer");
537                 externalFileSaveTimer = new QTimer();
538                 externalFileSaveTimer.timeout.connect(this, "externalFileEditedSaver()");
539                 externalFileSaveTimer.setInterval(1000*5);   // save every 5 seconds;
540                 externalFiles = new ArrayList<String>();
541                 importFilesDelete = new ArrayList<String>();
542                 importFilesKeep = new ArrayList<String>();
543                 externalFileSaveTimer.start();
544                 
545         notebookTree = new NotebookTreeWidget(conn);
546         attributeTree = new AttributeTreeWidget();
547         tagTree = new TagTreeWidget(conn);
548         savedSearchTree = new SavedSearchTreeWidget();
549         trashTree = new TrashTreeWidget();
550                 // ICHANGED
551                 noteTableView = new TableView(logger, listManager, this);     
552         
553         searchField = new QComboBox();
554         searchField.setObjectName("searchField");
555         //setStyleSheet("QComboBox#searchField { background-color: yellow }");
556         searchField.setEditable(true);
557         searchField.activatedIndex.connect(this, "searchFieldChanged()");
558         searchField.setDuplicatesEnabled(false);
559         searchField.editTextChanged.connect(this,"searchFieldTextChanged(String)");
560         searchShortcut = new QShortcut(this);
561         setupShortcut(searchShortcut, "Focus_Search");
562         searchShortcut.activated.connect(this, "focusSearch()");
563         
564         quotaBar = new QuotaProgressBar();
565         // Setup the zoom
566         zoomSpinner = new QSpinBox();
567         zoomSpinner.setMinimum(10);
568         zoomSpinner.setMaximum(1000);
569         zoomSpinner.setAccelerated(true);
570         zoomSpinner.setSingleStep(10);
571         zoomSpinner.setValue(100);
572         zoomSpinner.valueChanged.connect(this, "zoomChanged()");
573         
574         searchLayout = new SearchPanel(searchField, quotaBar, notebookTree, zoomSpinner);
575         
576         
577         QGridLayout leftGrid = new QGridLayout();
578         leftSplitter1.setContentsMargins(5, 0, 0, 7);
579         leftSplitter1.setLayout(leftGrid);
580         leftGrid.addWidget(searchLayout,1,1);
581         leftGrid.addWidget(tagTree,2,1);
582         leftGrid.addWidget(attributeTree,3,1);
583         leftGrid.addWidget(savedSearchTree,4,1);
584         leftGrid.addWidget(trashTree,5, 1);
585         
586         // Setup the browser window
587         noteCache = new HashMap<String,String>();
588         readOnlyCache = new HashMap<String, Boolean>();
589         inkNoteCache = new HashMap<String, Boolean>();
590         // ICHANGED
591         browserWindow = new BrowserWindow(conn, cbObserver);
592
593                 // ICHANGED 下から移動してきた。
594                 historyGuids = new HashMap<Integer, ArrayList<String>>();
595                 historyPosition = new HashMap<Integer, Integer>();
596                 fromHistory = new HashMap<Integer, Boolean>();
597                 
598                 // ICHANGED タブブラウザ作成
599                 tabWindows = new HashMap<Integer, TabBrowse>();
600                 tabBrowser = new TabBrowserWidget(this);
601                 tabBrowser.setStyleSheet("QTabBar::tab{width:150px;}");
602                 tabBrowser.setMovable(true);
603                 TabBrowse tab = new TabBrowse(conn, tabBrowser, cbObserver);
604                 browserWindow = tab.getBrowserWindow();
605                 int index = tabBrowser.addNewTab(tab, "");
606                 tabWindows.put(index, tab);
607                 tabBrowser.setTabsClosable(true);
608                 tabBrowser.currentChanged.connect(this, "tabWindowChanged(int)");
609                 tabBrowser.tabCloseRequested.connect(this, "tabWindowClosing(int)");
610                 
611                 noteDirty = new HashMap<Integer, Boolean>();
612                 noteDirty.put(index, false);
613                 
614                 inkNote = new HashMap<Integer, Boolean>();
615                 readOnly = new HashMap<Integer, Boolean>();
616
617                 // ICHANGED
618                 // 履歴記録のハッシュマップを初期化
619                 historyGuids.put(index, new ArrayList<String>());
620                 historyPosition.put(index, 0);
621                 fromHistory.put(index, false);
622                 
623         mainLeftRightSplitter.addWidget(leftSplitter1);
624         mainLeftRightSplitter.addWidget(browserIndexSplitter);
625         
626                 // ICHANGED
627                 // 連想ノートリストをセットアップ
628                 rensoNoteList = new RensoNoteList(conn, this);
629                 rensoNoteList.itemPressed.connect(this,
630                                 "rensoNoteItemPressed(QListWidgetItem)");
631                 rensoNoteListDock = new QDockWidget(tr("Renso Note List"), this);
632                 rensoNoteListDock.setWidget(rensoNoteList);
633                 addDockWidget(DockWidgetArea.RightDockWidgetArea, rensoNoteListDock);
634
635                 if (Global.getListView() == Global.View_List_Wide) {
636                         browserIndexSplitter.addWidget(noteTableView);
637                         // ICHANGED
638                         browserIndexSplitter.addWidget(tabBrowser);
639                         // browserIndexSplitter.addWidget(browserWindow);
640                 } else {
641                         mainLeftRightSplitter.addWidget(noteTableView);
642                         // ICHANGED
643                         mainLeftRightSplitter.addWidget(tabBrowser);
644                         // mainLeftRightSplitter.addWidget(browserWindow);
645                 }
646         
647         // Setup the thumbnail viewer
648         thumbnailViewer = new ThumbnailViewer();
649         thumbnailViewer.upArrow.connect(this, "upAction()");
650         thumbnailViewer.downArrow.connect(this, "downAction()");
651         thumbnailViewer.leftArrow.connect(this, "nextViewedAction()");
652         thumbnailViewer.rightArrow.connect(this, "previousViewedAction()");
653         
654         //Setup external browser manager
655         externalWindows = new HashMap<String, ExternalBrowse>();
656
657         listManager.loadNotesIndex();
658         initializeNotebookTree();
659         initializeTagTree();
660         initializeSavedSearchTree();
661         attributeTree.itemClicked.connect(this, "attributeTreeClicked(QTreeWidgetItem, Integer)");
662         attributeTreeSelected = null;
663         initializeNoteTable();    
664
665                 selectedNoteGUIDs = new ArrayList<String>();
666                 statusBar = new QStatusBar();
667                 setStatusBar(statusBar);
668                 menuBar = new MainMenuBar(this);
669                 emitLog = new ArrayList<String>();
670                 
671                 tagTree.setDeleteAction(menuBar.tagDeleteAction);
672                 tagTree.setMergeAction(menuBar.tagMergeAction);
673                 tagTree.setEditAction(menuBar.tagEditAction);
674                 tagTree.setAddAction(menuBar.tagAddAction);
675                 tagTree.setIconAction(menuBar.tagIconAction);
676                 tagTree.setVisible(Global.isWindowVisible("tagTree"));
677                 leftSplitter1.setVisible(Global.isWindowVisible("leftPanel"));
678                 tagTree.noteSignal.tagsAdded.connect(this, "tagsAdded(String, String)");
679                 menuBar.hideTags.setChecked(Global.isWindowVisible("tagTree"));
680                 listManager.tagSignal.listChanged.connect(this, "reloadTagTree()");
681                 
682                 if (!Global.isWindowVisible("zoom")) {
683                         searchLayout.hideZoom();
684                         menuBar.hideZoom.setChecked(false);
685                 } 
686         
687                 notebookTree.setDeleteAction(menuBar.notebookDeleteAction);
688                 notebookTree.setEditAction(menuBar.notebookEditAction);
689                 notebookTree.setAddAction(menuBar.notebookAddAction);
690                 notebookTree.setIconAction(menuBar.notebookIconAction);
691                 notebookTree.setStackAction(menuBar.notebookStackAction);
692                 notebookTree.setPublishAction(menuBar.notebookPublishAction);
693                 notebookTree.setShareAction(menuBar.notebookShareAction);
694                 notebookTree.setVisible(Global.isWindowVisible("notebookTree"));
695                 notebookTree.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
696                 notebookTree.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)");
697             notebookTree.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)");
698                 menuBar.hideNotebooks.setChecked(Global.isWindowVisible("notebookTree"));
699
700                 savedSearchTree.setAddAction(menuBar.savedSearchAddAction);
701                 savedSearchTree.setEditAction(menuBar.savedSearchEditAction);
702                 savedSearchTree.setDeleteAction(menuBar.savedSearchDeleteAction);
703                 savedSearchTree.setIconAction(menuBar.savedSearchIconAction);
704                 savedSearchTree.itemSelectionChanged.connect(this, "updateSavedSearchSelection()");
705                 savedSearchTree.setVisible(Global.isWindowVisible("savedSearchTree"));
706                 menuBar.hideSavedSearches.setChecked(Global.isWindowVisible("savedSearchTree"));
707                 
708                 // ICHANGED noteTableViewに新しいタブで開くを追加
709                 noteTableView.setOpenNewTabAction(menuBar.noteOpenNewTab);
710                         
711                 noteTableView.setAddAction(menuBar.noteAdd);
712                 
713                 // ICHANGED noteTableViewに新しいタブでノート追加を追加
714                 noteTableView.setAddNoteNewTabAction(menuBar.noteAddNewTab);
715                 
716                 noteTableView.setDeleteAction(menuBar.noteDelete);
717                 noteTableView.setRestoreAction(menuBar.noteRestoreAction);
718                 noteTableView.setNoteDuplicateAction(menuBar.noteDuplicateAction);
719                 noteTableView.setNoteHistoryAction(menuBar.noteOnlineHistoryAction);
720                 noteTableView.noteSignal.titleColorChanged.connect(this, "titleColorChanged(Integer)");
721                 noteTableView.noteSignal.notePinned.connect(this, "notePinned()");
722                 noteTableView.setMergeNotesAction(menuBar.noteMergeAction);
723                 noteTableView.setCopyAsUrlAction(menuBar.noteCopyAsUrlAction);
724                 noteTableView.doubleClicked.connect(this, "listDoubleClick()");
725                 listManager.trashSignal.countChanged.connect(trashTree, "updateCounts(Integer)");
726                 
727                 quotaBar.setMouseClickAction(menuBar.accountAction);
728                 
729                 trashTree.load();
730         trashTree.itemSelectionChanged.connect(this, "trashTreeSelection()");
731                 trashTree.setEmptyAction(menuBar.emptyTrashAction);
732                 trashTree.setVisible(Global.isWindowVisible("trashTree"));
733                 menuBar.hideTrash.setChecked(Global.isWindowVisible("trashTree"));
734                 trashTree.updateCounts(listManager.getTrashCount());
735                 attributeTree.setVisible(Global.isWindowVisible("attributeTree"));
736                 menuBar.hideAttributes.setChecked(Global.isWindowVisible("attributeTree"));
737
738                 noteTableView.setVisible(Global.isWindowVisible("noteList"));
739                 menuBar.hideNoteList.setChecked(Global.isWindowVisible("noteList"));
740                 
741                 if (!Global.isWindowVisible("editorButtonBar"))
742                         toggleEditorButtonBar();
743                 
744                 if (!Global.isWindowVisible("leftPanel"))
745                         menuBar.hideLeftSide.setChecked(true);
746                 if (Global.isWindowVisible("noteInformation"))
747                         toggleNoteInformation();
748                 quotaBar.setVisible(Global.isWindowVisible("quota"));
749                 // IFIXED quotaBar.isVisible() → Global.isWindowVisible("quota")
750                 // なぜかquotaBar.isVisible()が常にfalseを返すようなので修正
751                 if (!Global.isWindowVisible("quota"))
752                         menuBar.hideQuota.setChecked(false);
753                 
754                 searchField.setVisible(Global.isWindowVisible("searchField"));
755                 // IFIXED !searchField.isVisible() → !Global.isWindowVisible("searchField")
756                 // なぜかsearchField.isVisible()が常にfalseを返すようなので修正
757                 if (!Global.isWindowVisible("searchField"))
758                         menuBar.hideSearch.setChecked(false);
759                 
760                 if (searchField.isHidden() && quotaBar.isHidden() && zoomSpinner.isHidden() && notebookTree.isHidden())
761                         searchLayout.hide();
762                 
763                 setMenuBar(menuBar);
764                 setupToolBar();
765                 find = new FindDialog();
766                 find.getOkButton().clicked.connect(this, "doFindText()");
767                 
768                 // Setup the tray icon menu bar
769                 trayShowAction = new QAction(tr("Show/Hide"), this);
770                 trayExitAction = new QAction(tr("Exit"), this);
771                 trayAddNoteAction = new QAction(tr("Add Note"), this);
772                 
773                 trayExitAction.triggered.connect(this, "closeNeverNote()");
774                 trayAddNoteAction.triggered.connect(this, "addNote()");
775                 trayShowAction.triggered.connect(this, "trayToggleVisible()");
776                 
777                 trayMenu = new QMenu(this);
778                 trayMenu.addAction(trayAddNoteAction);
779                 trayMenu.addAction(trayShowAction);
780                 trayMenu.addAction(trayExitAction);
781                 
782                 
783                 trayIcon = new QSystemTrayIcon(this);
784                 trayIcon.setToolTip(tr("NeighborNote"));
785                 trayIcon.setContextMenu(trayMenu);
786                 trayIcon.activated.connect(this, "trayActivated(com.trolltech.qt.gui.QSystemTrayIcon$ActivationReason)");
787
788                 currentNoteGuid="";
789                 currentNoteGuid = Global.getLastViewedNoteGuid();
790                 if (currentNoteGuid.equals(""))
791                         currentNote = new Note();
792                 
793                 // ICHANGED
794                 /* 上に移動したので要らない
795                 historyGuids = new ArrayList<String>();
796                 historyPosition = 0;
797                 fromHistory = false;
798                 */
799                 
800                 if (!currentNoteGuid.trim().equals("")) {
801                         currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true);
802                 }
803                 
804                 noteIndexUpdated(true);
805                 showColumns();
806                 menuBar.showEditorBar.setChecked(Global.isWindowVisible("editorButtonBar"));
807                 if (menuBar.showEditorBar.isChecked())
808                 showEditorButtons(browserWindow);
809                 tagIndexUpdated(true);
810                 savedSearchIndexUpdated();
811                 notebookIndexUpdated();
812                 updateQuotaBar();
813         setupSyncSignalListeners();        
814         setupBrowserSignalListeners();
815         setupIndexListeners();
816               
817         
818         tagTree.tagSignal.listChanged.connect(this, "tagIndexUpdated()");
819         tagTree.showAllTags(true);
820
821                 QIcon appIcon = new QIcon(iconPath+"nevernote.png");
822                 if (QSystemTrayIcon.isSystemTrayAvailable()) {
823                         setWindowIcon(appIcon);
824                         trayIcon.setIcon(appIcon);
825                         if (Global.showTrayIcon() || Global.minimizeOnClose())
826                                 trayIcon.show();
827                         else
828                                 trayIcon.hide();
829                 }
830         
831         scrollToGuid(currentNoteGuid);
832         if (Global.automaticLogin()) {
833                 remoteConnect();
834                 if (Global.isConnected)
835                         syncTimer();
836         }
837         setupFolderImports();
838         
839         loadStyleSheet();
840         restoreWindowState(true);
841         
842         if (Global.mimicEvernoteInterface) {
843                 notebookTree.selectGuid("");
844         }
845         
846         threadMonitorTimer = new QTimer();
847         threadMonitorTimer.timeout.connect(this, "threadMonitorCheck()");
848         threadMonitorTimer.start(1000*10);  // Check for threads every 10 seconds;              
849         
850                 // ICHANGED たぶんこれはいらない
851                 // IFIXED ?
852                 /*
853                 historyGuids.add(currentNoteGuid);
854                 historyPosition = 1;
855                 */
856         
857         menuBar.blockSignals(true);
858         menuBar.narrowListView.blockSignals(true);
859         menuBar.wideListView.blockSignals(true);
860         if (Global.getListView() == Global.View_List_Narrow) { 
861                 menuBar.narrowListView.setChecked(true);
862         }
863         else{ 
864                 menuBar.wideListView.setChecked(true);
865         }
866         menuBar.blockSignals(false);
867         menuBar.narrowListView.blockSignals(false);
868         menuBar.wideListView.blockSignals(false);
869         
870                 // IFIXED
871                 // 上に同じコードがあるよね? とりあえずコメントアウト
872                 /*
873                  * if (Global.getListView() == Global.View_List_Wide) {
874                  * browserIndexSplitter.addWidget(noteTableView); // ICHANGED //
875                  * browserIndexSplitter.addWidget(tabBrowser);
876                  * browserIndexSplitter.addWidget(browserWindow); } else {
877                  * mainLeftRightSplitter.addWidget(noteTableView); // ICHANGED //
878                  * mainLeftRightSplitter.addWidget(tabBrowser);
879                  * mainLeftRightSplitter.addWidget(browserWindow); }
880                  */
881         
882                 messageTimer = new QTimer();
883                 messageTimer.timeout.connect(this, "clearMessage()");
884                 messageTimer.setInterval(1000*15);
885                 clearMessage();
886         
887         int sortCol = Global.getSortColumn();
888                 int sortOrder = Global.getSortOrder();
889                 noteTableView.proxyModel.blocked = true;
890                 // We sort the table twice to fix a bug.  For some reaosn the table won't sort properly if it is in narrow
891                 // list view and sorted descending on the date  created.  By sorting it twice it forces the proper sort.  Ugly.
892                 if (sortCol == 0 && sortOrder == 1 && Global.getListView() == Global.View_List_Narrow) 
893                         noteTableView.sortByColumn(sortCol, SortOrder.resolve(0));   
894                 noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder));
895                 noteTableView.proxyModel.blocked = false;
896                 noteTableView.proxyModel.sortChanged.connect(this, "tableSortOrderChanged(Integer,Integer)");
897                 
898                 // Set the startup notebook
899         String defaultNotebook = Global.getStartupNotebook();
900         if (!defaultNotebook.equals("AllNotebooks") && !defaultNotebook.equals("")) {
901                 for (int k=0; k<listManager.getNotebookIndex().size(); k++) {
902                         if (listManager.getNotebookIndex().get(k).isDefaultNotebook()) {
903                                 notebookTree.clearSelection();
904                                 notebookTree.selectGuid(listManager.getNotebookIndex().get(k).getGuid());
905                                 notebookTree.selectionSignal.emit();
906                         }
907                 }
908         }
909                 
910                 if (Global.checkVersionUpgrade()) {
911                         // ICHANGED TODO とりあえず封印
912                         // checkForUpdates();
913                 }
914         }
915         
916         
917         public void debugDirty() {
918                 List<Note> dirty = conn.getNoteTable().getDirty();
919                 logger.log(logger.LOW, "------ Dirty Notes List Begin ------");
920                 for (int i=0; i<dirty.size(); i++) {
921                         logger.log(logger.LOW, "GUID: " +dirty.get(i).getGuid() + " Title:" + dirty.get(i).getTitle());
922                 }
923                 logger.log(logger.LOW, "------ Dirty Notes List End ------");
924         }
925                 
926         // Main entry point
927         public static void main(String[] args) {
928                 log.setLevel(Level.FATAL);
929                 QApplication.initialize(args);
930                 QPixmap pixmap = new QPixmap("classpath:cx/fbn/nevernote/icons/splash_logo.png");
931                 QSplashScreen splash = new QSplashScreen(pixmap);
932                 boolean showSplash;
933                 
934                 DatabaseConnection dbConn;
935
936         try {
937             initializeGlobalSettings(args);
938
939             showSplash = Global.isWindowVisible("SplashScreen");
940             if (showSplash)
941                 splash.show();
942
943             dbConn = setupDatabaseConnection();
944
945             // Must be last stage of setup - only safe once DB is open hence we know we are the only instance running
946             Global.getFileManager().purgeResDirectory(true);
947
948         } catch (InitializationException e) {
949             // Fatal
950             e.printStackTrace();
951             QMessageBox.critical(null, "Startup error", "Aborting: " + e.getMessage());
952             return;
953         }
954         
955                 // Setup proxy crap
956                 String proxyUrl = Global.getProxyValue("url");
957                 String proxyPort = Global.getProxyValue("port");
958                 String proxyUserid = Global.getProxyValue("userid");
959                 String proxyPassword = Global.getProxyValue("password");
960                 boolean proxySet = false;
961                 QNetworkProxy proxy = new QNetworkProxy();
962                 proxy.setType(ProxyType.HttpProxy);
963                 if (!proxyUrl.trim().equals("")) {
964                         System.out.println("Proxy URL found: " +proxyUrl);
965                         proxySet = true;
966                         proxy.setHostName(proxyUrl);
967                 }
968                 if (!proxyPort.trim().equals("")) {
969                         System.out.println("Proxy Port found: " +proxyPort);
970                         proxySet = true;
971                         proxy.setPort(Integer.parseInt(proxyPort));
972                 }
973                 if (!proxyUserid.trim().equals("")) {
974                         System.out.println("Proxy Userid found: " +proxyUserid);
975                         proxySet = true;
976                         proxy.setUser(proxyUserid);
977                 }
978                 if (!proxyPassword.trim().equals("")) {
979                         System.out.println("Proxy URL found: " +proxyPassword);
980                         proxySet = true;
981                         proxy.setPassword(proxyPassword);
982                 }
983                 if (proxySet) {
984                         QNetworkProxy.setApplicationProxy(proxy);
985                 }
986                         
987
988         NeverNote application = new NeverNote(dbConn);
989                 if (Global.syncOnly) {
990                         System.out.println("Performing synchronization only.");
991                         application.remoteConnect();
992                         if (Global.isConnected) {
993                                 application.syncRunner.syncNeeded = true;
994                                 application.syncRunner.addWork("SYNC");
995                                 application.syncRunner.addWork("STOP");
996                                 while(!application.syncRunner.isIdle());
997                                 application.closeNeverNote();
998                         }
999                         return;
1000                 }
1001
1002                 application.setAttribute(WidgetAttribute.WA_DeleteOnClose, true);
1003                 if (Global.startMinimized()) 
1004                         application.showMinimized();
1005                 else {
1006                         if (Global.wasWindowMaximized())
1007                                 application.showMaximized();
1008                         else
1009                                 application.show();
1010                 }
1011                 
1012                 if (showSplash)
1013                         splash.finish(application);
1014                 QApplication.exec();
1015                 System.out.println("Goodbye.");
1016                 QApplication.exit();
1017         }
1018
1019     /**
1020      * Open the internal database, or create if not present
1021      *
1022      * @throws InitializationException when opening the database fails, e.g. because another process has it locked
1023      */
1024     private static DatabaseConnection setupDatabaseConnection() throws InitializationException {
1025         ApplicationLogger logger = new ApplicationLogger("nevernote-database.log");
1026         
1027         File f = Global.getFileManager().getDbDirFile(Global.databaseName + ".h2.db");
1028         File fr = Global.getFileManager().getDbDirFile(Global.resourceDatabaseName + ".h2.db");
1029                 // IFIXED resourceDatabaseNameになっていたので修正
1030                 File fi = Global.getFileManager().getDbDirFile(Global.indexDatabaseName + ".h2.db");
1031                 // ICHANGED
1032                 File fb = Global.getFileManager().getDbDirFile(Global.behaviorDatabaseName + ".h2.db");
1033                                 
1034                 if (!f.exists())
1035                         Global.setDatabaseUrl("");
1036                 if (!fr.exists())
1037                         Global.setResourceDatabaseUrl("");              
1038                 if (!fi.exists())
1039                         Global.setIndexDatabaseUrl(""); 
1040                 // ICHANGED
1041                 if (!fb.exists())
1042                         Global.setBehaviorDatabaseUrl("");
1043         
1044         if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") > -1) {
1045             boolean goodCheck = false;
1046             while (!goodCheck) {
1047                 DatabaseLoginDialog dialog = new DatabaseLoginDialog();
1048                 dialog.exec();
1049                 if (!dialog.okPressed())
1050                     System.exit(0);
1051                 Global.cipherPassword = dialog.getPassword();
1052                 goodCheck = databaseCheck(Global.getDatabaseUrl(), Global.getDatabaseUserid(),
1053                         Global.getDatabaseUserPassword(), Global.cipherPassword);
1054             }
1055         }
1056         // ICHANGED Global.getBehaviorDatabaserUrl()を追加
1057         DatabaseConnection dbConn = new DatabaseConnection(logger,Global.getDatabaseUrl(), 
1058                         Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), Global.getBehaviorDatabaseUrl(),
1059                         Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword, 0);
1060        return dbConn;
1061     }
1062     
1063     // Encrypt the database upon shutdown
1064     private void encryptOnShutdown() {
1065         String dbPath= Global.getFileManager().getDbDirPath("");
1066         try {
1067                 
1068                 Statement st = conn.getConnection().createStatement();  
1069                 st.execute("shutdown");
1070                 st = conn.getResourceConnection().createStatement();
1071                 st.execute("shutdown");
1072                 st = conn.getIndexConnection().createStatement();
1073                 st.execute("shutdown");
1074                 // ICHANGED
1075                 st = conn.getBehaviorConnection().createStatement();
1076                 st.execute("shutdown");
1077                 
1078                 if (QMessageBox.question(this, tr("Are you sure"), 
1079                                 tr("Are you sure you wish to encrypt the database?"),
1080                                 QMessageBox.StandardButton.Yes, 
1081                                 QMessageBox.StandardButton.No) == StandardButton.Yes.value()) {
1082                         ChangeFileEncryption.execute(dbPath, "NeverNote", encryptCipher, null, Global.cipherPassword.toCharArray(), true);
1083                         ChangeFileEncryption.execute(dbPath, "Resources", encryptCipher, null, Global.cipherPassword.toCharArray(), true);
1084                         ChangeFileEncryption.execute(dbPath, "Index", encryptCipher, null, Global.cipherPassword.toCharArray(), true);
1085                         // ICHANGED
1086                         ChangeFileEncryption.execute(dbPath, "Behavior", encryptCipher, null, Global.cipherPassword.toCharArray(), true);
1087                         
1088                         Global.setDatabaseUrl(Global.getDatabaseUrl() + ";CIPHER="+encryptCipher);
1089                         Global.setResourceDatabaseUrl(Global.getResourceDatabaseUrl() + ";CIPHER="+encryptCipher);
1090                         Global.setIndexDatabaseUrl(Global.getIndexDatabaseUrl() + ";CIPHER="+encryptCipher);
1091                         // ICHANGED
1092                                 Global.setBehaviorDatabaseUrl(Global.getBehaviorDatabaseUrl() + ";CIPHER=" + encryptCipher);
1093
1094                         QMessageBox.information(this, tr("Encryption Complete"), tr("Encryption is complete"));
1095                 }
1096         } catch (SQLException e) {
1097                         e.printStackTrace();
1098                 }       
1099     }
1100     
1101     // Decrypt the database upon shutdown
1102     private void decryptOnShutdown() {
1103         String dbPath= Global.getFileManager().getDbDirPath("");
1104         String dbName = "NeverNote";
1105         try {
1106                 Statement st = conn.getConnection().createStatement();  
1107                 st.execute("shutdown");
1108                 if (Global.getDatabaseUrl().toUpperCase().indexOf(";CIPHER=AES") > -1)
1109                         encryptCipher = "AES";
1110                 else
1111                         encryptCipher = "XTEA";
1112                 if (QMessageBox.question(this, tr("Confirmation"), tr("Are you sure", 
1113                                 "Are you sure you wish to decrypt the database?"),
1114                                 QMessageBox.StandardButton.Yes, 
1115                                 QMessageBox.StandardButton.No) == StandardButton.Yes.value()) {
1116
1117                         ChangeFileEncryption.execute(dbPath, dbName, encryptCipher, Global.cipherPassword.toCharArray(), null, true);
1118                         Global.setDatabaseUrl("");
1119                         Global.setResourceDatabaseUrl("");
1120                         Global.setIndexDatabaseUrl("");
1121                         QMessageBox.information(this, tr("Decryption Complete"), tr("Decryption is complete"));
1122                 }
1123                 } catch (SQLException e) {
1124                         e.printStackTrace();
1125                 }       
1126     }
1127     /**
1128      * Encrypt/Decrypt the local database
1129      **/
1130     public void doDatabaseEncrypt() {
1131         // The database is not currently encrypted
1132         if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") == -1) {
1133                 if (QMessageBox.question(this, tr("Confirmation"), tr("Encrypting the database is used" +
1134                                 "to enhance security and is performed\nupon shutdown, but please be aware that if"+
1135                                 " you lose the password your\nis lost forever.\n\nIt is highly recommended you " +
1136                                 "perform a backup and/or fully synchronize\n prior to executing this funtction.\n\n" +
1137                                 "Do you wish to proceed?"),
1138                                 QMessageBox.StandardButton.Yes, 
1139                                 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1140                                 return;
1141                 }
1142                 DBEncryptDialog dialog = new DBEncryptDialog();
1143                 dialog.exec();
1144                 if (dialog.okPressed()) {
1145                         Global.cipherPassword = dialog.getPassword();
1146                         encryptOnShutdown  = true;
1147                         encryptCipher = dialog.getEncryptionMethod();
1148                 }
1149         } else {
1150             DBEncryptDialog dialog = new DBEncryptDialog();
1151             dialog.setWindowTitle(tr("Database Decryption"));
1152             dialog.hideEncryption();
1153             dialog.exec();
1154             if (dialog.okPressed()) {
1155                 if (!dialog.getPassword().equals(Global.cipherPassword)) {
1156                         QMessageBox.critical(null, tr("Incorrect Password"), tr("Incorrect Password"));
1157                         return;
1158                 }
1159                 decryptOnShutdown  = true;
1160                 encryptCipher = "";
1161             }
1162         }
1163         return;
1164     }
1165
1166         private static void initializeGlobalSettings(String[] args) throws InitializationException {
1167                 StartupConfig   startupConfig = new StartupConfig();
1168
1169         for (String arg : args) {
1170             String lower = arg.toLowerCase();
1171             if (lower.startsWith("--name="))
1172                startupConfig.setName(arg.substring(arg.indexOf('=') + 1));
1173             if (lower.startsWith("--home="))
1174                startupConfig.setHomeDirPath(arg.substring(arg.indexOf('=') + 1));
1175             if (lower.startsWith("--disable-viewing"))
1176                startupConfig.setDisableViewing(true);
1177             if (lower.startsWith("--sync-only=true"))
1178                 startupConfig.setSyncOnly(true);
1179         }
1180         Global.setup(startupConfig);
1181         
1182     }
1183
1184     // Exit point
1185         @Override
1186         public void closeEvent(QCloseEvent event) {     
1187                 if (Global.minimizeOnClose() && !closeAction) {
1188                         event.ignore();
1189                         hide();
1190                         return;
1191                 }
1192                 logger.log(logger.HIGH, "Entering NeverNote.closeEvent");
1193                 waitCursor(true);
1194                 
1195                 if (currentNote != null & browserWindow != null) {
1196                         if (currentNote.getTitle() != null && browserWindow != null
1197                                         && !currentNote.getTitle().equals(browserWindow.getTitle()))
1198                                 conn.getNoteTable().updateNoteTitle(currentNote.getGuid(),
1199                                                 browserWindow.getTitle());
1200                 }
1201                 
1202                 saveNote();
1203                 setMessage(tr("Beginning shutdown."));
1204                 
1205                 // Close down external windows
1206                 Collection<ExternalBrowse> windows = externalWindows.values();
1207                 Iterator<ExternalBrowse> iterator = windows.iterator();
1208                 while (iterator.hasNext()) {
1209                         ExternalBrowse browser = iterator.next();
1210                         browser.windowClosing.disconnect();
1211                         browser.close();
1212                 }
1213                 
1214                 // ICHANGED タブブラウザに対してクローズ処理を行う
1215                 Collection<TabBrowse> win = tabWindows.values();
1216                 Iterator<TabBrowse> it = win.iterator();
1217                 tabBrowser.currentChanged.disconnect();
1218                 tabBrowser.tabCloseRequested.disconnect();
1219                 while (it.hasNext()) {
1220                         TabBrowse browser = it.next();
1221                         browser.close();
1222                 }
1223                 
1224                 externalFileEditedSaver();
1225                 if (Global.isConnected && Global.synchronizeOnClose()) {
1226                         setMessage(tr("Performing synchronization before closing."));
1227                         syncRunner.syncNeeded = true;
1228                         syncRunner.addWork("SYNC");
1229                 } else {
1230                         syncRunner.keepRunning = false;
1231                 }
1232                 syncRunner.addWork("STOP");
1233                 setMessage("Closing Program.");
1234                 threadMonitorTimer.stop();
1235
1236                 thumbnailRunner.addWork("STOP");
1237                 indexRunner.addWork("STOP");
1238                 saveNote();
1239                 listManager.stop();
1240                 saveWindowState();
1241
1242                 if (tempFiles != null)
1243                         tempFiles.clear();
1244
1245                 browserWindow.noteSignal.tagsChanged.disconnect();
1246                 browserWindow.noteSignal.titleChanged.disconnect();
1247                 browserWindow.noteSignal.noteChanged.disconnect();
1248                 browserWindow.noteSignal.notebookChanged.disconnect();
1249                 browserWindow.noteSignal.createdDateChanged.disconnect();
1250                 browserWindow.noteSignal.alteredDateChanged.disconnect();
1251                 syncRunner.searchSignal.listChanged.disconnect();
1252                 syncRunner.tagSignal.listChanged.disconnect();
1253         syncRunner.notebookSignal.listChanged.disconnect();
1254         syncRunner.noteIndexSignal.listChanged.disconnect();
1255
1256                 if (isVisible())
1257                         Global.saveWindowVisible("toolBar", toolBar.isVisible());
1258                 saveNoteColumnPositions();
1259                 saveNoteIndexWidth();
1260                 
1261                 int width = notebookTree.columnWidth(0);
1262                 Global.setColumnWidth("notebookTreeName", width);
1263                 width = tagTree.columnWidth(0);
1264                 Global.setColumnWidth("tagTreeName", width);
1265                 
1266                 Global.saveWindowMaximized(isMaximized());
1267                 Global.saveCurrentNoteGuid(currentNoteGuid);
1268                         
1269                 int sortCol = noteTableView.proxyModel.sortColumn();
1270                 int sortOrder = noteTableView.proxyModel.sortOrder().value();
1271                 Global.setSortColumn(sortCol);
1272                 Global.setSortOrder(sortOrder);
1273                 
1274                 hide();
1275                 trayIcon.hide();
1276                 Global.keepRunning = false;
1277                 try {
1278                         logger.log(logger.MEDIUM, "Waiting for indexThread to stop");
1279                         if (indexRunner.thread().isAlive())
1280                                 indexRunner.thread().join(50);
1281                         if (!indexRunner.thread().isAlive())
1282                                 logger.log(logger.MEDIUM, "Index thread has stopped");
1283                         else {
1284                                 logger.log(logger.MEDIUM, "Index thread still running - interrupting");
1285                                 indexRunner.thread().interrupt();
1286                         }
1287                 } catch (InterruptedException e1) {
1288                         e1.printStackTrace();
1289                 }
1290                 
1291                 if (!syncRunner.thread().isAlive()) {
1292                         logger.log(logger.MEDIUM, "Waiting for syncThread to stop");
1293                         if (syncRunner.thread().isAlive()) {
1294                                 System.out.println(tr("Synchronizing.  Please be patient."));
1295                                 for(;syncRunner.thread().isAlive();) {
1296                                         try {
1297                                                 wait(10);
1298                                         } catch (InterruptedException e) {
1299                                                 e.printStackTrace();
1300                                         }
1301                                 }
1302                         }
1303                         logger.log(logger.MEDIUM, "Sync thread has stopped");
1304                 }
1305
1306                 if (encryptOnShutdown) {
1307                         encryptOnShutdown();
1308                 }
1309                 if (decryptOnShutdown) {
1310                         decryptOnShutdown();
1311                 }
1312                 try {
1313                         Global.getFileManager().purgeResDirectory(false);
1314                 } catch (InitializationException e) {
1315                         System.out.println(tr("Empty res directory purge failed"));
1316                         e.printStackTrace();
1317                 }
1318                 logger.log(logger.HIGH, "Leaving NeverNote.closeEvent");
1319         }
1320
1321
1322         private void closeNeverNote() {
1323                 closeAction = true;
1324                 close();
1325         }
1326         public void setMessage(String s) {
1327                 if (logger != null) 
1328                         logger.log(logger.HIGH, "Entering NeverNote.setMessage");
1329                 else
1330                         System.out.println("*** ERROR *** " +s);
1331                 
1332                 if (statusBar != null) {
1333                         statusBar.show();
1334                         if (logger != null) 
1335                                 logger.log(logger.HIGH, "Message: " +s);
1336                         statusBar.showMessage(s);
1337                         if (emitLog != null)
1338                                 emitLog.add(s);
1339                 
1340                         if (messageTimer != null) {
1341                                 messageTimer.stop();
1342                                 messageTimer.setSingleShot(true);
1343                                 messageTimer.start();
1344                         }
1345                 }
1346                         
1347                 if (logger != null) 
1348                         logger.log(logger.HIGH, "Leaving NeverNote.setMessage");
1349         }
1350         
1351         private void clearMessage() {
1352                 statusBar.clearMessage();
1353                 statusBar.hide();
1354         }
1355                 
1356         private void waitCursor(boolean wait) {
1357                 if (wait) {
1358                         if (QApplication.overrideCursor() == null)
1359                                 QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.WaitCursor));
1360                 }
1361                 else {
1362                         if (QApplication.overrideCursor() != null)
1363                                 QApplication.restoreOverrideCursor();
1364                         else
1365                                 QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.ArrowCursor));
1366                 }
1367                 listManager.refreshCounters();
1368         }
1369         
1370         private void setupIndexListeners() {
1371 //              indexRunner.noteSignal.noteIndexed.connect(this, "indexThreadComplete(String)");
1372 //              indexRunner.resourceSignal.resourceIndexed.connect(this, "indexThreadComplete(String)");
1373                 indexRunner.signal.indexStarted.connect(this, "indexStarted()");
1374                 indexRunner.signal.indexFinished.connect(this, "indexComplete()");
1375         }
1376         private void setupSyncSignalListeners() {
1377                 syncRunner.tagSignal.listChanged.connect(this, "tagIndexUpdated()");
1378         syncRunner.searchSignal.listChanged.connect(this, "savedSearchIndexUpdated()");
1379         syncRunner.notebookSignal.listChanged.connect(this, "notebookIndexUpdated()");
1380         syncRunner.noteIndexSignal.listChanged.connect(this, "noteIndexUpdated(boolean)");
1381         syncRunner.noteSignal.quotaChanged.connect(this, "updateQuotaBar()");
1382         
1383                 syncRunner.syncSignal.saveUploadAmount.connect(this,"saveUploadAmount(long)");
1384                 syncRunner.syncSignal.saveUserInformation.connect(this,"saveUserInformation(User)");
1385                 syncRunner.syncSignal.saveEvernoteUpdateCount.connect(this,"saveEvernoteUpdateCount(int)");
1386                 
1387                 syncRunner.noteSignal.guidChanged.connect(this, "noteGuidChanged(String, String)");
1388                 syncRunner.noteSignal.noteChanged.connect(this, "invalidateNoteCache(String, String)");
1389                 syncRunner.resourceSignal.resourceGuidChanged.connect(this, "noteResourceGuidChanged(String,String,String)");
1390                 syncRunner.noteSignal.noteDownloaded.connect(listManager, "noteDownloaded(Note)");
1391                 syncRunner.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
1392                 
1393                 syncRunner.syncSignal.refreshLists.connect(this, "refreshLists()");
1394         }
1395         
1396         private void setupBrowserSignalListeners() {
1397                 setupBrowserWindowListeners(browserWindow, true);
1398         }
1399
1400         private void setupBrowserWindowListeners(BrowserWindow browser, boolean master) {
1401                 browser.fileWatcher.fileChanged.connect(this, "externalFileEdited(String)");
1402                 browser.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)");
1403             browser.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)");
1404             if (master) browser.noteSignal.noteChanged.connect(this, "setNoteDirty()");
1405             browser.noteSignal.titleChanged.connect(listManager, "updateNoteTitle(String, String)");
1406             browser.noteSignal.titleChanged.connect(this, "updateNoteTitle(String, String)");
1407             browser.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
1408             browser.noteSignal.createdDateChanged.connect(listManager, "updateNoteCreatedDate(String, QDateTime)");
1409             browser.noteSignal.alteredDateChanged.connect(listManager, "updateNoteAlteredDate(String, QDateTime)");
1410             browser.noteSignal.subjectDateChanged.connect(listManager, "updateNoteSubjectDate(String, QDateTime)");
1411             browser.noteSignal.authorChanged.connect(listManager, "updateNoteAuthor(String, String)");
1412             browser.noteSignal.geoChanged.connect(listManager, "updateNoteGeoTag(String, Double,Double,Double)");
1413             browser.noteSignal.geoChanged.connect(this, "setNoteDirty()");
1414             browser.noteSignal.sourceUrlChanged.connect(listManager, "updateNoteSourceUrl(String, String)");
1415         browser.blockApplication.connect(this, "blockApplication(BrowserWindow)");
1416         browser.unblockApplication.connect(this, "unblockApplication()");
1417             if (master) browser.focusLost.connect(this, "saveNote()");
1418             browser.resourceSignal.contentChanged.connect(this, "externalFileEdited(String)");
1419             browser.evernoteLinkClicked.connect(this, "evernoteLinkClick(String, String)");
1420         }
1421
1422         //**************************************************
1423         //* Setup shortcuts
1424         //**************************************************
1425         private void setupShortcut(QShortcut action, String text) {
1426                 if (!Global.shortcutKeys.containsAction(text))
1427                         return;
1428                 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
1429         }
1430         
1431         //***************************************************************
1432         //***************************************************************
1433         //* Settings and look & feel
1434         //***************************************************************
1435         //***************************************************************
1436         @SuppressWarnings("unused")
1437         private void settings() {
1438                 logger.log(logger.HIGH, "Entering NeverNote.settings");
1439
1440                 saveNoteColumnPositions();
1441                 saveNoteIndexWidth();
1442                 showColumns();
1443         ConfigDialog settings = new ConfigDialog(this);
1444         String dateFormat = Global.getDateFormat();
1445         String timeFormat = Global.getTimeFormat();
1446         
1447                 indexTime = 1000*Global.getIndexThreadSleepInterval();  
1448                 indexTimer.start(indexTime);  // reset indexing timer
1449         
1450         settings.exec();
1451         indexRunner.indexAttachmentsLocally = Global.indexAttachmentsLocally();
1452         indexRunner.indexNoteBody = Global.indexNoteBody();
1453         indexRunner.indexNoteTitle = Global.indexNoteTitle();
1454         indexRunner.specialIndexCharacters = Global.getSpecialIndexCharacters();
1455         indexRunner.indexImageRecognition = Global.indexImageRecognition();
1456         if (Global.showTrayIcon() || Global.minimizeOnClose())
1457                 trayIcon.show();
1458         else
1459                 trayIcon.hide();
1460         showColumns();
1461         if (menuBar.showEditorBar.isChecked()){
1462                 // ICHANGED 
1463                 for(int i = 0; i < tabBrowser.count(); i++){
1464                         BrowserWindow browser = ((TabBrowse) tabBrowser.widget(i)).getBrowserWindow();
1465                         showEditorButtons(browser);
1466                 }
1467                 
1468         }
1469         
1470         // Reset the save timer
1471         if (Global.getAutoSaveInterval() > 0)
1472                         saveTimer.setInterval(1000*60*Global.getAutoSaveInterval());
1473         else
1474                 saveTimer.stop();
1475         
1476         
1477         // Set special reloads
1478         if (settings.getDebugPage().reloadSharedNotebooksClicked()) {
1479                 conn.executeSql("Delete from LinkedNotebook");
1480                 conn.executeSql("delete from SharedNotebook");
1481                 conn.executeSql("Delete from Notebook where linked=true");
1482                 conn.executeSql("Insert into Sync (key, value) values ('FullLinkedNotebookSync', 'true')");
1483                 conn.executeSql("Insert into Sync (key, value) values ('FullSharedNotebookSync', 'true')");
1484         }
1485
1486         // Reload user data
1487         noteCache.clear();
1488         readOnlyCache.clear();
1489         inkNoteCache.clear();
1490         noteIndexUpdated(true);
1491                 
1492         logger.log(logger.HIGH, "Leaving NeverNote.settings");
1493         }
1494         // Restore things to the way they were
1495         private void restoreWindowState(boolean mainWindow) {
1496                 // We need to name things or this doesn't work.
1497                 setObjectName("NeverNote");
1498         restoreState(Global.restoreState(objectName()));
1499                 mainLeftRightSplitter.setObjectName("mainLeftRightSplitter");
1500                 browserIndexSplitter.setObjectName("browserIndexSplitter");
1501                 leftSplitter1.setObjectName("leftSplitter1");
1502                 // ICHANGED
1503                 rensoNoteListDock.setObjectName("rensoNoteListDock");
1504                 
1505                 // Restore the actual positions.
1506                 if (mainWindow)
1507                         restoreGeometry(Global.restoreGeometry(objectName()));
1508         mainLeftRightSplitter.restoreState(Global.restoreState(mainLeftRightSplitter.objectName()));
1509         browserIndexSplitter.restoreState(Global.restoreState(browserIndexSplitter.objectName()));
1510         leftSplitter1.restoreState(Global.restoreState(leftSplitter1.objectName()));
1511         // ICHANGED
1512         rensoNoteListDock.restoreGeometry(Global.restoreGeometry(rensoNoteListDock.objectName()));
1513        
1514         }
1515         // Save window positions for the next start
1516         private void saveWindowState() {
1517                 Global.saveGeometry(objectName(), saveGeometry());
1518                 Global.saveState(mainLeftRightSplitter.objectName(), mainLeftRightSplitter.saveState());
1519                 Global.saveState(browserIndexSplitter.objectName(), browserIndexSplitter.saveState());
1520                 Global.saveState(leftSplitter1.objectName(), leftSplitter1.saveState());
1521                 Global.saveState(objectName(), saveState());
1522                 // ICHANGED
1523                 Global.saveGeometry(rensoNoteListDock.objectName(), rensoNoteListDock.saveGeometry());
1524         }    
1525         // Load the style sheet
1526         private void loadStyleSheet() {
1527                 String styleSheetName = "default.qss";
1528                 if (Global.getStyle().equalsIgnoreCase("cleanlooks"))
1529                                 styleSheetName = "default-cleanlooks.qss";
1530                 String fileName = Global.getFileManager().getQssDirPathUser("default.qss");
1531                 QFile file = new QFile(fileName);
1532                 
1533                 // If a user default.qss doesn't exist, we use the one shipped with NeverNote
1534                 if (!file.exists()) {
1535                         fileName = Global.getFileManager().getQssDirPath(styleSheetName);
1536                         file = new QFile(fileName);
1537                 }
1538                 file.open(OpenModeFlag.ReadOnly);
1539                 String styleSheet = file.readAll().toString();
1540                 file.close();
1541                 setStyleSheet(styleSheet);
1542         }
1543         // Save column positions for the next time
1544         private void saveNoteColumnPositions() {
1545                 int position = noteTableView.header.visualIndex(Global.noteTableCreationPosition);
1546                 Global.setColumnPosition("noteTableCreationPosition", position);
1547                 position = noteTableView.header.visualIndex(Global.noteTableTagPosition);
1548                 Global.setColumnPosition("noteTableTagPosition", position);
1549                 position = noteTableView.header.visualIndex(Global.noteTableNotebookPosition);
1550                 Global.setColumnPosition("noteTableNotebookPosition", position);
1551                 position = noteTableView.header.visualIndex(Global.noteTableChangedPosition);
1552                 Global.setColumnPosition("noteTableChangedPosition", position);
1553                 position = noteTableView.header.visualIndex(Global.noteTableAuthorPosition);
1554                 Global.setColumnPosition("noteTableAuthorPosition", position);
1555                 position = noteTableView.header.visualIndex(Global.noteTableSourceUrlPosition);
1556                 Global.setColumnPosition("noteTableSourceUrlPosition", position);
1557                 position = noteTableView.header.visualIndex(Global.noteTableSubjectDatePosition);
1558                 Global.setColumnPosition("noteTableSubjectDatePosition", position);
1559                 position = noteTableView.header.visualIndex(Global.noteTableTitlePosition);
1560                 Global.setColumnPosition("noteTableTitlePosition", position);
1561                 position = noteTableView.header.visualIndex(Global.noteTableSynchronizedPosition);
1562                 Global.setColumnPosition("noteTableSynchronizedPosition", position);
1563                 position = noteTableView.header.visualIndex(Global.noteTableGuidPosition);
1564                 Global.setColumnPosition("noteTableGuidPosition", position);
1565                 position = noteTableView.header.visualIndex(Global.noteTableThumbnailPosition);
1566                 Global.setColumnPosition("noteTableThumbnailPosition", position);
1567                 position = noteTableView.header.visualIndex(Global.noteTablePinnedPosition);
1568                 Global.setColumnPosition("noteTablePinnedPosition", position);
1569
1570         }
1571         // Save column widths for the next time
1572         private void saveNoteIndexWidth() {
1573                 int width;
1574         width = noteTableView.getColumnWidth(Global.noteTableCreationPosition);
1575         Global.setColumnWidth("noteTableCreationPosition", width);
1576                 width = noteTableView.getColumnWidth(Global.noteTableChangedPosition);
1577                 Global.setColumnWidth("noteTableChangedPosition", width);
1578                 width = noteTableView.getColumnWidth(Global.noteTableGuidPosition);
1579                 Global.setColumnWidth("noteTableGuidPosition", width);
1580                 width = noteTableView.getColumnWidth(Global.noteTableNotebookPosition);
1581                 Global.setColumnWidth("noteTableNotebookPosition", width);
1582                 width = noteTableView.getColumnWidth(Global.noteTableTagPosition);
1583                 Global.setColumnWidth("noteTableTagPosition", width);
1584                 width = noteTableView.getColumnWidth(Global.noteTableTitlePosition);
1585                 Global.setColumnWidth("noteTableTitlePosition", width);
1586                 width = noteTableView.getColumnWidth(Global.noteTableSourceUrlPosition);
1587                 Global.setColumnWidth("noteTableSourceUrlPosition", width);
1588                 width = noteTableView.getColumnWidth(Global.noteTableAuthorPosition);
1589                 Global.setColumnWidth("noteTableAuthorPosition", width);
1590                 width = noteTableView.getColumnWidth(Global.noteTableSubjectDatePosition);
1591                 Global.setColumnWidth("noteTableSubjectDatePosition", width);
1592                 width = noteTableView.getColumnWidth(Global.noteTableSynchronizedPosition);
1593                 Global.setColumnWidth("noteTableSynchronizedPosition", width);
1594                 width = noteTableView.getColumnWidth(Global.noteTableThumbnailPosition);
1595                 Global.setColumnWidth("noteTableThumbnailPosition", width);
1596                 width = noteTableView.getColumnWidth(Global.noteTableGuidPosition);
1597                 Global.setColumnWidth("noteTableGuidPosition", width);
1598                 width = noteTableView.getColumnWidth(Global.noteTablePinnedPosition);
1599                 Global.setColumnWidth("noteTablePinnedPosition", width);
1600         }
1601         
1602         @SuppressWarnings("unused")
1603         private void toggleSearchWindow() {
1604                 logger.log(logger.HIGH, "Entering NeverNote.toggleSearchWindow");
1605         searchLayout.toggleSearchField();
1606         menuBar.hideSearch.setChecked(searchField.isVisible());
1607         Global.saveWindowVisible("searchField", searchField.isVisible());
1608         logger.log(logger.HIGH, "Leaving NeverNote.toggleSearchWindow");
1609     }   
1610         @SuppressWarnings("unused")
1611         private void toggleQuotaWindow() {
1612                 logger.log(logger.HIGH, "Entering NeverNote.toggleQuotaWindow");
1613         searchLayout.toggleQuotaBar();
1614         menuBar.hideQuota.setChecked(quotaBar.isVisible());
1615         Global.saveWindowVisible("quota", quotaBar.isVisible());
1616         logger.log(logger.HIGH, "Leaving NeverNote.toggleQuotaWindow");
1617     }   
1618         @SuppressWarnings("unused")
1619         private void toggleZoomWindow() {
1620                 logger.log(logger.HIGH, "Entering NeverNote.toggleZoomWindow");
1621         searchLayout.toggleZoom();
1622         menuBar.hideZoom.setChecked(zoomSpinner.isVisible());
1623         Global.saveWindowVisible("zoom", zoomSpinner.isVisible());
1624         logger.log(logger.HIGH, "Leaving NeverNote.toggleZoomWindow");
1625     }   
1626         
1627         
1628         
1629     //***************************************************************
1630     //***************************************************************
1631     //** These functions deal with Notebook menu items
1632     //***************************************************************
1633     //***************************************************************
1634     // Setup the tree containing the user's notebooks.
1635     private void initializeNotebookTree() {       
1636         logger.log(logger.HIGH, "Entering NeverNote.initializeNotebookTree");
1637 //      notebookTree.itemClicked.connect(this, "notebookTreeSelection()");
1638         notebookTree.selectionSignal.connect(this, "notebookTreeSelection()");
1639         listManager.notebookSignal.refreshNotebookTreeCounts.connect(notebookTree, "updateCounts(List, List)");
1640         logger.log(logger.HIGH, "Leaving NeverNote.initializeNotebookTree");
1641     }   
1642     // Listener when a notebook is selected
1643         private void notebookTreeSelection() {
1644                 logger.log(logger.HIGH, "Entering NeverNote.notebookTreeSelection");
1645                 noteTableView.proxyModel.blocked = true;
1646                 
1647                 clearTrashFilter();
1648                 clearAttributeFilter();
1649                 clearSavedSearchFilter();
1650                 if (Global.mimicEvernoteInterface) {
1651                         clearTagFilter();
1652                         //searchField.clear();
1653                         searchField.clearEditText();
1654                 }
1655                 menuBar.noteRestoreAction.setVisible(false);            
1656         menuBar.notebookEditAction.setEnabled(true);
1657         menuBar.notebookDeleteAction.setEnabled(true);
1658         menuBar.notebookPublishAction.setEnabled(true);
1659         menuBar.notebookShareAction.setEnabled(true);
1660         menuBar.notebookIconAction.setEnabled(true);
1661         menuBar.notebookStackAction.setEnabled(true);
1662         
1663                 // ICHANGED ゴミ箱から元の画面に戻す。連想ノートリストをONに。
1664                 if (!rensoNoteListDock.isEnabled()) {
1665                         rensoNoteListDock.setEnabled(true);
1666                 }
1667                 
1668         List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1669         selectedNotebookGUIDs.clear();
1670                 String guid = "";
1671                 String stackName = "";
1672                 if (selections.size() > 0) {
1673                 guid = (selections.get(0).text(2));
1674                 stackName = selections.get(0).text(0);
1675         }
1676                 if (!Global.mimicEvernoteInterface) {
1677                         // If no notebooks are selected, we make it look like the "all notebooks" one was selected
1678                         if (selections.size()==0) {
1679                                 selectedNotebookGUIDs.clear();
1680                                 for (int i=0; i < listManager.getNotebookIndex().size(); i++) {
1681                                         selectedNotebookGUIDs.add(listManager.getNotebookIndex().get(i).getGuid());
1682                                 }
1683                                 menuBar.notebookEditAction.setEnabled(false);
1684                                 menuBar.notebookDeleteAction.setEnabled(false);
1685                                 menuBar.notebookStackAction.setEnabled(false);
1686                                 menuBar.notebookIconAction.setEnabled(false);
1687                         }
1688                 }
1689         if (!guid.equals("") && !guid.equals("STACK")) {
1690                 selectedNotebookGUIDs.add(guid);
1691                 menuBar.notebookIconAction.setEnabled(true);
1692         } else {
1693                 menuBar.notebookIconAction.setEnabled(true);
1694                         for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1695                                 Notebook book = listManager.getNotebookIndex().get(j);
1696                                 if (book.getStack() != null && book.getStack().equalsIgnoreCase(stackName))
1697                                         selectedNotebookGUIDs.add(book.getGuid());
1698                         }
1699         }
1700         listManager.setSelectedNotebooks(selectedNotebookGUIDs);
1701         listManager.loadNotesIndex();
1702         noteIndexUpdated(false);
1703         refreshEvernoteNote(true);
1704         listManager.refreshCounters = true;
1705         listManager.refreshCounters();
1706         if (selectedNotebookGUIDs.size() == 1) {
1707                 int col = conn.getNotebookTable().getSortColumn(selectedNotebookGUIDs.get(0));
1708                 int order = conn.getNotebookTable().getSortOrder(selectedNotebookGUIDs.get(0));
1709                 if (col != -1) {
1710                         noteTableView.proxyModel.blocked = true;
1711                         if (order == 1)
1712                                 noteTableView.sortByColumn(col, Qt.SortOrder.DescendingOrder);
1713                         else
1714                                 noteTableView.sortByColumn(col, Qt.SortOrder.AscendingOrder);
1715                 }
1716         }
1717         noteTableView.proxyModel.blocked = false;
1718                 logger.log(logger.HIGH, "Leaving NeverNote.notebookTreeSelection");
1719
1720     }
1721     private void clearNotebookFilter() {
1722         notebookTree.blockSignals(true);
1723         notebookTree.clearSelection();
1724                 menuBar.noteRestoreAction.setVisible(false);
1725         menuBar.notebookEditAction.setEnabled(false);
1726         menuBar.notebookDeleteAction.setEnabled(false);
1727         selectedNotebookGUIDs.clear();
1728         listManager.setSelectedNotebooks(selectedNotebookGUIDs);
1729         notebookTree.blockSignals(false);
1730     }
1731         // Triggered when the notebook DB has been updated
1732         private void notebookIndexUpdated() {
1733                 logger.log(logger.HIGH, "Entering NeverNote.notebookIndexUpdated");
1734         
1735                 // Get the possible icons
1736                 HashMap<String, QIcon> icons = conn.getNotebookTable().getAllIcons();
1737         notebookTree.setIcons(icons);
1738         
1739         if (selectedNotebookGUIDs == null)
1740                         selectedNotebookGUIDs = new ArrayList<String>();
1741                 List<Notebook> books = conn.getNotebookTable().getAll();
1742                 for (int i=books.size()-1; i>=0; i--) {
1743                         for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1744                                 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(books.get(i).getGuid())) {
1745                                         books.remove(i);
1746                                         j=listManager.getArchiveNotebookIndex().size();
1747                                 }
1748                         }
1749                 }
1750                 
1751                 
1752                 listManager.countNotebookResults(listManager.getNoteIndex());
1753                 notebookTree.blockSignals(true);
1754         notebookTree.load(books, listManager.getLocalNotebooks());
1755         for (int i=selectedNotebookGUIDs.size()-1; i>=0; i--) {
1756                 boolean found = notebookTree.selectGuid(selectedNotebookGUIDs.get(i));
1757                 if (!found)
1758                         selectedNotebookGUIDs.remove(i);
1759         }
1760         listManager.refreshCounters = true;
1761         listManager.refreshCounters();
1762         notebookTree.blockSignals(false);
1763         
1764                 logger.log(logger.HIGH, "Leaving NeverNote.notebookIndexUpdated");
1765     }
1766     // Show/Hide note information
1767         @SuppressWarnings("unused")
1768         private void toggleNotebookWindow() {
1769                 logger.log(logger.HIGH, "Entering NeverNote.toggleNotebookWindow");
1770                 searchLayout.toggleNotebook();
1771         menuBar.hideNotebooks.setChecked(notebookTree.isVisible());
1772         Global.saveWindowVisible("notebookTree", notebookTree.isVisible());
1773         logger.log(logger.HIGH, "Leaving NeverNote.toggleNotebookWindow");
1774     }   
1775         // Add a new notebook
1776         @SuppressWarnings("unused")
1777         private void addNotebook() {
1778                 logger.log(logger.HIGH, "Inside NeverNote.addNotebook");
1779                 NotebookEdit edit = new NotebookEdit();
1780                 edit.setNotebooks(listManager.getNotebookIndex());
1781                 edit.exec();
1782         
1783                 if (!edit.okPressed())
1784                         return;
1785         
1786                 Calendar currentTime = new GregorianCalendar();
1787                 Long l = new Long(currentTime.getTimeInMillis());
1788                 String randint = new String(Long.toString(l));
1789         
1790                 Notebook newBook = new Notebook();
1791                 newBook.setUpdateSequenceNum(0);
1792                 newBook.setGuid(randint);
1793                 newBook.setName(edit.getNotebook());
1794                 newBook.setServiceCreated(new Date().getTime());
1795                 newBook.setServiceUpdated(new Date().getTime());
1796                 newBook.setDefaultNotebook(false);
1797                 newBook.setPublished(false);
1798                 
1799                 listManager.getNotebookIndex().add(newBook);
1800                 if (edit.isLocal())
1801                         listManager.getLocalNotebooks().add(newBook.getGuid());
1802                 conn.getNotebookTable().addNotebook(newBook, true, edit.isLocal());
1803                 notebookIndexUpdated();
1804                 listManager.countNotebookResults(listManager.getNoteIndex());
1805 //              notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
1806                 logger.log(logger.HIGH, "Leaving NeverNote.addNotebook");
1807         }
1808         // Edit an existing notebook
1809         @SuppressWarnings("unused")
1810         private void stackNotebook() {
1811                 logger.log(logger.HIGH, "Entering NeverNote.stackNotebook");
1812                 StackNotebook edit = new StackNotebook();
1813                 
1814                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1815                 QTreeWidgetItem currentSelection;
1816                 for (int i=0; i<selections.size(); i++) {
1817                         currentSelection = selections.get(0);
1818                         String guid = currentSelection.text(2);
1819                         if (guid.equalsIgnoreCase("")) {
1820                                  QMessageBox.critical(this, tr("Unable To Stack") ,tr("You can't stack the \"All Notebooks\" item."));
1821                                  return;
1822                         }
1823                         if (guid.equalsIgnoreCase("STACK")) {
1824                                  QMessageBox.critical(this, tr("Unable To Stack") ,tr("You can't stack a stack."));
1825                                  return;
1826                         }
1827                 }
1828
1829                 edit.setStackNames(conn.getNotebookTable().getAllStackNames());
1830
1831                 
1832                 edit.exec();
1833         
1834                 if (!edit.okPressed())
1835                         return;
1836         
1837                 String stack = edit.getStackName();
1838                 
1839                 for (int i=0; i<selections.size(); i++) {
1840                         currentSelection = selections.get(i);
1841                         String guid = currentSelection.text(2);
1842                         listManager.updateNotebookStack(guid, stack);
1843                 }
1844                 notebookIndexUpdated();
1845                 logger.log(logger.HIGH, "Leaving NeverNote.stackNotebook");
1846         }
1847         // Edit an existing notebook
1848         @SuppressWarnings("unused")
1849         private void editNotebook() {
1850                 logger.log(logger.HIGH, "Entering NeverNote.editNotebook");
1851                 NotebookEdit edit = new NotebookEdit();
1852                 
1853                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1854                 QTreeWidgetItem currentSelection;
1855                 currentSelection = selections.get(0);
1856                 edit.setNotebook(currentSelection.text(0));
1857                 
1858                 String guid = currentSelection.text(2);
1859                 if (!guid.equalsIgnoreCase("STACK")) {
1860                         edit.setTitle(tr("Edit Notebook"));
1861                         edit.setNotebooks(listManager.getNotebookIndex());
1862                         edit.setLocalCheckboxEnabled(false);
1863                         for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1864                                 if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
1865                                         edit.setDefaultNotebook(listManager.getNotebookIndex().get(i).isDefaultNotebook());
1866                                         i=listManager.getNotebookIndex().size();
1867                                 }
1868                         }
1869                 } else {
1870                         edit.setTitle(tr("Edit Stack"));
1871                         edit.setStacks(conn.getNotebookTable().getAllStackNames());
1872                         edit.hideLocalCheckbox();
1873                         edit.hideDefaultCheckbox();
1874                 }
1875                 
1876                 edit.exec();
1877         
1878                 if (!edit.okPressed())
1879                         return;
1880         
1881                 
1882                 if (guid.equalsIgnoreCase("STACK")) {
1883                         conn.getNotebookTable().renameStacks(currentSelection.text(0), edit.getNotebook());
1884                         for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1885                                 if (listManager.getNotebookIndex().get(j).getStack() != null && 
1886                                         listManager.getNotebookIndex().get(j).getStack().equalsIgnoreCase(currentSelection.text(0)))
1887                                                 listManager.getNotebookIndex().get(j).setStack(edit.getNotebook());
1888                         }
1889                         conn.getNotebookTable().renameStacks(currentSelection.text(0), edit.getNotebook());
1890                         currentSelection.setText(0, edit.getNotebook());
1891                         return;
1892                 }
1893                 
1894                 updateListNotebookName(currentSelection.text(0), edit.getNotebook());
1895                 currentSelection.setText(0, edit.getNotebook());
1896                 
1897                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1898                         if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
1899                                 listManager.getNotebookIndex().get(i).setName(edit.getNotebook());
1900                                 if (!listManager.getNotebookIndex().get(i).isDefaultNotebook() && edit.isDefaultNotebook()) {
1901                                         for (int j=0; j<listManager.getNotebookIndex().size(); j++)
1902                                                 listManager.getNotebookIndex().get(j).setDefaultNotebook(false);
1903                                         listManager.getNotebookIndex().get(i).setDefaultNotebook(true);
1904                                         conn.getNotebookTable().setDefaultNotebook(listManager.getNotebookIndex().get(i).getGuid());
1905                                 }
1906                                 conn.getNotebookTable().updateNotebook(listManager.getNotebookIndex().get(i), true);
1907                                 if (conn.getNotebookTable().isLinked(listManager.getNotebookIndex().get(i).getGuid())) {
1908                                         LinkedNotebook linkedNotebook = conn.getLinkedNotebookTable().getByNotebookGuid(listManager.getNotebookIndex().get(i).getGuid());
1909                                         linkedNotebook.setShareName(edit.getNotebook());
1910                                         conn.getLinkedNotebookTable().updateNotebook(linkedNotebook, true);
1911                                 }
1912                                 i=listManager.getNotebookIndex().size();
1913                         }
1914                 }
1915                 
1916                 // Build a list of non-closed notebooks
1917                 List<Notebook> nbooks = new ArrayList<Notebook>();
1918                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1919                         boolean found=false;
1920                         for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1921                                 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
1922                                         found = true;
1923                         }
1924                         if (!found)
1925                                 nbooks.add(listManager.getNotebookIndex().get(i));
1926                 }
1927                 
1928                 
1929                 FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger);
1930                 List<Notebook> filteredBooks = notebookFilter.getValidNotebooks(currentNote, listManager.getNotebookIndex());
1931                 browserWindow.setNotebookList(filteredBooks);
1932                 Iterator<String> set = externalWindows.keySet().iterator();
1933                 while(set.hasNext())
1934                         externalWindows.get(set.next()).getBrowserWindow().setNotebookList(filteredBooks);
1935                 
1936                 // ICHANGED
1937                 Iterator<Integer>it = tabWindows.keySet().iterator();
1938                 while (it.hasNext()) {
1939                         tabWindows.get(it.next()).getBrowserWindow()
1940                                         .setNotebookList(filteredBooks);
1941                 }
1942                 
1943                 logger.log(logger.HIGH, "Leaving NeverNote.editNotebook");
1944         }
1945         // Publish a notebook
1946         @SuppressWarnings("unused")
1947         private void publishNotebook() {
1948                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1949                 QTreeWidgetItem currentSelection;
1950                 currentSelection = selections.get(0);
1951                 String guid = currentSelection.text(2);
1952
1953                 if (guid.equalsIgnoreCase("STACK") || guid.equalsIgnoreCase(""))
1954                         return;
1955                 
1956                 Notebook n = null;
1957                 int position = 0;
1958                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1959                         if (guid.equals(listManager.getNotebookIndex().get(i).getGuid())) {
1960                                 n = listManager.getNotebookIndex().get(i);
1961                                 position = i;
1962                                 i = listManager.getNotebookIndex().size();
1963                         }
1964                 }
1965                 if (n == null)
1966                         return;
1967                 
1968                 PublishNotebook publish = new PublishNotebook(Global.username, Global.getServer(), n);
1969                 publish.exec();
1970                 
1971                 if (!publish.okClicked()) 
1972                         return;
1973                 
1974                 Publishing p = publish.getPublishing();
1975                 boolean isPublished = !publish.isStopPressed();
1976                 conn.getNotebookTable().setPublishing(n.getGuid(), isPublished, p);
1977                 n.setPublished(isPublished);
1978                 n.setPublishing(p);
1979                 listManager.getNotebookIndex().set(position, n);
1980                 notebookIndexUpdated();
1981         }
1982         // Publish a notebook
1983         @SuppressWarnings("unused")
1984         private void shareNotebook() {
1985                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1986                 QTreeWidgetItem currentSelection;
1987                 currentSelection = selections.get(0);
1988                 String guid = currentSelection.text(2);
1989
1990                 if (guid.equalsIgnoreCase("STACK") || guid.equalsIgnoreCase(""))
1991                         return;
1992                 
1993                 Notebook n = null;;
1994                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1995                         if (guid.equals(listManager.getNotebookIndex().get(i).getGuid())) {
1996                                 n = listManager.getNotebookIndex().get(i);
1997                                 i = listManager.getNotebookIndex().size();
1998                         }
1999                 }
2000                                 
2001                 String authToken = null;
2002                 if (syncRunner.isConnected)
2003                         authToken = syncRunner.authToken;
2004                 ShareNotebook share = new ShareNotebook(n.getName(), conn, n, syncRunner);
2005                 share.exec();
2006                 
2007         }
2008
2009         // Delete an existing notebook
2010         @SuppressWarnings("unused")
2011         private void deleteNotebook() {
2012                 logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
2013                 boolean stacksFound = false;
2014                 boolean notebooksFound = false;
2015                 boolean assigned = false;
2016                 // Check if any notes have this notebook
2017                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
2018         for (int i=0; i<selections.size(); i++) {
2019                 QTreeWidgetItem currentSelection;
2020                 currentSelection = selections.get(i);
2021                 String guid = currentSelection.text(2);
2022                 if (!guid.equalsIgnoreCase("STACK")) {
2023                         notebooksFound = true;
2024                         for (int j=0; j<listManager.getNoteIndex().size(); j++) {
2025                                 String noteGuid = listManager.getNoteIndex().get(j).getNotebookGuid();
2026                                 if (noteGuid.equals(guid)) {
2027                                         assigned = true;
2028                                         j=listManager.getNoteIndex().size();
2029                                         i=selections.size();
2030                                 }
2031                         }
2032                 } else {
2033                         stacksFound = true;
2034                 }
2035         }
2036                 if (assigned) {
2037                         QMessageBox.information(this, tr("Unable to Delete"), tr("Some of the selected notebook(s) contain notes.\n"+
2038                                         "Please delete the notes or move them to another notebook before deleting any notebooks."));
2039                         return;
2040                 }
2041                 
2042                 if (conn.getNotebookTable().getAll().size() == 1) {
2043                         QMessageBox.information(this, tr("Unable to Delete"), tr("You must have at least one notebook."));
2044                         return;
2045                 }
2046         
2047         // If all notebooks are clear, verify the delete
2048                 String msg1 = new String(tr("Delete selected notebooks?"));
2049                 String msg2 = new String(tr("Remove selected stacks (notebooks will not be deleted)?"));
2050                 String msg3 = new String(tr("Delete selected notebooks & remove stacks? Notebooks under the stacks are" +
2051                                 " not deleted unless selected?"));
2052                 String msg = "";
2053                 if (stacksFound && notebooksFound)
2054                         msg = msg3;
2055                 if (!stacksFound && notebooksFound)
2056                         msg = msg1;
2057                 if (stacksFound && !notebooksFound)
2058                         msg = msg2;
2059                 if (QMessageBox.question(this, tr("Confirmation"), msg,
2060                         QMessageBox.StandardButton.Yes, 
2061                         QMessageBox.StandardButton.No)==StandardButton.No.value()) {
2062                         return;
2063                 }
2064                 
2065                 // If confirmed, delete the notebook
2066         for (int i=selections.size()-1; i>=0; i--) {
2067                 QTreeWidgetItem currentSelection;
2068                 currentSelection = selections.get(i);
2069                 String guid = currentSelection.text(2);
2070                 if (currentSelection.text(2).equalsIgnoreCase("STACK")) {
2071                         conn.getNotebookTable().renameStacks(currentSelection.text(0), "");
2072                         listManager.renameStack(currentSelection.text(0), "");
2073                 } else {
2074                         conn.getNotebookTable().expungeNotebook(guid, true);
2075                         listManager.deleteNotebook(guid);
2076                 }
2077         }
2078
2079                 notebookIndexUpdated();
2080 //        notebookTreeSelection();
2081 //        notebookTree.load(listManager.getNotebookIndex(), listManager.getLocalNotebooks());
2082 //        listManager.countNotebookResults(listManager.getNoteIndex());
2083         logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
2084         }
2085         // A note's notebook has been updated
2086         @SuppressWarnings("unused")
2087         private void updateNoteNotebook(String guid, String notebookGuid) {
2088                 // ICHANGED 同じノートブックに入れられたノート間の履歴を登録
2089                 conn.getHistoryTable().addSameNotebookHistory(guid, notebookGuid);
2090                 
2091                 // Update the list manager
2092                 listManager.updateNoteNotebook(guid, notebookGuid);
2093                 listManager.countNotebookResults(listManager.getNoteIndex());
2094 //              notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());    
2095                 
2096                 // Find the name of the notebook
2097                 String notebookName = null;
2098                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
2099                         if (listManager.getNotebookIndex().get(i).getGuid().equals(notebookGuid)) {
2100                                 notebookName = listManager.getNotebookIndex().get(i).getName();
2101                                 break;
2102                         }
2103                 }
2104                 
2105                 // If we found the name, update the browser window
2106                 if (notebookName != null) {
2107                         updateListNoteNotebook(guid, notebookName);
2108                         if (guid.equals(currentNoteGuid)) {
2109                                 int pos =  browserWindow.notebookBox.findText(notebookName);
2110                                 if (pos >=0)
2111                                         browserWindow.notebookBox.setCurrentIndex(pos);
2112                         }
2113                 }
2114                 
2115                 // If we're dealing with the current note, then we need to be sure and update the notebook there
2116                 if (guid.equals(currentNoteGuid)) {
2117                         if (currentNote != null) {
2118                                 currentNote.setNotebookGuid(notebookGuid);
2119                         }
2120                 }
2121         }
2122         // Open/close notebooks
2123         @SuppressWarnings("unused")
2124         private void closeNotebooks() {
2125                 NotebookArchive na = new NotebookArchive(listManager.getNotebookIndex(), listManager.getArchiveNotebookIndex());
2126                 na.exec();
2127                 if (!na.okClicked())
2128                         return;
2129                 
2130                 waitCursor(true);
2131                 listManager.getArchiveNotebookIndex().clear();
2132                 
2133                 for (int i=na.getClosedBookList().count()-1; i>=0; i--) {
2134                         String text = na.getClosedBookList().takeItem(i).text();
2135                         for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
2136                                 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
2137                                         Notebook n = listManager.getNotebookIndex().get(j);
2138                                         conn.getNotebookTable().setArchived(n.getGuid(),true);
2139                                         listManager.getArchiveNotebookIndex().add(n);
2140                                         j=listManager.getNotebookIndex().size();
2141                                 }
2142                         }
2143                 }
2144                 
2145                 for (int i=na.getOpenBookList().count()-1; i>=0; i--) {
2146                         String text = na.getOpenBookList().takeItem(i).text();
2147                         for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
2148                                 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
2149                                         Notebook n = listManager.getNotebookIndex().get(j);
2150                                         conn.getNotebookTable().setArchived(n.getGuid(),false);
2151                                         j=listManager.getNotebookIndex().size();
2152                                 }
2153                         }
2154                 }
2155                 notebookTreeSelection();
2156                 listManager.loadNotesIndex();
2157                 notebookIndexUpdated();
2158                 noteIndexUpdated(false);
2159                 reloadTagTree(true);
2160 //              noteIndexUpdated(false);
2161                 
2162                 // Build a list of non-closed notebooks
2163                 List<Notebook> nbooks = new ArrayList<Notebook>();
2164                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
2165                         boolean found=false;
2166                         for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
2167                                 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
2168                                         found = true;
2169                         }
2170                         if (!found)
2171                                 nbooks.add(listManager.getNotebookIndex().get(i));
2172                 }
2173                 
2174                 FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger);
2175                 List<Notebook> filteredBooks = notebookFilter.getValidNotebooks(currentNote, listManager.getNotebookIndex());
2176                 browserWindow.setNotebookList(filteredBooks);
2177                 
2178                 // Update any external windows
2179                 Iterator<String> set = externalWindows.keySet().iterator();
2180                 while(set.hasNext())
2181                         externalWindows.get(set.next()).getBrowserWindow().setNotebookList(filteredBooks);
2182                 
2183                 // ICHANGED
2184                 // 全てのタブウィンドウを更新
2185                 Iterator<Integer> it = tabWindows.keySet().iterator();
2186                 while (it.hasNext()) {
2187                         tabWindows.get(it.next()).getBrowserWindow()
2188                                         .setNotebookList(filteredBooks);
2189                 }
2190                 
2191                 waitCursor(false);
2192         }
2193         // Change the notebook's icon
2194         @SuppressWarnings("unused")
2195         private void setNotebookIcon() {
2196                 boolean stackSelected = false;
2197                 boolean allNotebookSelected = false;
2198                 
2199                 QTreeWidgetItem currentSelection;
2200                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
2201                 if (selections.size() == 0)
2202                         return;
2203                 
2204                 currentSelection = selections.get(0);   
2205                 String guid = currentSelection.text(2);
2206                 if (guid.equalsIgnoreCase(""))
2207                         allNotebookSelected = true;
2208                 if (guid.equalsIgnoreCase("STACK"))
2209                         stackSelected = true;
2210
2211                 QIcon currentIcon = currentSelection.icon(0);
2212                 QIcon icon;
2213                 SetIcon dialog;
2214                 
2215                 if (!stackSelected && !allNotebookSelected) {
2216                         icon = conn.getNotebookTable().getIcon(guid);
2217                         if (icon == null) {
2218                                 dialog = new SetIcon(currentIcon, saveLastPath);
2219                                 dialog.setUseDefaultIcon(true);
2220                         } else {
2221                                 dialog = new SetIcon(icon, saveLastPath);
2222                                 dialog.setUseDefaultIcon(false);
2223                         }
2224                 } else {
2225                         if (stackSelected) {
2226                                 icon = conn.getSystemIconTable().getIcon(currentSelection.text(0), "STACK");
2227                         } else {
2228                                 icon = conn.getSystemIconTable().getIcon(currentSelection.text(0), "ALLNOTEBOOK");                              
2229                         }
2230                         if (icon == null) {
2231                                 dialog = new SetIcon(currentIcon, saveLastPath);
2232                                 dialog.setUseDefaultIcon(true);
2233                         } else {
2234                                 dialog = new SetIcon(icon, saveLastPath);
2235                                 dialog.setUseDefaultIcon(false);
2236                         }
2237                 }
2238                 dialog.exec();
2239                 if (dialog.okPressed()) {
2240                 saveLastPath = dialog.getPath();
2241
2242                         QIcon newIcon = dialog.getIcon();
2243                         if (stackSelected) {
2244                                 conn.getSystemIconTable().setIcon(currentSelection.text(0), "STACK", newIcon, dialog.getFileType());
2245                                 if (newIcon == null) {
2246                                         newIcon = new QIcon(iconPath+"books2.png");
2247                                 }
2248                                 currentSelection.setIcon(0,newIcon);
2249                                 return;
2250                         }
2251                         if (allNotebookSelected) {
2252                                 conn.getSystemIconTable().setIcon(currentSelection.text(0), "ALLNOTEBOOK", newIcon, dialog.getFileType());
2253                                 if (newIcon == null) {
2254                                         newIcon = new QIcon(iconPath+"notebook-green.png");
2255                                 }
2256                                 currentSelection.setIcon(0,newIcon);
2257                                 return;
2258                         }
2259                         conn.getNotebookTable().setIcon(guid, newIcon, dialog.getFileType());
2260                         if (newIcon == null) {
2261                                 boolean isPublished = false;;
2262                                 boolean found = false;
2263                                 for (int i=0; i<listManager.getNotebookIndex().size() && !found; i++) {
2264                                         if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
2265                                                 isPublished = listManager.getNotebookIndex().get(i).isPublished();
2266                                                 found = true;
2267                                         }
2268                                 }
2269                                 newIcon = notebookTree.findDefaultIcon(guid, currentSelection.text(1), listManager.getLocalNotebooks(), isPublished);
2270                         }
2271                         currentSelection.setIcon(0, newIcon);
2272                 }
2273         
2274         }
2275         
2276         
2277     //***************************************************************
2278     //***************************************************************
2279     //** These functions deal with Tag menu items
2280     //***************************************************************
2281     //***************************************************************
2282         // Add a new notebook
2283         @SuppressWarnings("unused")
2284         private void addTag() {
2285                 logger.log(logger.HIGH, "Inside NeverNote.addTag");
2286                 TagEdit edit = new TagEdit();
2287                 edit.setTagList(listManager.getTagIndex());
2288
2289                 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2290                 QTreeWidgetItem currentSelection = null;
2291                 if (selections.size() > 0) {
2292                         currentSelection = selections.get(0);
2293                         edit.setParentTag(currentSelection.text(0));
2294                 }
2295
2296                 edit.exec();
2297         
2298                 if (!edit.okPressed())
2299                         return;
2300         
2301                 Calendar currentTime = new GregorianCalendar();
2302                 Long l = new Long(currentTime.getTimeInMillis());
2303                 String randint = new String(Long.toString(l));
2304         
2305                 Tag newTag = new Tag();
2306                 newTag.setUpdateSequenceNum(0);
2307                 newTag.setGuid(randint);
2308                 newTag.setName(edit.getTag());
2309                 if (edit.getParentTag().isChecked()) {
2310                         newTag.setParentGuid(currentSelection.text(2));
2311                         newTag.setParentGuidIsSet(true);
2312                         currentSelection.setExpanded(true);
2313                 }
2314                 conn.getTagTable().addTag(newTag, true);
2315                 listManager.getTagIndex().add(newTag);
2316                 reloadTagTree(true);
2317                 
2318                 logger.log(logger.HIGH, "Leaving NeverNote.addTag");
2319         }
2320         @SuppressWarnings("unused")
2321         private void reloadTagTree() {
2322                 reloadTagTree(false);
2323         }
2324         private void reloadTagTree(boolean reload) {
2325                 logger.log(logger.HIGH, "Entering NeverNote.reloadTagTree");
2326                 tagIndexUpdated(reload);
2327                 boolean filter = false;
2328                 if (reload)
2329                         listManager.countTagResults(listManager.getNoteIndex());
2330                 if (notebookTree.selectedItems().size() > 0 
2331                                                   && !notebookTree.selectedItems().get(0).text(0).equalsIgnoreCase("All Notebooks"))
2332                                                   filter = true;
2333                 if (tagTree.selectedItems().size() > 0)
2334                         filter = true;
2335                 tagTree.showAllTags(!filter);
2336                 tagIndexUpdated(false);
2337                 logger.log(logger.HIGH, "Leaving NeverNote.reloadTagTree");
2338         }
2339         // Edit an existing tag
2340         @SuppressWarnings("unused")
2341         private void editTag() {
2342                 logger.log(logger.HIGH, "Entering NeverNote.editTag");
2343                 TagEdit edit = new TagEdit();
2344                 edit.setTitle("Edit Tag");
2345                 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2346                 QTreeWidgetItem currentSelection;
2347                 currentSelection = selections.get(0);
2348                 edit.setTag(currentSelection.text(0));
2349                 edit.setTagList(listManager.getTagIndex());
2350                 edit.exec();
2351         
2352                 if (!edit.okPressed())
2353                         return;
2354         
2355                 String guid = currentSelection.text(2);
2356                 currentSelection.setText(0,edit.getTag());
2357                 
2358                 for (int i=0; i<listManager.getTagIndex().size(); i++) {
2359                         if (listManager.getTagIndex().get(i).getGuid().equals(guid)) {
2360                                 listManager.getTagIndex().get(i).setName(edit.getTag());
2361                                 conn.getTagTable().updateTag(listManager.getTagIndex().get(i), true);
2362                                 updateListTagName(guid);
2363                                 if (currentNote != null && currentNote.getTagGuids().contains(guid))
2364                                         browserWindow.setTag(getTagNamesForNote(currentNote));
2365                                 logger.log(logger.HIGH, "Leaving NeverNote.editTag");
2366                                 //return;
2367                         }
2368                 }
2369                 listManager.reloadNoteTagNames(guid, edit.getTag());
2370                 noteIndexUpdated(true);
2371                 refreshEvernoteNote(true);
2372                 browserWindow.setTag(getTagNamesForNote(currentNote));
2373                 logger.log(logger.HIGH, "Leaving NeverNote.editTag...");
2374         }
2375         // Delete an existing tag
2376         @SuppressWarnings("unused")
2377         private void deleteTag() {
2378                 logger.log(logger.HIGH, "Entering NeverNote.deleteTag");
2379                 
2380                 if (QMessageBox.question(this, tr("Confirmation"), tr("Delete the selected tags?"),
2381                         QMessageBox.StandardButton.Yes, 
2382                         QMessageBox.StandardButton.No)==StandardButton.No.value()) {
2383                                                         return;
2384                 }
2385                 
2386                 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2387         for (int i=selections.size()-1; i>=0; i--) {
2388                 QTreeWidgetItem currentSelection;
2389                 currentSelection = selections.get(i);                   
2390                 removeTagItem(currentSelection.text(2));
2391         }
2392         tagIndexUpdated(true);
2393         tagTreeSelection();
2394         listManager.countTagResults(listManager.getNoteIndex());
2395 //              tagTree.updateCounts(listManager.getTagCounter());
2396         logger.log(logger.HIGH, "Leaving NeverNote.deleteTag");
2397         }
2398         // Remove a tag tree item.  Go recursively down & remove the children too
2399         private void removeTagItem(String guid) {
2400         for (int j=listManager.getTagIndex().size()-1; j>=0; j--) {             
2401                 String parent = listManager.getTagIndex().get(j).getParentGuid();
2402                 if (parent != null && parent.equals(guid)) {            
2403                         //Remove this tag's children
2404                         removeTagItem(listManager.getTagIndex().get(j).getGuid());
2405                 }
2406         }
2407         //Now, remove this tag
2408         removeListTagName(guid);
2409         conn.getTagTable().expungeTag(guid, true);                      
2410         for (int a=0; a<listManager.getTagIndex().size(); a++) {
2411                 if (listManager.getTagIndex().get(a).getGuid().equals(guid)) {
2412                         listManager.getTagIndex().remove(a);
2413                         return;
2414                 }
2415         }
2416         }
2417         // Setup the tree containing the user's tags
2418     private void initializeTagTree() {
2419         logger.log(logger.HIGH, "Entering NeverNote.initializeTagTree");
2420 //      tagTree.itemSelectionChanged.connect(this, "tagTreeSelection()");
2421 //      tagTree.itemClicked.connect(this, "tagTreeSelection()");
2422         tagTree.selectionSignal.connect(this, "tagTreeSelection()");
2423         listManager.tagSignal.refreshTagTreeCounts.connect(tagTree, "updateCounts(List)");
2424         logger.log(logger.HIGH, "Leaving NeverNote.initializeTagTree");
2425     }
2426     // Listener when a tag is selected
2427         private void tagTreeSelection() {
2428         logger.log(logger.HIGH, "Entering NeverNote.tagTreeSelection");
2429                 
2430         clearTrashFilter();
2431         clearAttributeFilter();
2432         clearSavedSearchFilter();
2433         
2434                 menuBar.noteRestoreAction.setVisible(false);
2435                 
2436                 // ICHANGED ゴミ箱から元の画面に戻す。連想ノートリストをONに。
2437                 if (!rensoNoteListDock.isEnabled()) {
2438                         rensoNoteListDock.setEnabled(true);
2439                 }
2440                 
2441         List<QTreeWidgetItem> selections = tagTree.selectedItems();
2442         QTreeWidgetItem currentSelection;
2443         selectedTagGUIDs.clear();
2444         for (int i=0; i<selections.size(); i++) {
2445                 currentSelection = selections.get(i);
2446                 selectedTagGUIDs.add(currentSelection.text(2));
2447         }
2448         if (selections.size() > 0) {
2449                 menuBar.tagEditAction.setEnabled(true);
2450                 menuBar.tagDeleteAction.setEnabled(true);
2451                 menuBar.tagIconAction.setEnabled(true);
2452         }
2453         else {
2454                 menuBar.tagEditAction.setEnabled(false);
2455                 menuBar.tagDeleteAction.setEnabled(false);
2456                 menuBar.tagIconAction.setEnabled(true);
2457         }
2458         if (selections.size() > 1)
2459                 menuBar.tagMergeAction.setEnabled(true);
2460         else
2461                 menuBar.tagMergeAction.setEnabled(false);
2462         listManager.setSelectedTags(selectedTagGUIDs);
2463         listManager.loadNotesIndex();
2464         noteIndexUpdated(false);
2465         refreshEvernoteNote(true);
2466         listManager.refreshCounters = true;
2467         listManager.refreshCounters();
2468         logger.log(logger.HIGH, "Leaving NeverNote.tagTreeSelection");
2469     }
2470     // trigger the tag index to be refreshed
2471     @SuppressWarnings("unused")
2472         private void tagIndexUpdated() {
2473         tagIndexUpdated(true);
2474     }
2475     private void tagIndexUpdated(boolean reload) {
2476         logger.log(logger.HIGH, "Entering NeverNote.tagIndexUpdated");
2477                 if (selectedTagGUIDs == null)
2478                         selectedTagGUIDs = new ArrayList<String>();
2479                 if (reload)
2480                         listManager.reloadTagIndex();
2481
2482                 tagTree.blockSignals(true);
2483                 if (reload) {
2484                         tagTree.setIcons(conn.getTagTable().getAllIcons());
2485                         tagTree.load(listManager.getTagIndex());
2486                 }
2487
2488         for (int i=selectedTagGUIDs.size()-1; i>=0; i--) {
2489                 boolean found = tagTree.selectGuid(selectedTagGUIDs.get(i));
2490                 if (!found)
2491                         selectedTagGUIDs.remove(i);
2492         }
2493         tagTree.blockSignals(false);
2494         
2495                 browserWindow.setTag(getTagNamesForNote(currentNote));
2496         logger.log(logger.HIGH, "Leaving NeverNote.tagIndexUpdated");
2497     }   
2498     // Show/Hide note information
2499         @SuppressWarnings("unused")
2500         private void toggleTagWindow() {
2501                 logger.log(logger.HIGH, "Entering NeverNote.toggleTagWindow");
2502         if (tagTree.isVisible())
2503                 tagTree.hide();
2504         else
2505                 tagTree.show();
2506         menuBar.hideTags.setChecked(tagTree.isVisible());
2507         Global.saveWindowVisible("tagTree", tagTree.isVisible());
2508         logger.log(logger.HIGH, "Leaving NeverNote.toggleTagWindow");
2509     }   
2510         // A note's tags have been updated
2511         @SuppressWarnings("unused")
2512         private void updateNoteTags(String guid, List<String> tags) {
2513                 // Save any new tags.  We'll need them later.
2514                 List<String> newTags = new ArrayList<String>();
2515                 for (int i=0; i<tags.size(); i++) {
2516                         if (conn.getTagTable().findTagByName(tags.get(i))==null) 
2517                                 newTags.add(tags.get(i));
2518                 }
2519                 
2520                 listManager.saveNoteTags(guid, tags, true);
2521                 listManager.countTagResults(listManager.getNoteIndex());
2522                 StringBuffer names = new StringBuffer("");
2523                 for (int i=0; i<tags.size(); i++) {
2524                         names = names.append(tags.get(i));
2525                         if (i<tags.size()-1) {
2526                                 names.append(Global.tagDelimeter + " ");
2527                         }
2528                 }
2529                 browserWindow.setTag(names.toString());
2530                 
2531                 // ICHANGED
2532                 for (TabBrowse tab: tabWindows.values()) {
2533                         if (tab.getBrowserWindow().getNote().getGuid().equals(guid)) {
2534                                 int index = tabBrowser.indexOf(tab);
2535                                 noteDirty.put(index, true);
2536                                 break;
2537                         }
2538                 }
2539                 
2540                 // Now, we need to add any new tags to the tag tree
2541                 for (int i=0; i<newTags.size(); i++) 
2542                         tagTree.insertTag(newTags.get(i), conn.getTagTable().findTagByName(newTags.get(i)));
2543         }
2544         // Get a string containing all tag names for a note
2545         private String getTagNamesForNote(Note n) {
2546                 logger.log(logger.HIGH, "Entering NeverNote.getTagNamesForNote");
2547                 if (n==null || n.getGuid() == null || n.getGuid().equals(""))
2548                         return "";
2549                 StringBuffer buffer = new StringBuffer(100);
2550                 Vector<String> v = new Vector<String>();
2551                 List<String> guids = n.getTagGuids();
2552                 
2553                 if (guids == null) 
2554                         return "";
2555                 
2556                 for (int i=0; i<guids.size(); i++) {
2557                         v.add(listManager.getTagNameByGuid(guids.get(i)));
2558                 }
2559                 Comparator<String> comparator = Collections.reverseOrder();
2560                 Collections.sort(v,comparator);
2561                 Collections.reverse(v);
2562                 
2563                 for (int i = 0; i<v.size(); i++) {
2564                         if (i>0) 
2565                                 buffer.append(", ");
2566                         buffer.append(v.get(i));
2567                 }
2568                 
2569                 logger.log(logger.HIGH, "Leaving NeverNote.getTagNamesForNote");
2570                 return buffer.toString();
2571         }       
2572         // Tags were added via dropping notes from the note list
2573         @SuppressWarnings("unused")
2574         private void tagsAdded(String noteGuid, String tagGuid) {
2575                 String tagName = null;
2576                 for (int i=0; i<listManager.getTagIndex().size(); i++) {
2577                         if (listManager.getTagIndex().get(i).getGuid().equals(tagGuid)) {
2578                                 tagName = listManager.getTagIndex().get(i).getName();
2579                                 i=listManager.getTagIndex().size();
2580                         }
2581                 }
2582                 if (tagName == null)
2583                         return;
2584                 
2585                 for (int i=0; i<listManager.getMasterNoteIndex().size(); i++) {
2586                         if (listManager.getMasterNoteIndex().get(i).getGuid().equals(noteGuid)) {
2587                                 List<String> tagNames = new ArrayList<String>();
2588                                 tagNames.add(new String(tagName));
2589                                 Note n = listManager.getMasterNoteIndex().get(i);
2590                                 for (int j=0; j<n.getTagNames().size(); j++) {
2591                                         tagNames.add(new String(n.getTagNames().get(j)));
2592                                 }
2593                                 listManager.getNoteTableModel().updateNoteTags(noteGuid, n.getTagGuids(), tagNames);
2594                                 if (n.getGuid().equals(currentNoteGuid)) {
2595                                         Collections.sort(tagNames);
2596                                         String display = "";
2597                                         for (int j=0; j<tagNames.size(); j++) {
2598                                                 display = display+tagNames.get(j);
2599                                                 if (j+2<tagNames.size()) 
2600                                                         display = display+Global.tagDelimeter+" ";
2601                                         }
2602                                         browserWindow.setTag(display);
2603                                 }
2604                                 i=listManager.getMasterNoteIndex().size();
2605                         }
2606                 }
2607                 
2608                 
2609                 listManager.getNoteTableModel().updateNoteSyncStatus(noteGuid, false);
2610         }
2611         private void clearTagFilter() {
2612                 tagTree.blockSignals(true);
2613                 tagTree.clearSelection();
2614                 menuBar.noteRestoreAction.setVisible(false);
2615                 menuBar.tagEditAction.setEnabled(false);
2616                 menuBar.tagMergeAction.setEnabled(false);
2617                 menuBar.tagDeleteAction.setEnabled(false);
2618                 menuBar.tagIconAction.setEnabled(false);
2619                 selectedTagGUIDs.clear();
2620         listManager.setSelectedTags(selectedTagGUIDs);
2621         tagTree.blockSignals(false);
2622         }
2623         // Change the icon for a tag
2624         @SuppressWarnings("unused")
2625         private void setTagIcon() {
2626                 QTreeWidgetItem currentSelection;
2627                 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2628                 if (selections.size() == 0)
2629                         return;
2630                 
2631                 currentSelection = selections.get(0);   
2632                 String guid = currentSelection.text(2);
2633
2634                 QIcon currentIcon = currentSelection.icon(0);
2635                 QIcon icon = conn.getTagTable().getIcon(guid);
2636                 SetIcon dialog;
2637                 if (icon == null) {
2638                         dialog = new SetIcon(currentIcon, saveLastPath);
2639                         dialog.setUseDefaultIcon(true);
2640                 } else {
2641                         dialog = new SetIcon(icon, saveLastPath);
2642                         dialog.setUseDefaultIcon(false);
2643                 }
2644                 dialog.exec();
2645                 if (dialog.okPressed()) {
2646                 saveLastPath = dialog.getPath();
2647                         QIcon newIcon = dialog.getIcon();
2648                         conn.getTagTable().setIcon(guid, newIcon, dialog.getFileType());
2649                         if (newIcon == null) 
2650                                 newIcon = new QIcon(iconPath+"tag.png");
2651                         currentSelection.setIcon(0, newIcon);
2652                 }
2653         
2654         }
2655         // Merge tags
2656         @SuppressWarnings("unused")
2657         private void mergeTags() {
2658                 List<Tag> tags = new ArrayList<Tag>();
2659                 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2660                 for (int i=0; i<selections.size(); i++) {
2661                         Tag record = new Tag();
2662                         record.setGuid(selections.get(i).text(2));
2663                         record.setName(selections.get(i).text(0));
2664                         tags.add(record);
2665                 }
2666
2667                 TagMerge mergeDialog = new TagMerge(tags);
2668                 mergeDialog.exec();
2669                 if (!mergeDialog.okClicked())
2670                         return;
2671                 String newGuid = mergeDialog.getNewTagGuid();
2672                 
2673                 for (int i=0; i<tags.size(); i++) {
2674                         if (!tags.get(i).getGuid().equals(newGuid)) {
2675                                 List<String> noteGuids = conn.getNoteTable().noteTagsTable.getTagNotes(tags.get(i).getGuid());
2676                                 for (int j=0; j<noteGuids.size(); j++) {
2677                                         String noteGuid = noteGuids.get(j);
2678                                         conn.getNoteTable().noteTagsTable.deleteNoteTag(noteGuid);
2679                                         if (!conn.getNoteTable().noteTagsTable.checkNoteNoteTags(noteGuid, newGuid))
2680                                                 conn.getNoteTable().noteTagsTable.saveNoteTag(noteGuid, newGuid, true);
2681                                 }
2682                         }
2683                 }
2684                 listManager.reloadIndexes();
2685         }
2686         
2687     //***************************************************************
2688     //***************************************************************
2689     //** These functions deal with Saved Search menu items
2690     //***************************************************************
2691     //***************************************************************
2692         // Add a new notebook
2693         @SuppressWarnings("unused")
2694         private void addSavedSearch() {
2695                 logger.log(logger.HIGH, "Inside NeverNote.addSavedSearch");
2696                 SavedSearchEdit edit = new SavedSearchEdit();
2697                 edit.setSearchList(listManager.getSavedSearchIndex());
2698                 edit.exec();
2699         
2700                 if (!edit.okPressed())
2701                         return;
2702         
2703                 Calendar currentTime = new GregorianCalendar();         
2704                 Long l = new Long(currentTime.getTimeInMillis());
2705                 String randint = new String(Long.toString(l));
2706         
2707                 SavedSearch search = new SavedSearch();
2708                 search.setUpdateSequenceNum(0);
2709                 search.setGuid(randint);
2710                 search.setName(edit.getName());
2711                 search.setQuery(edit.getQuery());
2712                 search.setFormat(QueryFormat.USER);
2713                 listManager.getSavedSearchIndex().add(search);
2714                 conn.getSavedSearchTable().addSavedSearch(search, true);
2715                 savedSearchIndexUpdated();
2716                 logger.log(logger.HIGH, "Leaving NeverNote.addSavedSearch");
2717         }
2718         // Edit an existing tag
2719         @SuppressWarnings("unused")
2720         private void editSavedSearch() {
2721                 logger.log(logger.HIGH, "Entering NeverNote.editSavedSearch");
2722                 SavedSearchEdit edit = new SavedSearchEdit();
2723                 edit.setTitle(tr("Edit Search"));
2724                 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2725                 QTreeWidgetItem currentSelection;
2726                 currentSelection = selections.get(0);
2727                 String guid = currentSelection.text(1);
2728                 SavedSearch s = conn.getSavedSearchTable().getSavedSearch(guid);
2729                 edit.setName(currentSelection.text(0));
2730                 edit.setQuery(s.getQuery());
2731                 edit.setSearchList(listManager.getSavedSearchIndex());
2732                 edit.exec();
2733         
2734                 if (!edit.okPressed())
2735                         return;
2736         
2737                 List<SavedSearch> list = listManager.getSavedSearchIndex();
2738                 SavedSearch search = null;
2739                 boolean found = false;
2740                 for (int i=0; i<list.size(); i++) {
2741                         search = list.get(i);
2742                         if (search.getGuid().equals(guid)) {
2743                                 i=list.size();
2744                                 found = true;
2745                         }
2746                 }
2747                 if (!found)
2748                         return;
2749                 search.setName(edit.getName());
2750                 search.setQuery(edit.getQuery());
2751                 conn.getSavedSearchTable().updateSavedSearch(search, true);
2752                 savedSearchIndexUpdated();
2753                 logger.log(logger.HIGH, "Leaving NeverNote.editSavedSearch");
2754         }
2755         // Delete an existing tag
2756         @SuppressWarnings("unused")
2757         private void deleteSavedSearch() {
2758                 logger.log(logger.HIGH, "Entering NeverNote.deleteSavedSearch");
2759                 
2760                 if (QMessageBox.question(this, tr("Confirmation"), tr("Delete the selected search?"),
2761                         QMessageBox.StandardButton.Yes, 
2762                         QMessageBox.StandardButton.No)==StandardButton.No.value()) {
2763                                                         return;
2764                 }
2765                 
2766                 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2767         for (int i=selections.size()-1; i>=0; i--) {
2768                 QTreeWidgetItem currentSelection;
2769                 currentSelection = selections.get(i);
2770                 for (int j=0; j<listManager.getSavedSearchIndex().size(); j++) {
2771                         if (listManager.getSavedSearchIndex().get(j).getGuid().equals(currentSelection.text(1))) {
2772                                 conn.getSavedSearchTable().expungeSavedSearch(listManager.getSavedSearchIndex().get(j).getGuid(), true);
2773                                 listManager.getSavedSearchIndex().remove(j);
2774                                 j=listManager.getSavedSearchIndex().size()+1;
2775                         }
2776                 }
2777                 selections.remove(i);
2778         }
2779         savedSearchIndexUpdated();
2780         logger.log(logger.HIGH, "Leaving NeverNote.deleteSavedSearch");
2781         }
2782     // Setup the tree containing the user's tags
2783     private void initializeSavedSearchTree() {
2784         logger.log(logger.HIGH, "Entering NeverNote.initializeSavedSearchTree");
2785         savedSearchTree.itemSelectionChanged.connect(this, "savedSearchTreeSelection()");
2786         logger.log(logger.HIGH, "Leaving NeverNote.initializeSavedSearchTree");
2787     }
2788     // Listener when a tag is selected
2789     @SuppressWarnings("unused")
2790         private void savedSearchTreeSelection() {
2791         logger.log(logger.HIGH, "Entering NeverNote.savedSearchTreeSelection");
2792
2793         clearNotebookFilter();
2794         clearTagFilter();
2795         clearTrashFilter();
2796         clearAttributeFilter();
2797         
2798         String currentGuid = selectedSavedSearchGUID;
2799         menuBar.savedSearchEditAction.setEnabled(true);
2800         menuBar.savedSearchDeleteAction.setEnabled(true);
2801         menuBar.savedSearchIconAction.setEnabled(true);
2802         
2803                 // ICHANGED ゴミ箱から元の画面に戻す。連想ノートリストをONに。
2804                 if (!rensoNoteListDock.isEnabled()) {
2805                         rensoNoteListDock.setEnabled(true);
2806                 }
2807                 
2808         List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2809         QTreeWidgetItem currentSelection;
2810         selectedSavedSearchGUID = "";
2811         for (int i=0; i<selections.size(); i++) {
2812                 currentSelection = selections.get(i);
2813                 if (currentSelection.text(1).equals(currentGuid)) {
2814                         currentSelection.setSelected(false);
2815                 } else {
2816                         selectedSavedSearchGUID = currentSelection.text(1);
2817                 }
2818 //              i = selections.size() +1;
2819         }
2820         
2821         // There is the potential for no notebooks to be selected if this 
2822         // happens then we make it look like all notebooks were selecetd.
2823         // If that happens, just select the "all notebooks"
2824         if (selections.size()==0) {
2825                 clearSavedSearchFilter();
2826         }
2827         listManager.setSelectedSavedSearch(selectedSavedSearchGUID);
2828         
2829         logger.log(logger.HIGH, "Leaving NeverNote.savedSearchTreeSelection");
2830     }
2831     private void clearSavedSearchFilter() {
2832         menuBar.savedSearchEditAction.setEnabled(false);
2833         menuBar.savedSearchDeleteAction.setEnabled(false);
2834         menuBar.savedSearchIconAction.setEnabled(false);
2835         savedSearchTree.blockSignals(true);
2836         savedSearchTree.clearSelection();
2837         savedSearchTree.blockSignals(false);
2838         selectedSavedSearchGUID = "";
2839         searchField.setEditText("");
2840         searchPerformed = false;
2841         listManager.setSelectedSavedSearch(selectedSavedSearchGUID);
2842     }
2843     // trigger the tag index to be refreshed
2844         private void savedSearchIndexUpdated() { 
2845                 if (selectedSavedSearchGUID == null)
2846                         selectedSavedSearchGUID = new String();
2847                 savedSearchTree.blockSignals(true);
2848                 savedSearchTree.setIcons(conn.getSavedSearchTable().getAllIcons());
2849         savedSearchTree.load(listManager.getSavedSearchIndex());
2850         savedSearchTree.selectGuid(selectedSavedSearchGUID);
2851         savedSearchTree.blockSignals(false);
2852     }
2853     // trigger when the saved search selection changes
2854     @SuppressWarnings("unused")
2855         private void updateSavedSearchSelection() {
2856                 logger.log(logger.HIGH, "Entering NeverNote.updateSavedSearchSelection()");
2857                 
2858         menuBar.savedSearchEditAction.setEnabled(true);
2859         menuBar.savedSearchDeleteAction.setEnabled(true);
2860         menuBar.savedSearchIconAction.setEnabled(true);
2861         List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2862
2863         if (selections.size() > 0) {
2864                 menuBar.savedSearchEditAction.setEnabled(true);
2865                 menuBar.savedSearchDeleteAction.setEnabled(true);
2866                 menuBar.savedSearchIconAction.setEnabled(true);
2867                 selectedSavedSearchGUID = selections.get(0).text(1);
2868                 SavedSearch s = conn.getSavedSearchTable().getSavedSearch(selectedSavedSearchGUID);
2869                 searchField.setEditText(s.getQuery());
2870         } else { 
2871                 menuBar.savedSearchEditAction.setEnabled(false);
2872                 menuBar.savedSearchDeleteAction.setEnabled(false);
2873                 menuBar.savedSearchIconAction.setEnabled(false);
2874                 selectedSavedSearchGUID = "";
2875                 searchField.setEditText("");
2876         }
2877         searchFieldChanged();
2878         
2879                 logger.log(logger.HIGH, "Leaving NeverNote.updateSavedSearchSelection()");
2880
2881         
2882     }
2883     // Show/Hide note information
2884         @SuppressWarnings("unused")
2885         private void toggleSavedSearchWindow() {
2886                 logger.log(logger.HIGH, "Entering NeverNote.toggleSavedSearchWindow");
2887         if (savedSearchTree.isVisible())
2888                 savedSearchTree.hide();
2889         else
2890                 savedSearchTree.show();
2891         menuBar.hideSavedSearches.setChecked(savedSearchTree.isVisible());
2892                                 
2893                 Global.saveWindowVisible("savedSearchTree", savedSearchTree.isVisible());
2894         logger.log(logger.HIGH, "Leaving NeverNote.toggleSavedSearchWindow");
2895     }
2896         // Change the icon for a saved search
2897         @SuppressWarnings("unused")
2898         private void setSavedSearchIcon() {
2899                 QTreeWidgetItem currentSelection;
2900                 List<QTreeWidgetItem> selections = savedSearchTree.selectedItems();
2901                 if (selections.size() == 0)
2902                         return;
2903                 
2904                 currentSelection = selections.get(0);   
2905                 String guid = currentSelection.text(1);
2906
2907                 QIcon currentIcon = currentSelection.icon(0);
2908                 QIcon icon = conn.getSavedSearchTable().getIcon(guid);
2909                 SetIcon dialog;
2910                 if (icon == null) {
2911                         dialog = new SetIcon(currentIcon, saveLastPath);
2912                         dialog.setUseDefaultIcon(true);
2913                 } else {
2914                         dialog = new SetIcon(icon, saveLastPath);
2915                         dialog.setUseDefaultIcon(false);
2916                 }
2917                 dialog.exec();
2918                 if (dialog.okPressed()) {
2919                 saveLastPath = dialog.getPath();
2920                         QIcon newIcon = dialog.getIcon();
2921                         conn.getSavedSearchTable().setIcon(guid, newIcon, dialog.getFileType());
2922                         if (newIcon == null) 
2923                                 newIcon = new QIcon(iconPath+"search.png");
2924                         currentSelection.setIcon(0, newIcon);
2925                 }
2926         
2927         }
2928         
2929         
2930         
2931         
2932     //***************************************************************
2933     //***************************************************************
2934     //** These functions deal with Help menu & tool menu items
2935     //***************************************************************
2936     //***************************************************************
2937         // Show database status
2938         @SuppressWarnings("unused")
2939         private void databaseStatus() {
2940                 waitCursor(true);
2941                 indexRunner.interrupt = true;
2942                 int dirty = conn.getNoteTable().getDirtyCount();
2943                 int unindexed = conn.getNoteTable().getUnindexedCount();
2944                 DatabaseStatus status = new DatabaseStatus();
2945                 status.setUnsynchronized(dirty);
2946                 status.setUnindexed(unindexed);
2947                 status.setNoteCount(conn.getNoteTable().getNoteCount());
2948                 status.setNotebookCount(listManager.getNotebookIndex().size());
2949                 status.setUnindexedResourceCount(conn.getNoteTable().noteResourceTable.getUnindexedCount());
2950                 status.setSavedSearchCount(listManager.getSavedSearchIndex().size());
2951                 status.setTagCount(listManager.getTagIndex().size());
2952                 status.setResourceCount(conn.getNoteTable().noteResourceTable.getResourceCount());
2953                 status.setWordCount(conn.getWordsTable().getWordCount());
2954                 waitCursor(false);
2955                 status.exec();
2956         }
2957         // Compact the database
2958         @SuppressWarnings("unused")
2959         private void compactDatabase() {
2960         logger.log(logger.HIGH, "Entering NeverNote.compactDatabase");
2961                 if (QMessageBox.question(this, tr("Confirmation"), tr("This will free unused space in the database, "+
2962                                 "but please be aware that depending upon the size of your database this can be time consuming " +
2963                                 "and NeighborNote will be unresponsive until it is complete.  Do you wish to continue?"),
2964                                 QMessageBox.StandardButton.Yes, 
2965                                 QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) {
2966                                                         return;
2967                 }
2968                 setMessage("Compacting database.");
2969                 waitCursor(true);
2970                 listManager.compactDatabase();
2971                 waitCursor(false);
2972                 setMessage("Database compact is complete.");            
2973         logger.log(logger.HIGH, "Leaving NeverNote.compactDatabase");
2974     }
2975         @SuppressWarnings("unused")
2976         private void accountInformation() {
2977                 logger.log(logger.HIGH, "Entering NeverNote.accountInformation");
2978                 AccountDialog dialog = new AccountDialog();
2979                 dialog.show();
2980                 logger.log(logger.HIGH, "Leaving NeverNote.accountInformation");
2981         }
2982         @SuppressWarnings("unused")
2983         private void releaseNotes() {
2984                 logger.log(logger.HIGH, "Entering NeverNote.releaseNotes");
2985                 QDialog dialog = new QDialog(this);
2986                 QHBoxLayout layout = new QHBoxLayout();
2987                 QTextEdit textBox = new QTextEdit();
2988                 layout.addWidget(textBox);
2989                 textBox.setReadOnly(true);
2990                 QFile file = new QFile(Global.getFileManager().getProgramDirPath("release.txt"));
2991                 if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly,
2992                 QIODevice.OpenModeFlag.Text)))
2993                         return;
2994                 // ICHANGED 日本語文字化け対策
2995                 QTextCodec codec = QTextCodec.codecForName("UTF-8");
2996                 QTextStream textStream = new QTextStream(file);
2997                 textStream.setCodec(codec);
2998                 textBox.setText(textStream.readAll().toString());
2999                 
3000                 file.close();
3001                 dialog.setWindowTitle(tr("Release Notes"));
3002                 dialog.setLayout(layout);
3003                 dialog.show();
3004                 logger.log(logger.HIGH, "Leaving NeverNote.releaseNotes");
3005         }
3006         // Called when user picks Log from the help menu
3007         @SuppressWarnings("unused")
3008         private void logger() {
3009                 logger.log(logger.HIGH, "Entering NeverNote.logger");
3010                 LogFileDialog dialog = new LogFileDialog(emitLog);
3011                 dialog.exec();
3012                 logger.log(logger.HIGH, "Leaving NeverNote.logger");
3013         }
3014         // Menu option "help/about" was selected
3015         @SuppressWarnings("unused")
3016         private void about() {
3017                 logger.log(logger.HIGH, "Entering NeverNote.about");
3018                 // ICHANGED based on...の記述を付加
3019                 QMessageBox.about(this, 
3020                                                 tr("About NeighborNote"),
3021                                                 tr("<h4><center><b>NeighborNote</b></center></h4><hr><center>Version ")
3022                                                 +Global.version + "(based on NixNote 1.5)"
3023                                                 //+"1.2.120724"
3024                                                 +tr("<hr>"
3025                                                                 +"Open Source Evernote Client.<br><br>" 
3026                                                                 +"Licensed under GPL v2.  <br><hr><br>"
3027                                                                 +"</center>Evernote is copyright 2001-2012 by Evernote Corporation<br>"
3028                                                                 +"Jambi and QT are the licensed trademark of Nokia Corporation<br>"
3029                                                                 +"PDFRenderer is licened under the LGPL<br>"
3030                                                                 +"JTidy is copyrighted under the World Wide Web Consortium<br>"
3031                                                                 +"Apache Common Utilities licensed under the Apache License Version 2.0<br>"
3032                                                                 +"Jazzy is licened under the LGPL<br>"
3033                                                                 +"Java is a registered trademark of Oracle Corporation.<br><hr>"
3034                                                                 +"Special thanks to:<br>BitRock InstallBuilder for the Windows installer"
3035                                                                 +"<br>CodeCogs (www.codecogs.com) for the LaTeX image rendering."));
3036                 logger.log(logger.HIGH, "Leaving NeverNote.about");
3037         }
3038         // Hide the entire left hand side
3039         @SuppressWarnings("unused")
3040         private void toggleLeftSide() {
3041                 boolean hidden;
3042                 
3043                 hidden = !menuBar.hideLeftSide.isChecked();
3044                 menuBar.hideLeftSide.setChecked(!hidden);
3045                 
3046                 if (!hidden) 
3047                         leftSplitter1.setHidden(true);
3048                 else
3049                         leftSplitter1.setHidden(false);
3050                 
3051                 Global.saveWindowVisible("leftPanel", hidden);
3052                 
3053         }
3054         public void checkForUpdates() {
3055                 // Send off thread to check for a new version
3056                 versionChecker = new QNetworkAccessManager(this);
3057                 versionChecker.finished.connect(this, "upgradeFileRead(QNetworkReply)");
3058                 QNetworkRequest request = new QNetworkRequest();
3059                 request.setUrl(new QUrl(Global.getUpdatesAvailableUrl()));
3060                 versionChecker.get(request);
3061         }
3062         @SuppressWarnings("unused")
3063         private void upgradeFileRead(QNetworkReply reply) {
3064                 if (!reply.isReadable())
3065                         return;
3066                 
3067                 String winVersion = Global.version;
3068                 String osxVersion = Global.version;
3069                 String linuxVersion = Global.version;
3070                 String linux64Version = Global.version;
3071                 String version = Global.version;
3072                 
3073                 // Determine the versions available
3074                 QByteArray data = reply.readLine();
3075                 while (data != null && !reply.atEnd()) {
3076                         String line = data.toString();
3077                         String lineVersion;
3078                         if (line.contains(":")) 
3079                                 lineVersion = line.substring(line.indexOf(":")+1).replace(" ", "").replace("\n", "");
3080                         else
3081                                 lineVersion = "";
3082                         if (line.toLowerCase().contains("windows")) 
3083                                 winVersion = lineVersion;
3084                         else if (line.toLowerCase().contains("os-x")) 
3085                                 osxVersion = lineVersion;
3086                         else if (line.toLowerCase().contains("linux amd64")) 
3087                                 linux64Version = lineVersion;
3088                         else if (line.toLowerCase().contains("linux i386")) 
3089                                 linuxVersion = lineVersion;
3090                         else if (line.toLowerCase().contains("default")) 
3091                                 version = lineVersion;
3092                         
3093                         // Read the next line
3094                         data = reply.readLine();
3095                 }
3096                 
3097                 // Now we need to determine what system we are on.
3098                 if (System.getProperty("os.name").toLowerCase().contains("windows"))
3099                         version = winVersion;
3100                 if (System.getProperty("os.name").toLowerCase().contains("mac os"))
3101                         version = osxVersion;
3102                 if (System.getProperty("os.name").toLowerCase().contains("Linux")) {
3103                         if (System.getProperty("os.arch").contains("amd64") ||
3104                                 System.getProperty("os.arch").contains("x86_64"))
3105                                         version = linux64Version;
3106                         else
3107                                 version = linuxVersion;
3108                 }
3109                 
3110                 
3111                 for (String validVersion : Global.validVersions) {
3112                         if (version.equals(validVersion))
3113                                 return;
3114                 }
3115                 
3116                 UpgradeAvailableDialog dialog = new UpgradeAvailableDialog();
3117                 dialog.exec();
3118                 if (dialog.remindMe())
3119                         Global.setCheckVersionUpgrade(true);
3120                 else
3121                         Global.setCheckVersionUpgrade(false);
3122         }
3123                 
3124         
3125     //***************************************************************
3126     //***************************************************************
3127     //** These functions deal with the Toolbar
3128     //***************************************************************
3129     //*************************************************************** 
3130         @SuppressWarnings("unused")
3131         private void focusSearch() {
3132                 searchField.setFocus();
3133         }
3134
3135         // Text in the search bar has been cleared
3136         private void searchFieldCleared() {
3137                 saveNote();
3138                 
3139                 // This is done because we want to force a reload of
3140                 // images.  Some images we may want to highlight the text.
3141                 readOnlyCache.clear();
3142                 inkNoteCache.clear();
3143                 noteCache.clear();
3144                 QWebSettings.setMaximumPagesInCache(0);
3145                 QWebSettings.setObjectCacheCapacities(0, 0, 0);
3146         
3147                 searchField.setEditText("");
3148                 saveNoteColumnPositions();
3149                 saveNoteIndexWidth();
3150                 noteIndexUpdated(true);
3151                 if (currentNote == null && listManager.getNoteIndex().size() > 0) {
3152                         currentNote = listManager.getNoteIndex().get(0);
3153                         currentNoteGuid = currentNote.getGuid();
3154                 }
3155                 refreshEvernoteNote(true);
3156                 if (currentNote != null)
3157                         loadNoteBrowserInformation(browserWindow, currentNoteGuid, currentNote);
3158         }
3159         // text in the search bar changed.  We only use this to tell if it was cleared, 
3160         // otherwise we trigger off searchFieldChanged.
3161         @SuppressWarnings("unused")
3162         private void searchFieldTextChanged(String text) {
3163                 QWebSettings.setMaximumPagesInCache(0);
3164                 QWebSettings.setObjectCacheCapacities(0, 0, 0);
3165
3166                 if (text.trim().equals("")) {
3167                         searchFieldCleared();
3168                         if (searchPerformed) {
3169
3170                                 // This is done because we want to force a reload of
3171                                 // images.  Some images we may want to highlight the text.
3172                                 noteCache.clear();
3173                                 readOnlyCache.clear();
3174                                 inkNoteCache.clear();
3175                                 
3176                                 listManager.setEnSearch("");
3177                                 listManager.loadNotesIndex();
3178                                 refreshEvernoteNote(true);
3179                                 noteIndexUpdated(false);
3180                                 refreshEvernoteNote(true);
3181                         }
3182                         searchPerformed = false;
3183                 }
3184         }
3185     // Text in the toolbar has changed
3186     private void searchFieldChanged() {
3187         logger.log(logger.HIGH, "Entering NeverNote.searchFieldChanged");
3188         noteCache.clear();
3189         readOnlyCache.clear();
3190         inkNoteCache.clear();
3191         saveNoteColumnPositions();
3192         saveNoteIndexWidth();
3193         String text = searchField.currentText();
3194         listManager.setEnSearch(text.trim());
3195         listManager.loadNotesIndex();
3196         noteIndexUpdated(false);
3197
3198         refreshEvernoteNote(true);
3199         searchPerformed = true;
3200         waitCursor(false);
3201         logger.log(logger.HIGH, "Leaving NeverNote.searchFieldChanged");
3202     }
3203
3204     // Build the window tool bar
3205     private void setupToolBar() {
3206         logger.log(logger.HIGH, "Entering NeverNote.setupToolBar");
3207         toolBar = addToolBar(tr("Tool Bar"));   
3208         toolBar.setObjectName("toolBar");
3209         menuBar.setupToolBarVisible();
3210         if (!Global.isWindowVisible("toolBar"))
3211                 toolBar.setVisible(false);
3212         else
3213                 toolBar.setVisible(true);
3214
3215 //      toolBar.addWidget(menuBar);
3216 //      menuBar.setSizePolicy(Policy.Minimum, Policy.Minimum);
3217 //      toolBar.addSeparator();
3218         prevButton = toolBar.addAction(tr("Previous"));
3219         QIcon prevIcon = new QIcon(iconPath+"back.png");
3220         prevButton.setIcon(prevIcon);
3221         prevButton.triggered.connect(this, "previousViewedAction()");   
3222         togglePrevArrowButton(Global.isToolbarButtonVisible("prevArrow"));
3223         
3224         nextButton = toolBar.addAction(tr("Next"));
3225         QIcon nextIcon = new QIcon(iconPath+"forward.png");
3226         nextButton.setIcon(nextIcon);
3227         nextButton.triggered.connect(this, "nextViewedAction()");       
3228         toggleNextArrowButton(Global.isToolbarButtonVisible("nextArrow"));
3229         
3230         upButton = toolBar.addAction(tr("Up"));
3231         QIcon upIcon = new QIcon(iconPath+"up.png");
3232         upButton.setIcon(upIcon);
3233         upButton.triggered.connect(this, "upAction()");         
3234         toggleUpArrowButton(Global.isToolbarButtonVisible("upArrow"));
3235
3236         
3237         downButton = toolBar.addAction(tr("Down"));
3238         QIcon downIcon = new QIcon(iconPath+"down.png");
3239         downButton.setIcon(downIcon);
3240         downButton.triggered.connect(this, "downAction()");
3241         toggleDownArrowButton(Global.isToolbarButtonVisible("downArrow"));
3242         
3243         synchronizeButton = toolBar.addAction(tr("Synchronize"));
3244         synchronizeButton.setIcon(new QIcon(iconPath+"synchronize.png"));
3245         synchronizeIconAngle = 0;
3246         synchronizeButton.triggered.connect(this, "evernoteSync()");
3247         toggleSynchronizeButton(Global.isToolbarButtonVisible("synchronize"));
3248         
3249         printButton = toolBar.addAction(tr("Print"));
3250         QIcon printIcon = new QIcon(iconPath+"print.png");
3251         printButton.setIcon(printIcon);
3252         printButton.triggered.connect(this, "printNote()");
3253         togglePrintButton(Global.isToolbarButtonVisible("print"));
3254
3255         tagButton = toolBar.addAction(tr("Tag")); 
3256         QIcon tagIcon = new QIcon(iconPath+"tag.png");
3257         tagButton.setIcon(tagIcon);
3258         tagButton.triggered.connect(browserWindow, "modifyTags()");
3259         toggleTagButton(Global.isToolbarButtonVisible("tag"));
3260
3261         attributeButton = toolBar.addAction(tr("Attributes")); 
3262         QIcon attributeIcon = new QIcon(iconPath+"attribute.png");
3263         attributeButton.setIcon(attributeIcon);
3264         attributeButton.triggered.connect(this, "toggleNoteAttributes()");
3265         toggleAttributeButton(Global.isToolbarButtonVisible("attribute"));
3266                 
3267         emailButton = toolBar.addAction(tr("Email"));
3268         QIcon emailIcon = new QIcon(iconPath+"email.png");
3269         emailButton.setIcon(emailIcon);
3270         emailButton.triggered.connect(this, "emailNote()");
3271         toggleEmailButton(Global.isToolbarButtonVisible("email"));
3272
3273         deleteButton = toolBar.addAction(tr("Delete"));         
3274         QIcon deleteIcon = new QIcon(iconPath+"delete.png");
3275         deleteButton.setIcon(deleteIcon);
3276         deleteButton.triggered.connect(this, "deleteNote()");
3277         toggleDeleteButton(Global.isToolbarButtonVisible("delete"));
3278
3279         newButton = toolBar.addAction(tr("New"));
3280         QIcon newIcon = new QIcon(iconPath+"new.png");
3281         newButton.triggered.connect(this, "addNote()");
3282         newButton.setIcon(newIcon);
3283         toggleNewButton(Global.isToolbarButtonVisible("new"));
3284         
3285         allNotesButton = toolBar.addAction(tr("All Notes"));
3286         QIcon allIcon = new QIcon(iconPath+"books.png");
3287         allNotesButton.triggered.connect(this, "allNotes()");
3288         allNotesButton.setIcon(allIcon);
3289         toggleAllNotesButton(Global.isToolbarButtonVisible("allNotes"));
3290         
3291         //toolBar.addSeparator();
3292         //toolBar.addWidget(new QLabel(tr("Quota:")));
3293         //toolBar.addWidget(quotaBar);
3294         //quotaBar.setSizePolicy(Policy.Minimum, Policy.Minimum);
3295         updateQuotaBar();
3296         //toolBar.addSeparator();
3297         
3298         //toolBar.addWidget(new QLabel(tr("Zoom")));
3299         //toolBar.addWidget(zoomSpinner);
3300         
3301         //toolBar.addWidget(new QLabel("                    "));
3302         //toolBar.addSeparator();
3303         //toolBar.addWidget(new QLabel(tr("  Search:")));
3304         //toolBar.addWidget(searchField);
3305         QSizePolicy sizePolicy = new QSizePolicy();
3306         sizePolicy.setHorizontalPolicy(Policy.MinimumExpanding);
3307         QLabel spacer = new QLabel("");
3308         spacer.setSizePolicy(sizePolicy);
3309         toolBar.addWidget(spacer);
3310         //searchField.setInsertPolicy(InsertPolicy.InsertAtTop);
3311
3312         //searchClearButton = toolBar.addAction("Search Clear");
3313         //QIcon searchClearIcon = new QIcon(iconPath+"searchclear.png");
3314         //searchClearButton.setIcon(searchClearIcon);
3315         //searchClearButton.triggered.connect(this, "searchFieldCleared()");
3316         //toggleSearchClearButton(Global.isToolbarButtonVisible("searchClear"));
3317
3318         logger.log(logger.HIGH, "Leaving NeverNote.setupToolBar");
3319     }
3320     // Update the sychronize button picture
3321     @Override
3322         public QMenu createPopupMenu() {
3323         QMenu contextMenu = super.createPopupMenu();
3324         
3325         contextMenu.addSeparator();
3326         QAction prevAction = addContextAction("prevArrow", tr("Previous Arrow"));
3327         contextMenu.addAction(prevAction);
3328         prevAction.triggered.connect(this, "togglePrevArrowButton(Boolean)");
3329
3330         QAction nextAction = addContextAction("nextArrow", tr("Next Arrow"));
3331         contextMenu.addAction(nextAction);
3332         nextAction.triggered.connect(this, "toggleNextArrowButton(Boolean)");
3333
3334         QAction upAction = addContextAction("upArrow", tr("Up Arrow"));
3335         contextMenu.addAction(upAction);
3336         upAction.triggered.connect(this, "toggleUpArrowButton(Boolean)");
3337
3338         QAction downAction = addContextAction("downArrow", tr("Down Arrow"));
3339         contextMenu.addAction(downAction);
3340         downAction.triggered.connect(this, "toggleDownArrowButton(Boolean)");
3341
3342         QAction synchronizeAction = addContextAction("synchronize", tr("Synchronize"));
3343         contextMenu.addAction(synchronizeAction);
3344         synchronizeAction.triggered.connect(this, "toggleSynchronizeButton(Boolean)");
3345
3346         QAction printAction = addContextAction("print", tr("Print"));
3347         contextMenu.addAction(printAction);
3348         printAction.triggered.connect(this, "togglePrintButton(Boolean)");
3349
3350         QAction tagAction = addContextAction("tag", tr("Tag"));
3351         contextMenu.addAction(tagAction);
3352         tagAction.triggered.connect(this, "toggleTagButton(Boolean)");
3353         
3354         QAction attributeAction = addContextAction("attribute", tr("Attribute"));
3355         contextMenu.addAction(attributeAction);
3356         attributeAction.triggered.connect(this, "toggleAttributeButton(Boolean)");
3357         
3358         QAction emailAction = addContextAction("email", tr("Email"));
3359         contextMenu.addAction(emailAction);
3360         emailAction.triggered.connect(this, "toggleEmailButton(Boolean)");
3361
3362         QAction deleteAction = addContextAction("delete", tr("Delete"));
3363         contextMenu.addAction(deleteAction);
3364         deleteAction.triggered.connect(this, "toggleDeleteButton(Boolean)");
3365
3366         QAction newAction = addContextAction("new", tr("Add"));
3367         contextMenu.addAction(newAction);
3368         newAction.triggered.connect(this, "toggleNewButton(Boolean)");
3369
3370         QAction allNotesAction = addContextAction("allNotes", tr("All Notes"));
3371         contextMenu.addAction(allNotesAction);
3372         allNotesAction.triggered.connect(this, "toggleAllNotesButton(Boolean)");
3373         
3374         QAction searchClearAction = addContextAction("searchClear", tr("Search Clear"));
3375         contextMenu.addAction(searchClearAction);
3376         searchClearAction.triggered.connect(this, "toggleSearchClearButton(Boolean)");
3377         
3378         return contextMenu;
3379         
3380     }
3381     private QAction addContextAction(String config, String name) {
3382         QAction newAction = new QAction(this);
3383                 newAction.setText(name);
3384                 newAction.setCheckable(true);
3385                 newAction.setChecked(Global.isToolbarButtonVisible(config));
3386                 return newAction;
3387     }
3388     private void togglePrevArrowButton(Boolean toggle) {
3389                 prevButton.setVisible(toggle);
3390                 Global.saveToolbarButtonsVisible("prevArrow", toggle);
3391     }
3392     private void toggleNextArrowButton(Boolean toggle) {
3393                 nextButton.setVisible(toggle);
3394                 Global.saveToolbarButtonsVisible("nextArrow", toggle);
3395     }
3396     private void toggleUpArrowButton(Boolean toggle) {
3397                 upButton.setVisible(toggle);
3398                 Global.saveToolbarButtonsVisible("upArrow", toggle);
3399     }
3400     private void toggleDownArrowButton(Boolean toggle) {
3401                 downButton.setVisible(toggle);
3402                 Global.saveToolbarButtonsVisible("downArrow", toggle);
3403     }
3404     private void toggleSynchronizeButton(Boolean toggle) {
3405                 synchronizeButton.setVisible(toggle);
3406                 Global.saveToolbarButtonsVisible("synchronize", toggle);
3407     }
3408     private void togglePrintButton(Boolean toggle) {
3409                 printButton.setVisible(toggle);
3410                 Global.saveToolbarButtonsVisible("print", toggle);
3411     }
3412     private void toggleTagButton(Boolean toggle) {
3413                 tagButton.setVisible(toggle);
3414                 Global.saveToolbarButtonsVisible("tag", toggle);
3415     }
3416     private void toggleAttributeButton(Boolean toggle) {
3417                 attributeButton.setVisible(toggle);
3418                 Global.saveToolbarButtonsVisible("attribute", toggle);
3419     }
3420     private void toggleEmailButton(Boolean toggle) {
3421                 emailButton.setVisible(toggle);
3422                 Global.saveToolbarButtonsVisible("email", toggle);
3423     }
3424     private void toggleDeleteButton(Boolean toggle) {
3425                 deleteButton.setVisible(toggle);
3426                 Global.saveToolbarButtonsVisible("delete", toggle);
3427     }
3428     private void toggleNewButton(Boolean toggle) {
3429                 newButton.setVisible(toggle);
3430                 Global.saveToolbarButtonsVisible("new", toggle);
3431     }
3432     private void toggleAllNotesButton(Boolean toggle) {
3433                 allNotesButton.setVisible(toggle);
3434                 Global.saveToolbarButtonsVisible("allNotes", toggle);
3435     }
3436     @SuppressWarnings("unused")
3437         private void toggleSearchClearButton(Boolean toggle) {
3438                 searchClearButton.setVisible(toggle);
3439                 Global.saveToolbarButtonsVisible("searchClear", toggle);
3440     }
3441
3442
3443
3444
3445
3446     @SuppressWarnings("unused")
3447         private void updateSyncButton() {
3448                 
3449         if (syncIcons == null) {
3450                 syncIcons = new ArrayList<QPixmap>();
3451                 double angle = 0.0;
3452                 synchronizeIconAngle = 0;
3453                 QPixmap pix = new QPixmap(iconPath+"synchronize.png");
3454                 syncIcons.add(pix);
3455                 for (int i=0; i<=360; i++) {
3456                         QPixmap rotatedPix = new QPixmap(pix.size());
3457                         QPainter p = new QPainter(rotatedPix);
3458                 rotatedPix.fill(toolBar.palette().color(ColorRole.Button));
3459                 QSize size = pix.size();
3460                 p.translate(size.width()/2, size.height()/2);
3461                 angle = angle+1.0;
3462                 p.rotate(angle);
3463                 p.setBackgroundMode(BGMode.OpaqueMode);
3464                 p.translate(-size.width()/2, -size.height()/2);
3465                 p.drawPixmap(0,0, pix);
3466                 p.end();
3467                 syncIcons.add(rotatedPix);
3468                 }
3469         }
3470
3471         synchronizeIconAngle++;
3472         if (synchronizeIconAngle > 359)
3473                 synchronizeIconAngle=0;
3474         synchronizeButton.setIcon(syncIcons.get(synchronizeIconAngle));
3475         
3476     }
3477     // Synchronize with Evernote
3478
3479         private void evernoteSync() {
3480         logger.log(logger.HIGH, "Entering NeverNote.evernoteSync");
3481         if (!Global.isConnected)
3482                 remoteConnect();
3483         if (Global.isConnected)
3484                 synchronizeAnimationTimer.start(5);
3485 //                      synchronizeAnimationTimer.start(200);
3486         syncTimer();
3487         logger.log(logger.HIGH, "Leaving NeverNote.evernoteSync");
3488     }
3489     private void updateQuotaBar() {
3490         long limit = Global.getUploadLimit();
3491         long amount = Global.getUploadAmount();
3492         if (amount>0 && limit>0) {
3493                 int percent =(int)(amount*100/limit);
3494                 quotaBar.setValue(percent);
3495         } else 
3496                 quotaBar.setValue(0);
3497     }
3498         // Zoom changed
3499     @SuppressWarnings("unused")
3500         private void zoomChanged() {
3501         browserWindow.getBrowser().setZoomFactor(new Double(zoomSpinner.value())/100);
3502     }
3503
3504     //****************************************************************
3505     //****************************************************************
3506     //* System Tray functions
3507     //****************************************************************
3508     //****************************************************************
3509         private void trayToggleVisible() {
3510         if (isVisible()) {
3511                 hide();
3512         } else {
3513                 show();
3514                 if (windowMaximized)
3515                         showMaximized();
3516                 else
3517                         showNormal();
3518                 raise();
3519         }
3520     }
3521     @SuppressWarnings("unused")
3522         private void trayActivated(QSystemTrayIcon.ActivationReason reason) {
3523         if (reason == QSystemTrayIcon.ActivationReason.DoubleClick) {
3524                 String name = QSystemTrayIcon.MessageIcon.resolve(reason.value()).name();
3525                 trayToggleVisible();
3526         }
3527     }
3528     
3529     
3530     //***************************************************************
3531     //***************************************************************
3532     //** These functions deal with the trash tree
3533     //***************************************************************
3534     //***************************************************************    
3535     // Setup the tree containing the trash.
3536     @SuppressWarnings("unused")
3537         private void trashTreeSelection() {     
3538         logger.log(logger.HIGH, "Entering NeverNote.trashTreeSelection");
3539         
3540         clearNotebookFilter();
3541         clearTagFilter();
3542         clearAttributeFilter();
3543         clearSavedSearchFilter();
3544         
3545         String tempGuid = currentNoteGuid;
3546         
3547 //      currentNoteGuid = "";
3548         currentNote = new Note();
3549         selectedNoteGUIDs.clear();
3550         listManager.getSelectedNotebooks().clear();
3551         listManager.getSelectedTags().clear();
3552         listManager.setSelectedSavedSearch("");
3553         browserWindow.clear();
3554     
3555         // toggle the add buttons
3556         newButton.setEnabled(!newButton.isEnabled());
3557         menuBar.noteAdd.setEnabled(newButton.isEnabled());
3558         menuBar.noteAdd.setVisible(true);
3559         
3560         List<QTreeWidgetItem> selections = trashTree.selectedItems();
3561         if (selections.size() == 0) {
3562                 currentNoteGuid = trashNoteGuid;
3563                         trashNoteGuid = tempGuid;
3564                 Global.showDeleted = false;
3565                 menuBar.noteRestoreAction.setEnabled(false);
3566                 menuBar.noteRestoreAction.setVisible(false);
3567                         // ICHANGED ゴミ箱から元の画面に戻す。連想ノートリストをONに。
3568                         rensoNoteListDock.setEnabled(true);
3569         }
3570         else {
3571                 trashNoteGuid = tempGuid;
3572                 currentNoteGuid = trashNoteGuid;
3573                 menuBar.noteRestoreAction.setEnabled(true);
3574                 menuBar.noteRestoreAction.setVisible(true);
3575                 // ICHANGED ゴミ箱を開く。連想ノートリストをOFFに。
3576                 rensoNoteListDock.setEnabled(false);
3577                                         
3578                 Global.showDeleted = true;
3579         }
3580         listManager.loadNotesIndex();
3581         noteIndexUpdated(false);
3582 ////            browserWindow.setEnabled(newButton.isEnabled());
3583         browserWindow.setReadOnly(!newButton.isEnabled());
3584         logger.log(logger.HIGH, "Leaving NeverNote.trashTreeSelection");
3585     }
3586     // Empty the trash file
3587     @SuppressWarnings("unused")
3588         private void emptyTrash() {
3589 //      browserWindow.clear();
3590         logger.log(logger.EXTREME, "Emptying Trash");
3591         listManager.emptyTrash();
3592         logger.log(logger.EXTREME, "Resetting view after trash empty");
3593         if (trashTree.selectedItems().size() > 0) {
3594                 listManager.getSelectedNotebooks().clear();
3595                 listManager.getSelectedTags().clear();
3596                 listManager.setSelectedSavedSearch("");
3597                 newButton.setEnabled(!newButton.isEnabled());
3598                 menuBar.noteAdd.setEnabled(newButton.isEnabled());
3599                 menuBar.noteAdd.setVisible(true);
3600                 browserWindow.clear();
3601                 
3602                 clearTagFilter();
3603                 clearNotebookFilter();
3604                 clearSavedSearchFilter();
3605                 clearAttributeFilter();
3606                         
3607                 Global.showDeleted = false;
3608                 menuBar.noteRestoreAction.setEnabled(false);
3609                 menuBar.noteRestoreAction.setVisible(false);
3610                 
3611                 listManager.loadNotesIndex();
3612                 noteIndexUpdated(false);
3613                 
3614                 // ICHANGED ゴミ箱から元の画面に戻す。連想ノートリストをONに。
3615                 if (!rensoNoteListDock.isEnabled()) {
3616                         rensoNoteListDock.setEnabled(true);
3617                 }
3618         }       
3619    }
3620     // Show/Hide trash window
3621         @SuppressWarnings("unused")
3622         private void toggleTrashWindow() {
3623                 logger.log(logger.HIGH, "Entering NeverNote.toggleTrashWindow");
3624         if (trashTree.isVisible())
3625                 trashTree.hide();
3626         else
3627                 trashTree.show();
3628         menuBar.hideTrash.setChecked(trashTree.isVisible());
3629         
3630                 Global.saveWindowVisible("trashTree", trashTree.isVisible());
3631         logger.log(logger.HIGH, "Leaving NeverNote.trashWindow");
3632     }    
3633         private void clearTrashFilter() {
3634                 Global.showDeleted = false;
3635         newButton.setEnabled(true);
3636         menuBar.noteAdd.setEnabled(true);
3637         menuBar.noteAdd.setVisible(true);
3638                 trashTree.blockSignals(true);
3639                 trashTree.clearSelection();
3640                 trashTree.blockSignals(false);
3641                 
3642         }
3643     
3644    
3645     //***************************************************************
3646     //***************************************************************
3647     //** These functions deal with connection settings
3648     //***************************************************************
3649     //***************************************************************
3650         // SyncRunner had a problem and things are disconnected
3651         @SuppressWarnings("unused")
3652         private void remoteErrorDisconnect() {
3653                 menuBar.connectAction.setText(tr("Connect"));
3654                 menuBar.connectAction.setToolTip(tr("Connect to Evernote"));
3655                 menuBar.synchronizeAction.setEnabled(false);
3656                 Global.isConnected = false;
3657                 synchronizeAnimationTimer.stop();
3658                 return;
3659         }
3660         // Do a manual connect/disconnect
3661     private void remoteConnect() {
3662         
3663         logger.log(logger.HIGH, "Entering NeverNote.remoteConnect");
3664
3665         // If we are already connected, we just disconnect
3666         if (Global.isConnected) {
3667                 Global.isConnected = false;
3668                 syncRunner.enDisconnect();
3669                 setupConnectMenuOptions();
3670                 setupOnlineMenu();
3671                 return;
3672         }
3673         
3674         OAuthTokenizer tokenizer = new OAuthTokenizer();
3675         AESEncrypter aes = new AESEncrypter();
3676         try {
3677                         aes.decrypt(new FileInputStream(Global.getFileManager().getHomeDirFile("oauth.txt")));
3678                 } catch (FileNotFoundException e) {
3679                         // File not found, so we'll just get empty strings anyway. 
3680                 }
3681         
3682                 
3683                 if (Global.getProxyValue("url").equals("")) {
3684                         System.setProperty("http.proxyHost","") ;
3685                         System.setProperty("http.proxyPort", "") ;
3686                         System.setProperty("https.proxyHost","") ;
3687                         System.setProperty("https.proxyPort", "") ;         
3688                 } else {
3689                         // PROXY
3690                         System.setProperty("http.proxyHost",Global.getProxyValue("url")) ;
3691                         System.setProperty("http.proxyPort", Global.getProxyValue("port")) ;
3692                         System.setProperty("https.proxyHost",Global.getProxyValue("url")) ;
3693                         System.setProperty("https.proxyPort", Global.getProxyValue("port")) ;
3694  
3695                         if (Global.getProxyValue("userid").equals("")) {
3696                                 Authenticator.setDefault(new Authenticator() {
3697                         @Override
3698                         protected PasswordAuthentication getPasswordAuthentication() {
3699                                 return new
3700                                 PasswordAuthentication(Global.getProxyValue("userid"),Global.getProxyValue("password").toCharArray());
3701                                 }
3702                         });
3703                 }
3704         }
3705
3706                 syncRunner.userStoreUrl = Global.userStoreUrl;
3707                 syncRunner.noteStoreUrl = Global.noteStoreUrl;
3708                 syncRunner.noteStoreUrlBase = Global.noteStoreUrlBase;
3709                 
3710                 
3711                 
3712                 String authString = aes.getString();
3713                 if (!authString.equals("")) {
3714                         tokenizer.tokenize(authString);
3715                         syncRunner.authToken = tokenizer.oauth_token;
3716                 syncRunner.enConnect();
3717                 }               
3718
3719                 Global.isConnected = syncRunner.isConnected;
3720                 
3721                 if (!Global.isConnected) {
3722                 OAuthWindow window = new OAuthWindow(logger);
3723                 if (window.error) {
3724                         setMessage(window.errorMessage);
3725                         return;
3726                 }
3727                 window.exec();
3728                 if (window.error) {
3729                         setMessage(window.errorMessage);
3730                         return;
3731                         }
3732                 tokenizer.tokenize(window.response);
3733                 if (tokenizer.oauth_token.equals("")) {
3734                         setMessage(tr("Invalid authorization token received."));
3735                         return;
3736                 }
3737                 aes.setString(window.response);
3738                 try {
3739                                 aes.encrypt(new FileOutputStream(Global.getFileManager().getHomeDirFile("oauth.txt")));
3740                         } catch (FileNotFoundException e) {
3741                                 // TODO Auto-generated catch block
3742                                 e.printStackTrace();
3743                         }
3744                 syncRunner.authToken = tokenizer.oauth_token;
3745                         syncRunner.enConnect();
3746                         Global.isConnected = syncRunner.isConnected;
3747                 }
3748 //              Global.username = syncRunner.username;
3749                         
3750                 if (!Global.isConnected)
3751                         return;
3752                 setupOnlineMenu();
3753                 setupConnectMenuOptions();
3754                 logger.log(logger.HIGH, "Leaving NeverNote.remoteConnect");
3755
3756
3757     }
3758     private void setupConnectMenuOptions() {
3759         logger.log(logger.HIGH, "entering NeverNote.setupConnectMenuOptions");
3760                 if (!Global.isConnected) {
3761                         menuBar.connectAction.setText(tr("Connect"));
3762                         menuBar.connectAction.setToolTip(tr("Connect to Evernote"));
3763                         menuBar.synchronizeAction.setEnabled(false);
3764                 } else {
3765                         menuBar.connectAction.setText(tr("Disconnect"));
3766                         menuBar.connectAction.setToolTip(tr("Disconnect from Evernote"));
3767                         menuBar.synchronizeAction.setEnabled(true);
3768                 }
3769                 logger.log(logger.HIGH, "Leaving NeverNote.setupConnectionMenuOptions");
3770     }
3771     
3772     
3773     
3774     //***************************************************************
3775     //***************************************************************
3776     //** These functions deal with the GUI Attribute tree
3777     //***************************************************************
3778     //***************************************************************    
3779     @SuppressWarnings("unused")
3780         private void attributeTreeClicked(QTreeWidgetItem item, Integer integer) {
3781         
3782 //      clearTagFilter();
3783 //      clearNotebookFilter();
3784         clearTrashFilter();
3785 //      clearSavedSearchFilter();
3786         
3787                 // ICHANGED ゴミ箱から元の画面に戻す。連想ノートリストをONに。
3788                 if (!rensoNoteListDock.isEnabled()) {
3789                         rensoNoteListDock.setEnabled(true);
3790                 }
3791
3792         if (attributeTreeSelected == null || item.nativeId() != attributeTreeSelected.nativeId()) {
3793                 if (item.childCount() > 0) {
3794                         item.setSelected(false);
3795                 } else {
3796                 Global.createdBeforeFilter.reset();
3797                 Global.createdSinceFilter.reset();
3798                 Global.changedBeforeFilter.reset();
3799                 Global.changedSinceFilter.reset();
3800                 Global.containsFilter.reset();
3801                         attributeTreeSelected = item;
3802                         DateAttributeFilterTable f = null;
3803                         f = findDateAttributeFilterTable(item.parent());
3804                         if (f!=null)
3805                                 f.select(item.parent().indexOfChild(item));
3806                         else {
3807                                 Global.containsFilter.select(item.parent().indexOfChild(item));
3808                         }
3809                 }
3810                 listManager.loadNotesIndex();
3811                 noteIndexUpdated(false);
3812                 return;
3813         }
3814                 attributeTreeSelected = null;
3815                 item.setSelected(false);
3816         Global.createdBeforeFilter.reset();
3817         Global.createdSinceFilter.reset();
3818         Global.changedBeforeFilter.reset();
3819         Global.changedSinceFilter.reset();
3820         Global.containsFilter.reset();
3821         listManager.loadNotesIndex();
3822                 noteIndexUpdated(false); 
3823     }
3824     // This determines what attribute filter we need, depending upon the selection
3825     private DateAttributeFilterTable findDateAttributeFilterTable(QTreeWidgetItem w) {
3826                 if (w.parent() != null && w.childCount() > 0) {
3827                         QTreeWidgetItem parent = w.parent();
3828                         if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Created && 
3829                                 w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Since)
3830                                         return Global.createdSinceFilter;
3831                         if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Created && 
3832                         w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Before)
3833                                         return Global.createdBeforeFilter;
3834                         if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.LastModified && 
3835                         w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Since)
3836                                         return Global.changedSinceFilter;
3837                 if (parent.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.LastModified && 
3838                         w.data(0,ItemDataRole.UserRole)==AttributeTreeWidget.Attributes.Before)
3839                                                 return Global.changedBeforeFilter;
3840                 }
3841                 return null;
3842     }
3843
3844     // Show/Hide attribute search window
3845         @SuppressWarnings("unused")
3846         private void toggleAttributesWindow() {
3847                 logger.log(logger.HIGH, "Entering NeverNote.toggleAttributesWindow");
3848         if (attributeTree.isVisible())
3849                 attributeTree.hide();
3850         else
3851                 attributeTree.show();
3852         menuBar.hideAttributes.setChecked(attributeTree.isVisible());
3853         
3854                 Global.saveWindowVisible("attributeTree", attributeTree.isVisible());
3855         logger.log(logger.HIGH, "Leaving NeverNote.toggleAttributeWindow");
3856     }    
3857         private void clearAttributeFilter() {
3858         Global.createdBeforeFilter.reset();
3859         Global.createdSinceFilter.reset();
3860         Global.changedBeforeFilter.reset();
3861         Global.changedSinceFilter.reset();
3862         Global.containsFilter.reset();
3863         attributeTreeSelected = null;
3864                 attributeTree.blockSignals(true);
3865                 attributeTree.clearSelection();
3866                 attributeTree.blockSignals(false);
3867         }
3868     
3869         
3870     //***************************************************************
3871     //***************************************************************
3872     //** These functions deal with the GUI Note index table
3873     //***************************************************************
3874     //***************************************************************    
3875     // Initialize the note list table
3876         private void initializeNoteTable() {
3877                 logger.log(logger.HIGH, "Entering NeverNote.initializeNoteTable");
3878                 noteTableView.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection);
3879                 noteTableView.selectionModel().selectionChanged.connect(this, "noteTableSelection()");
3880                 logger.log(logger.HIGH, "Leaving NeverNote.initializeNoteTable");
3881         }       
3882     // Show/Hide trash window
3883         @SuppressWarnings("unused")
3884         private void toggleNoteListWindow() {
3885                 logger.log(logger.HIGH, "Entering NeverNote.toggleNoteListWindow");
3886         if (noteTableView.isVisible())
3887                 noteTableView.hide();
3888         else
3889                 noteTableView.show();
3890         menuBar.hideNoteList.setChecked(noteTableView.isVisible());
3891         
3892                 Global.saveWindowVisible("noteList", noteTableView.isVisible());
3893         logger.log(logger.HIGH, "Leaving NeverNote.toggleNoteListWindow");
3894     }   
3895         // Handle the event that a user selects a note from the table
3896     @SuppressWarnings("unused")
3897         private void noteTableSelection() {
3898                 logger.log(logger.HIGH, "Entering NeverNote.noteTableSelection");
3899
3900                 saveNote();
3901                 
3902                 // ICHANGED
3903                 // 右クリックだったときの処理
3904                 if (QApplication.mouseButtons().isSet(MouseButton.RightButton)) {
3905                         // 選択されたノートのguidをselectedNoteGUIDsにセット
3906                         List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
3907                         if(selections.size() > 0){
3908                                 selectedNoteGUIDs.clear();
3909                                 for(int i = 0; i < selections.size(); i++){
3910                                         int row = selections.get(i).row();
3911                                         QModelIndex index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
3912                                         SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
3913                                         selectedNoteGUIDs.add((String) ix.values().toArray()[0]);
3914                                 }
3915                         }
3916                         return;
3917                 }
3918                 
3919                 // If we have more than one selection, then set the merge note action to true.
3920         List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
3921                 if (selections.size() > 1) 
3922                 menuBar.noteMergeAction.setEnabled(true);
3923                 else
3924                         menuBar.noteMergeAction.setEnabled(false);
3925
3926                 // If the ctrl key is pressed, then they are selecting multiple 
3927                 // entries and we don't want to change the currently viewed note.
3928                 // ICHANGED
3929                 // Shiftキーを押しながらの場合の処理も追加
3930                 if ((QApplication.keyboardModifiers().isSet(KeyboardModifier.ControlModifier) ||
3931                                 QApplication.keyboardModifiers().isSet(KeyboardModifier.ShiftModifier)) &&
3932                                 QApplication.mouseButtons().isSet(MouseButton.LeftButton)){
3933                         selectedNoteGUIDs.clear();
3934                 for (int i=0; i<selections.size(); i++) {
3935                         int row = selections.get(i).row();
3936                         QModelIndex index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
3937                         SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
3938                         selectedNoteGUIDs.add((String)ix.values().toArray()[0]);
3939                 }
3940                         return;
3941                 }
3942                 
3943                 // ICHANGED たぶんこれは不要
3944                 // IFIXED ?
3945                 /*if (historyGuids.size() == 0) {
3946                         historyGuids.add(currentNoteGuid);
3947                         historyPosition = 1;
3948                 }*/
3949
3950         noteTableView.showColumn(Global.noteTableGuidPosition);
3951         
3952         if (!Global.isColumnVisible("guid"))
3953                 noteTableView.hideColumn(Global.noteTableGuidPosition);
3954         
3955         if (selections.size() > 0) {
3956                 QModelIndex index;
3957                 menuBar.noteDuplicateAction.setEnabled(true);
3958                 menuBar.noteOnlineHistoryAction.setEnabled(true);
3959                 menuBar.noteMergeAction.setEnabled(true);
3960                 selectedNoteGUIDs.clear();
3961                 if (selections.size() != 1 || Global.showDeleted) {
3962                         menuBar.noteDuplicateAction.setEnabled(false);
3963                 }
3964                 if (selections.size() != 1 || !Global.isConnected) {
3965                         menuBar.noteOnlineHistoryAction.setEnabled(false);
3966                 }
3967                 if (selections.size() == 1) {
3968                         menuBar.noteMergeAction.setEnabled(false);
3969                 }
3970                 for (int i=0; i<selections.size(); i++) {
3971                         int row = selections.get(i).row();
3972                         if (row == 0) 
3973                                 upButton.setEnabled(false);
3974                         else
3975                                 upButton.setEnabled(true);
3976                         if (row < listManager.getNoteTableModel().rowCount()-1)
3977                                 downButton.setEnabled(true);
3978                         else
3979                                 downButton.setEnabled(false);
3980                         index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
3981                         SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
3982                                 
3983                         currentNoteGuid = (String)ix.values().toArray()[0];                     
3984                         selectedNoteGUIDs.add(currentNoteGuid);
3985                 }
3986         }
3987         
3988         nextButton.setEnabled(true);
3989                 prevButton.setEnabled(true);
3990                 
3991                 // ICHANGED
3992                 int currentIndex = tabBrowser.currentIndex();
3993                 ArrayList<String> histGuids = historyGuids.get(currentIndex);
3994                 int histPosition = historyPosition.get(currentIndex);
3995                 boolean fromHist = fromHistory.get(currentIndex);
3996                 
3997                 // ICHANGED
3998                 if (!fromHist) {
3999                         int endPosition = histGuids.size() - 1;
4000
4001                         for (int j = histPosition; j <= endPosition; j++) {
4002                                 histGuids.remove(histGuids.size() - 1);
4003                         }
4004                         histGuids.add(currentNoteGuid);
4005                         historyPosition.put(currentIndex, histGuids.size());
4006                         histPosition = histGuids.size();
4007                 }
4008                 if (histPosition <= 1){
4009                         prevButton.setEnabled(false);
4010                 }
4011                 if (histPosition == histGuids.size())
4012                         nextButton.setEnabled(false);
4013                 fromHistory.put(currentIndex, false);
4014                 fromHist = false;
4015                 
4016         scrollToGuid(currentNoteGuid);
4017         refreshEvernoteNote(true);
4018         
4019                 // ICHANGED
4020                 if (currentNoteGuid != null && !currentNoteGuid.equals("")) {
4021                         if (!Global.showDeleted) { // ゴミ箱じゃなければ
4022                                 addBrowseHistory();
4023                         }
4024                 }
4025
4026                 // ICHANGED
4027                 // 連想ノートリストを更新
4028                 rensoNoteList.refreshRensoNoteList(currentNoteGuid);
4029                 
4030                 waitCursor(false);
4031                 logger.log(logger.HIGH, "Leaving NeverNote.noteTableSelection");
4032     }
4033     
4034
4035         // ICHANGED
4036     // 複数ノートの同時閲覧履歴をデータベースに保存
4037         private void addBrowseHistory() {
4038                 // このノートと他のタブウィンドウノートの関連性を内部データベースのHistoryテーブルに登録
4039                 if (tabWindows.size() >= 2) {
4040                         Iterator<Integer> it = tabWindows.keySet().iterator();
4041                         while (it.hasNext()) {
4042                                 int tabIndex = it.next();
4043                                 String nextGuid = ((TabBrowse) tabBrowser.widget(tabIndex)).getBrowserWindow().getNote().getGuid();
4044                                 // guid1=guid2のデータは登録しない
4045                                 if (!currentNoteGuid.equals(nextGuid)) {
4046                                         conn.getHistoryTable().addHistory("browse", currentNoteGuid, nextGuid);
4047                                 }
4048                         }
4049                 }
4050                 // このノートと他の外部ウィンドウノートの関連性を内部データベースのHistoryテーブルに登録
4051                 if (externalWindows.size() >= 1) {
4052                         Iterator<String> it = externalWindows.keySet().iterator();
4053                         while (it.hasNext()) {
4054                                 String nextGuid = it.next();
4055                                 // guid1=guid2のデータは登録しない
4056                                 if (!currentNoteGuid.equals(nextGuid)) {
4057                                         conn.getHistoryTable().addHistory("browse", currentNoteGuid, nextGuid);
4058                                 }
4059                         }
4060                 }
4061         }
4062         
4063         // Trigger a refresh when the note db has been updated
4064         private void noteIndexUpdated(boolean reload) {
4065                 logger.log(logger.HIGH, "Entering NeverNote.noteIndexUpdated");
4066                 saveNote();
4067         refreshEvernoteNoteList();
4068         logger.log(logger.HIGH, "Calling note table reload in NeverNote.noteIndexUpdated() - "+reload);
4069         noteTableView.load(reload);
4070         if (currentNoteGuid == null || currentNoteGuid.equals("")) {
4071                 int pos;
4072                 if (noteTableView.proxyModel.sortOrder() == SortOrder.AscendingOrder)
4073                         pos = noteTableView.proxyModel.rowCount();
4074                 else 
4075                         pos = 1;
4076                 if (noteTableView.proxyModel.rowCount() == 0)
4077                         pos = 0;
4078                 if (pos>0)      {
4079                         QModelIndex i = noteTableView.proxyModel.index(pos-1, Global.noteTableGuidPosition);
4080                         if (i!=null) {
4081                                 currentNoteGuid = (String)i.data();
4082                         }
4083                 }
4084         }               
4085                 if (!noteTableView.isColumnHidden(Global.noteTableGuidPosition))
4086                         showColumns();
4087                 scrollToGuid(currentNoteGuid);
4088                 logger.log(logger.HIGH, "Leaving NeverNote.noteIndexUpdated");
4089     }
4090         // Called when the list of notes is updated
4091     private void refreshEvernoteNoteList() {
4092         logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNoteList");
4093         browserWindow.setDisabled(false);
4094                 if (selectedNoteGUIDs == null)
4095                         selectedNoteGUIDs = new ArrayList<String>();
4096                 selectedNoteGUIDs.clear();  // clear out old entries
4097                 
4098                 String saveCurrentNoteGuid = new String();
4099                 String tempNoteGuid = new String();
4100                 
4101                 // ICHANGED
4102                 int currentIndex = tabBrowser.currentIndex();
4103                 ArrayList<String> histGuids = historyGuids.get(currentIndex);
4104                 histGuids.clear();
4105                 historyPosition.put(currentIndex, 0);
4106                 
4107                 prevButton.setEnabled(false);
4108                 nextButton.setEnabled(false);
4109                 
4110                 if (currentNoteGuid == null) 
4111                         currentNoteGuid = new String();
4112                 
4113                 //determine current note guid
4114                 for (Note note : listManager.getNoteIndex()) {
4115                         tempNoteGuid = note.getGuid();
4116                         if (currentNoteGuid.equals(tempNoteGuid)) {
4117                                 saveCurrentNoteGuid = tempNoteGuid;
4118                         }
4119                 }
4120                 
4121                 if (listManager.getNoteIndex().size() == 0) {
4122                         currentNoteGuid = "";
4123                         currentNote = null;
4124                         browserWindow.clear();
4125                         browserWindow.setDisabled(true);
4126                         waitCursor(false);
4127                 } 
4128                 
4129                 if (Global.showDeleted && listManager.getNoteIndex().size() > 0 && saveCurrentNoteGuid.equals("")) {
4130                         currentNoteGuid = listManager.getNoteIndex().get(0).getGuid();
4131                         saveCurrentNoteGuid = currentNoteGuid;
4132                         refreshEvernoteNote(true);
4133                 }
4134                 
4135                 if (!saveCurrentNoteGuid.equals("")) {
4136                         refreshEvernoteNote(false);
4137                 } else {
4138                                 currentNoteGuid = "";
4139                 }
4140                 reloadTagTree(false);
4141
4142                 logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNoteList");
4143         } 
4144     
4145         // ICHANGED
4146         // Called when the previous arrow button is clicked
4147         @SuppressWarnings("unused")
4148         private void previousViewedAction() {
4149                 int currentIndex = tabBrowser.currentIndex();
4150                 ArrayList<String> histGuids = historyGuids.get(currentIndex);
4151                 int histPosition = historyPosition.get(currentIndex);
4152                 boolean fromHist = fromHistory.get(currentIndex);
4153                 if (!prevButton.isEnabled())
4154                         return;
4155                 if (histPosition == 0)
4156                         return;
4157                 histPosition--;
4158                 historyPosition.put(currentIndex, histPosition);
4159                 if (histPosition <= 0)
4160                         return;
4161                 String historyGuid = histGuids.get(histPosition - 1);
4162                 fromHistory.put(currentIndex, true);
4163                 fromHist = true;
4164                 for (int i = 0; i < noteTableView.model().rowCount(); i++) {
4165                         QModelIndex modelIndex = noteTableView.model().index(i,
4166                                         Global.noteTableGuidPosition);
4167                         if (modelIndex != null) {
4168                                 SortedMap<Integer, Object> ix = noteTableView.model().itemData(
4169                                                 modelIndex);
4170                                 String tableGuid = (String) ix.values().toArray()[0];
4171                                 if (tableGuid.equals(historyGuid)) {
4172                                         noteTableView.selectRow(i);
4173                                         return;
4174                                 }
4175                         }
4176                 }
4177         }
4178         
4179     @SuppressWarnings("unused")
4180         private void nextViewedAction() {
4181         if (!nextButton.isEnabled())
4182                 return;
4183                 // ICHANGED
4184                 int currentIndex = tabBrowser.currentIndex();
4185                 ArrayList<String> histGuids = historyGuids.get(currentIndex);
4186                 int histPosition = historyPosition.get(currentIndex);
4187                 boolean fromHist = fromHistory.get(currentIndex);
4188                 String historyGuid = histGuids.get(histPosition);
4189                 histPosition++;
4190                 historyPosition.put(currentIndex, histPosition);
4191                 fromHistory.put(currentIndex, true);
4192                 fromHist = true;
4193                 for (int i = 0; i < noteTableView.model().rowCount(); i++) {
4194                         QModelIndex modelIndex = noteTableView.model().index(i,
4195                                         Global.noteTableGuidPosition);
4196                         if (modelIndex != null) {
4197                                 SortedMap<Integer, Object> ix = noteTableView.model().itemData(
4198                                                 modelIndex);
4199                                 String tableGuid = (String) ix.values().toArray()[0];
4200                                 if (tableGuid.equals(historyGuid)) {
4201                                         noteTableView.selectRow(i);
4202                                         return;
4203                                 }
4204                         }
4205                 }
4206     }
4207     // Called when the up arrow is clicked 
4208     @SuppressWarnings("unused")
4209         private void upAction() {
4210         List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
4211         int row = selections.get(0).row();
4212         if (row > 0) {
4213                 noteTableView.selectRow(row-1);
4214         }
4215     }
4216     // Called when the down arrow is clicked 
4217     @SuppressWarnings("unused")
4218         private void downAction() {
4219         List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
4220         int row = selections.get(0).row();
4221         int max = listManager.getNoteTableModel().rowCount();
4222         if (row < max-1) {
4223                 noteTableView.selectRow(row+1);
4224         }
4225     }
4226     // Update a tag string for a specific note in the list
4227     @SuppressWarnings("unused")
4228         private void updateListTags(String guid, List<String> tags) {
4229         logger.log(logger.HIGH, "Entering NeverNote.updateListTags");
4230         StringBuffer tagBuffer = new StringBuffer();
4231         for (int i=0; i<tags.size(); i++) {
4232                 tagBuffer.append(tags.get(i));
4233                 if (i<tags.size()-1)
4234                         tagBuffer.append(", ");
4235         }
4236         
4237         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4238                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4239                 if (modelIndex != null) {
4240                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4241                         String tableGuid =  (String)ix.values().toArray()[0];
4242                         if (tableGuid.equals(guid)) {
4243                                 listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition,tagBuffer.toString());
4244                                 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
4245                                 noteTableView.proxyModel.invalidate();
4246                                 return;
4247                         }
4248                 }
4249         }
4250         logger.log(logger.HIGH, "Leaving NeverNote.updateListTags");
4251     }
4252     // Update a title for a specific note in the list
4253     @SuppressWarnings("unused")
4254         private void updateListAuthor(String guid, String author) {
4255         logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
4256
4257         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4258                 //QModelIndex modelIndex =  noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
4259                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4260                 if (modelIndex != null) {
4261                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4262                         String tableGuid =  (String)ix.values().toArray()[0];
4263                         if (tableGuid.equals(guid)) {
4264                                 listManager.getNoteTableModel().setData(i, Global.noteTableAuthorPosition,author);
4265                                 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
4266                                 noteTableView.proxyModel.invalidate();
4267                                 return;
4268                         }       
4269                 }
4270         }
4271         
4272         logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
4273     }
4274         private void updateListNoteNotebook(String guid, String notebook) {
4275         logger.log(logger.HIGH, "Entering NeverNote.updateListNoteNotebook");
4276         listManager.getNoteTableModel().updateNoteSyncStatus(guid, false);
4277         logger.log(logger.HIGH, "Leaving NeverNote.updateListNoteNotebook");
4278     }
4279     // Update a title for a specific note in the list
4280     @SuppressWarnings("unused")
4281         private void updateListSourceUrl(String guid, String url) {
4282         logger.log(logger.HIGH, "Entering NeverNote.updateListAuthor");
4283
4284         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4285                 //QModelIndex modelIndex =  noteTableView.proxyModel.index(i, Global.noteTableGuidPosition);
4286                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4287                 if (modelIndex != null) {
4288 //                      SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(modelIndex);
4289                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4290                         String tableGuid =  (String)ix.values().toArray()[0];
4291                         if (tableGuid.equals(guid)) {
4292                                 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
4293                                 listManager.getNoteTableModel().setData(i, Global.noteTableSourceUrlPosition,url);
4294                                 noteTableView.proxyModel.invalidate();
4295                                 return;
4296                         }       
4297                 }
4298         }
4299         logger.log(logger.HIGH, "Leaving NeverNote.updateListAuthor");
4300     }
4301         @SuppressWarnings("unused")
4302         private void updateListGuid(String oldGuid, String newGuid) {
4303         logger.log(logger.HIGH, "Entering NeverNote.updateListTitle");
4304
4305         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4306                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4307                 if (modelIndex != null) {
4308                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4309                         String tableGuid =  (String)ix.values().toArray()[0];
4310                         if (tableGuid.equals(oldGuid)) {
4311                                 listManager.getNoteTableModel().setData(i, Global.noteTableGuidPosition,newGuid);
4312                                 //listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
4313                                 return;
4314                         }       
4315                 }
4316         }
4317         logger.log(logger.HIGH, "Leaving NeverNote.updateListTitle");
4318     }
4319         private void updateListTagName(String guid) {
4320         logger.log(logger.HIGH, "Entering NeverNote.updateTagName");
4321                 
4322                 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
4323                         if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) {
4324                                 String newName = listManager.getTagNamesForNote(listManager.getNoteIndex().get(j));
4325
4326                                 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4327                                         QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4328                                         if (modelIndex != null) {
4329                                                 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4330                                                 String noteGuid = (String)ix.values().toArray()[0];
4331                                                 if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) {
4332                                                         listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition, newName);
4333                                                         i=listManager.getNoteTableModel().rowCount();
4334                                                 }
4335                                         }
4336                                 }
4337                         }
4338                 }       
4339         logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebook");
4340     }
4341         private void removeListTagName(String guid) {
4342         logger.log(logger.HIGH, "Entering NeverNote.updateTagName");
4343                 
4344                 for (int j=0; j<listManager.getNoteIndex().size(); j++) {
4345                         if (listManager.getNoteIndex().get(j).getTagGuids().contains(guid)) {
4346                                 for (int i=listManager.getNoteIndex().get(j).getTagGuids().size()-1; i>=0; i--) {
4347                                         if (listManager.getNoteIndex().get(j).getTagGuids().get(i).equals(guid))
4348                                                 listManager.getNoteIndex().get(j).getTagGuids().remove(i);
4349                                 }
4350                                 
4351                                 String newName = listManager.getTagNamesForNote(listManager.getNoteIndex().get(j));
4352                                 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4353                                         QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4354                                         if (modelIndex != null) {
4355                                                 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4356                                                 String noteGuid = (String)ix.values().toArray()[0];
4357                                                 if (noteGuid.equalsIgnoreCase(listManager.getNoteIndex().get(j).getGuid())) {
4358                                                         listManager.getNoteTableModel().setData(i, Global.noteTableTagPosition, newName);
4359                                                         i=listManager.getNoteTableModel().rowCount();
4360                                                 }
4361                                         }
4362                                 }
4363                         }
4364                 }       
4365         logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebook");
4366     }
4367     private void updateListNotebookName(String oldName, String newName) {
4368         logger.log(logger.HIGH, "Entering NeverNote.updateListNotebookName");
4369
4370         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4371                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableNotebookPosition); 
4372                 if (modelIndex != null) {
4373                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4374                         String tableName =  (String)ix.values().toArray()[0];
4375                         if (tableName.equalsIgnoreCase(oldName)) {
4376                                 listManager.getNoteTableModel().setData(i, Global.noteTableNotebookPosition, newName);
4377                         }
4378                 }
4379         }
4380         logger.log(logger.HIGH, "Leaving NeverNote.updateListNotebookName");
4381     }
4382     @SuppressWarnings("unused")
4383         private void updateListDateCreated(String guid, QDateTime date) {
4384         logger.log(logger.HIGH, "Entering NeverNote.updateListDateCreated");
4385
4386         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4387                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4388                 if (modelIndex != null) {
4389                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4390                         String tableGuid =  (String)ix.values().toArray()[0];
4391                         if (tableGuid.equals(guid)) {
4392                                 listManager.getNoteTableModel().setData(i, Global.noteTableCreationPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
4393                                 noteTableView.proxyModel.invalidate();
4394                                 return;
4395                         }
4396                 }
4397         }
4398         logger.log(logger.HIGH, "Leaving NeverNote.updateListDateCreated");
4399     }
4400     @SuppressWarnings("unused")
4401         private void updateListDateSubject(String guid, QDateTime date) {
4402         logger.log(logger.HIGH, "Entering NeverNote.updateListDateSubject");
4403
4404         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4405                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4406                 if (modelIndex != null) {
4407                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4408                         String tableGuid =  (String)ix.values().toArray()[0];
4409                         if (tableGuid.equals(guid)) {
4410                                 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
4411                                 listManager.getNoteTableModel().setData(i, Global.noteTableSubjectDatePosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
4412                                 noteTableView.proxyModel.invalidate();
4413                                 return;
4414                         }
4415                 }
4416         }
4417         logger.log(logger.HIGH, "Leaving NeverNote.updateListDateCreated");
4418     }
4419         private void updateListDateChanged(String guid, QDateTime date) {
4420         logger.log(logger.HIGH, "Entering NeverNote.updateListDateChanged");
4421
4422         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4423                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4424                 if (modelIndex != null) {
4425                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4426                         String tableGuid =  (String)ix.values().toArray()[0];
4427                         if (tableGuid.equals(guid)) {
4428                                 listManager.getNoteTableModel().setData(i, Global.noteTableSynchronizedPosition, "false");
4429                                 listManager.getNoteTableModel().setData(i, Global.noteTableChangedPosition, date.toString(Global.getDateFormat()+" " +Global.getTimeFormat()));
4430                                 return;
4431                         }
4432                 }
4433         }
4434         logger.log(logger.HIGH, "Leaving NeverNote.updateListDateChanged");
4435     }
4436     private void updateListDateChanged() {
4437         logger.log(logger.HIGH, "Entering NeverNote.updateListDateChanged");
4438         QDateTime date = new QDateTime(QDateTime.currentDateTime());
4439         updateListDateChanged(currentNoteGuid, date);
4440         logger.log(logger.HIGH, "Leaving NeverNote.updateListDateChanged");
4441     }  
4442     // Redo scroll
4443         private void scrollToCurrentGuid() {
4444         //scrollToGuid(currentNoteGuid);
4445         List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
4446         if (selections.size() == 0)
4447                 return;
4448         QModelIndex index = selections.get(0);
4449         int row = selections.get(0).row();
4450         String guid = (String)index.model().index(row, Global.noteTableGuidPosition).data();
4451         scrollToGuid(guid);
4452     }
4453         // Scroll to the current GUID in tthe list.
4454     // Scroll to a particular index item
4455     private void scrollToGuid(String guid) {
4456         if (currentNote == null || guid == null) 
4457                 return;
4458         if (currentNote.isActive() && Global.showDeleted) {
4459                 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
4460                         if (!listManager.getNoteIndex().get(i).isActive()) {
4461                                 currentNote = listManager.getNoteIndex().get(i);
4462                                 currentNoteGuid =  currentNote.getGuid();
4463                                 i = listManager.getNoteIndex().size();
4464                         }
4465                 }
4466         }
4467         if (!currentNote.isActive() && !Global.showDeleted) {
4468                 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
4469                         if (listManager.getNoteIndex().get(i).isActive()) {
4470                                 currentNote = listManager.getNoteIndex().get(i);
4471                                 currentNoteGuid =  currentNote.getGuid();
4472                                 i = listManager.getNoteIndex().size();
4473                         }
4474                 }
4475         }
4476         QModelIndex index; 
4477         for (int i=0; i<noteTableView.model().rowCount(); i++) {
4478                 index = noteTableView.model().index(i, Global.noteTableGuidPosition);
4479                 if (currentNoteGuid.equals(index.data())) {
4480 //                      noteTableView.selectionModel().blockSignals(true);
4481                         noteTableView.selectRow(i);
4482 //                              noteTableView.selectionModel().blockSignals(false);
4483                         noteTableView.scrollTo(index, ScrollHint.EnsureVisible);  // This should work, but it doesn't
4484                                 i=listManager.getNoteTableModel().rowCount();
4485                 }
4486         }
4487         noteTableView.repaint();
4488     }
4489     // Show/Hide columns
4490     private void showColumns() {
4491                 noteTableView.setColumnHidden(Global.noteTableCreationPosition, !Global.isColumnVisible("dateCreated"));
4492                 noteTableView.setColumnHidden(Global.noteTableChangedPosition, !Global.isColumnVisible("dateChanged"));
4493                 noteTableView.setColumnHidden(Global.noteTableSubjectDatePosition, !Global.isColumnVisible("dateSubject"));
4494                 noteTableView.setColumnHidden(Global.noteTableAuthorPosition, !Global.isColumnVisible("author"));
4495                 noteTableView.setColumnHidden(Global.noteTableSourceUrlPosition, !Global.isColumnVisible("sourceUrl"));
4496                 noteTableView.setColumnHidden(Global.noteTableTagPosition, !Global.isColumnVisible("tags"));
4497                 noteTableView.setColumnHidden(Global.noteTableNotebookPosition, !Global.isColumnVisible("notebook"));
4498                 noteTableView.setColumnHidden(Global.noteTableSynchronizedPosition, !Global.isColumnVisible("synchronized"));
4499                 noteTableView.setColumnHidden(Global.noteTableGuidPosition, !Global.isColumnVisible("guid"));
4500                 noteTableView.setColumnHidden(Global.noteTableThumbnailPosition, !Global.isColumnVisible("thumbnail"));
4501                 noteTableView.setColumnHidden(Global.noteTableTitlePosition, !Global.isColumnVisible("title"));         
4502                 noteTableView.setColumnHidden(Global.noteTablePinnedPosition, !Global.isColumnVisible("pinned")); 
4503     }
4504     // Title color has changed
4505     @SuppressWarnings("unused")
4506         private void titleColorChanged(Integer color) {
4507         logger.log(logger.HIGH, "Entering NeverNote.titleColorChanged");
4508
4509         setNoteDirty();
4510         QColor backgroundColor = new QColor();
4511                 QColor foregroundColor = new QColor(QColor.black);
4512                 backgroundColor.setRgb(color);
4513                 
4514                 if (backgroundColor.rgb() == QColor.black.rgb() || backgroundColor.rgb() == QColor.blue.rgb())
4515                         foregroundColor.setRgb(QColor.white.rgb());
4516         
4517                 if (selectedNoteGUIDs.size() == 0)
4518                         selectedNoteGUIDs.add(currentNoteGuid);
4519                 
4520         for (int j=0; j<selectedNoteGUIDs.size(); j++) {
4521                 for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
4522                         QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
4523                         if (modelIndex != null) {
4524                                 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
4525                                 String tableGuid =  (String)ix.values().toArray()[0];
4526                                 if (tableGuid.equals(selectedNoteGUIDs.get(j))) {
4527                                         for (int k=0; k<Global.noteTableColumnCount; k++) {
4528                                                 listManager.getNoteTableModel().setData(i, k, backgroundColor, Qt.ItemDataRole.BackgroundRole);
4529                                                 listManager.getNoteTableModel().setData(i, k, foregroundColor, Qt.ItemDataRole.ForegroundRole);
4530                                                 listManager.updateNoteTitleColor(selectedNoteGUIDs.get(j), backgroundColor.rgb());
4531                                         }
4532                                         i=listManager.getNoteTableModel().rowCount();
4533                                 }
4534                         }
4535                 }
4536         }
4537         logger.log(logger.HIGH, "Leaving NeverNote.titleColorChanged");
4538     }
4539     // A note has been pinned or unpinned
4540         @SuppressWarnings("unused")
4541         private void notePinned() {
4542                 logger.log(logger.EXTREME, "Entering NeverNote.notePinned()");
4543                 setNoteDirty();
4544
4545         for (int j=0; j<selectedNoteGUIDs.size(); j++) {
4546                 NoteMetadata meta = listManager.getNoteMetadata().get(selectedNoteGUIDs.get(j));
4547                 boolean pinned = !meta.isPinned();
4548                 meta.setPinned(pinned);   // Toggle the pinned/unpinned 
4549                 
4550                 // Update the list & table
4551                 listManager.updateNoteMetadata(meta);   
4552                 noteTableView.proxyModel.addGuid(selectedNoteGUIDs.get(j), meta);
4553         }
4554                 logger.log(logger.EXTREME, "Leaving NeverNote.notePinned()");
4555     }
4556     // Wide list was chosen
4557     public void narrowListView() {
4558         saveNoteColumnPositions();
4559         saveNoteIndexWidth();
4560         saveWindowState();
4561                 int sortCol = noteTableView.proxyModel.sortColumn();
4562                 int sortOrder = noteTableView.proxyModel.sortOrder().value();
4563                 Global.setSortColumn(sortCol);
4564                 Global.setSortOrder(sortOrder);
4565
4566                 Global.setListView(Global.View_List_Narrow);
4567         
4568         menuBar.wideListView.blockSignals(true);
4569         menuBar.narrowListView.blockSignals(true);
4570         
4571         menuBar.wideListView.setChecked(false);
4572         menuBar.narrowListView.setChecked(true);
4573         
4574         menuBar.wideListView.blockSignals(false);
4575         menuBar.narrowListView.blockSignals(false);
4576         
4577         mainLeftRightSplitter.addWidget(noteTableView);
4578         // ICHANGED browserWindow → tabBrowser
4579         mainLeftRightSplitter.addWidget(tabBrowser);
4580         
4581         restoreWindowState(false);
4582         noteTableView.repositionColumns();
4583         noteTableView.resizeColumnWidths();
4584         noteTableView.resizeRowHeights();
4585         
4586         sortCol = Global.getSortColumn();
4587                 sortOrder = Global.getSortOrder();
4588                 noteTableView.proxyModel.blocked = true;
4589                 noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder));
4590                 noteTableView.proxyModel.blocked = false;
4591
4592                 
4593         showColumns();
4594         noteTableView.load(false);
4595         refreshEvernoteNote(true);
4596         scrollToCurrentGuid();
4597     }
4598     public void wideListView() {
4599                 int sortCol = noteTableView.proxyModel.sortColumn();
4600                 int sortOrder = noteTableView.proxyModel.sortOrder().value();
4601                 Global.setSortColumn(sortCol);
4602                 Global.setSortOrder(sortOrder);
4603
4604                 saveWindowState();
4605         saveNoteColumnPositions();
4606         saveNoteIndexWidth();
4607         Global.setListView(Global.View_List_Wide);
4608
4609         menuBar.wideListView.blockSignals(true);
4610         menuBar.narrowListView.blockSignals(true);
4611         
4612         menuBar.wideListView.setChecked(true);
4613         menuBar.narrowListView.setChecked(false);
4614
4615         menuBar.wideListView.blockSignals(false);
4616         menuBar.narrowListView.blockSignals(false);
4617         browserIndexSplitter.setVisible(true);
4618         browserIndexSplitter.addWidget(noteTableView);
4619                 // ICHANGED browserWindow → tabBrowser
4620                 browserIndexSplitter.addWidget(tabBrowser);
4621                 
4622         restoreWindowState(false);
4623         noteTableView.repositionColumns();
4624         noteTableView.resizeColumnWidths();
4625         noteTableView.resizeRowHeights();
4626         
4627         sortCol = Global.getSortColumn();
4628                 sortOrder = Global.getSortOrder();
4629                 noteTableView.proxyModel.blocked = true;
4630                 noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder));
4631                 noteTableView.proxyModel.blocked = false;
4632
4633         showColumns();
4634         noteTableView.load(false);
4635         scrollToCurrentGuid();
4636     }
4637     // Sort order for the notebook has changed   
4638     public void tableSortOrderChanged(Integer column, Integer order) {
4639         
4640         // Find what notebook (if any) is selected.  We ignore stacks & the "All Notebooks".
4641         List<QTreeWidgetItem> selectedNotebook = notebookTree.selectedItems();
4642         if (selectedNotebook.size() > 0 && !selectedNotebook.get(0).text(0).equalsIgnoreCase("All Notebooks") && !selectedNotebook.get(0).text(2).equalsIgnoreCase("STACK")) {
4643                 QTreeWidgetItem currentSelectedNotebook = selectedNotebook.get(0);
4644                 String notebook;
4645                 notebook = currentSelectedNotebook.text(2);
4646                 conn.getNotebookTable().setSortOrder(notebook, column, order);
4647         }       
4648     }
4649     
4650     //***************************************************************
4651     @SuppressWarnings("unused")
4652         private void evernoteLinkClick(String syncGuid, String locGuid) {
4653         String guid = null;
4654         if (conn.getNoteTable().guidExists(syncGuid)) {
4655                 guid = syncGuid;
4656         } else {
4657                 // If we didn't find it via the synchronized guid, look under the local guid
4658                 // Iwe don't find it there, look to see if the GUID is posted under the local GUID, but was 
4659                 // later synchronized (that causes the guid to change so we need to find the new one).
4660                 if (conn.getNoteTable().guidExists(locGuid)) 
4661                         guid = locGuid;
4662                 else
4663                         guid = conn.getNoteTable().findAlternateGuid(locGuid);
4664         }
4665                 if (guid != null) {
4666                         openExternalEditor(guid);
4667                         return;
4668                 }
4669         
4670         //If we've gotten this far, we can't find the note
4671         QMessageBox.information(this, tr("Note Not Found"), tr("Sorry, but I can't"+
4672                         " seem to find that note."));
4673     }
4674     //***************************************************************
4675     //***************************************************************
4676     //** External editor window functions                    
4677     //***************************************************************
4678     //***************************************************************
4679         private void listDoubleClick() {
4680                 saveNote();
4681         openExternalEditor(currentNoteGuid);
4682     }
4683     private void openExternalEditor(String guid) {
4684         
4685         if (externalWindows.containsKey(guid)) {
4686                 externalWindows.get(guid).raise();
4687                 return;
4688         }
4689         
4690         Note note = conn.getNoteTable().getNote(guid, true, true, false, true, true);
4691         // We have a new external editor to create
4692         QIcon appIcon = new QIcon(iconPath+"nevernote.png");
4693         // ICHANGED
4694         ExternalBrowse newBrowser = new ExternalBrowse(conn, cbObserver);
4695         
4696         newBrowser.setWindowIcon(appIcon);
4697         externalWindows.put(guid, newBrowser);
4698         showEditorButtons(newBrowser.getBrowserWindow());
4699         loadNoteBrowserInformation(newBrowser.getBrowserWindow(), guid, note);
4700         setupBrowserWindowListeners(newBrowser.getBrowserWindow(), false);
4701         newBrowser.windowClosing.connect(this, "externalWindowClosing(String)");
4702         //newBrowser.getBrowserWindow().noteSignal.titleChanged.connect(this, "externalWindowTitleEdited(String, String)");
4703         newBrowser.getBrowserWindow().noteSignal.tagsChanged.connect(this, "externalWindowTagsEdited(String, List)");
4704         newBrowser.contentsChanged.connect(this, "saveNoteExternalBrowser(String, String, Boolean, BrowserWindow)");
4705         newBrowser.getBrowserWindow().blockApplication.connect(this, "blockApplication(BrowserWindow)");
4706         newBrowser.getBrowserWindow().unblockApplication.connect(this, "unblockApplication()");
4707
4708         browserWindow.noteSignal.tagsChanged.connect(newBrowser, "updateTags(String, List)");
4709         browserWindow.noteSignal.titleChanged.connect(newBrowser, "updateTitle(String, String)");
4710         browserWindow.noteSignal.notebookChanged.connect(newBrowser, "updateNotebook(String, String)");
4711         
4712         newBrowser.show();
4713     }
4714     @SuppressWarnings({ "rawtypes", "unused" })
4715         private void externalWindowTagsEdited(String guid, List values) {
4716         StringBuffer line = new StringBuffer(100);
4717         for (int i=0; i<values.size(); i++) {
4718                 if (i>0) 
4719                         line.append(Global.tagDelimeter+" ");
4720                 line.append(values.get(i));
4721         }
4722         if (guid.equals(currentNoteGuid)) {
4723                 browserWindow.setTag(line.toString());
4724         }
4725     }
4726     @SuppressWarnings("unused")
4727         private void externalWindowClosing(String guid) {
4728                 externalWindows.remove(guid);
4729     }
4730     
4731         // ***************************************************************
4732         // ***************************************************************
4733         // ** タブウィンドウの機能
4734         // ***************************************************************
4735         // ***************************************************************
4736         @SuppressWarnings("unused")
4737         private void openNewTab() {
4738                 saveNote();
4739
4740                 // selectedNoteGUIDsをディープコピー
4741                 List<String> copySelected = new ArrayList<String>(selectedNoteGUIDs);
4742                 
4743                 for (int i=0; i < copySelected.size() ; i++) {
4744                         openTabEditor(copySelected.get(i));
4745                 }
4746         }
4747         
4748         // ICHANGED 連想ノートリストから新しいタブで開く
4749         @SuppressWarnings("unused")
4750         private void openNewTabFromRNL(){
4751                 if(rensoNotePressedItemGuid != null){
4752                         String prevCurrentNoteGuid = new String(currentNoteGuid);
4753                         
4754                         saveNote();
4755                         openTabEditor(rensoNotePressedItemGuid);
4756                         
4757                         // 連想ノートリストアイテムクリック操作を記録
4758                         conn.getHistoryTable().addHistory("rensoItemClick", prevCurrentNoteGuid, rensoNotePressedItemGuid);
4759                 }
4760         }
4761
4762         // ICHANGED
4763         private void openTabEditor(String guid) {
4764                 
4765                 Note note = conn.getNoteTable().getNote(guid, true, true, false, true, true);
4766                 // 新しいタブエディタを作成
4767                 TabBrowse newBrowser = new TabBrowse(conn, tabBrowser, cbObserver);
4768                 showEditorButtons(newBrowser.getBrowserWindow());
4769                 
4770                 String noteTitle = note.getTitle();
4771                 int index = tabBrowser.addNewTab(newBrowser, noteTitle);
4772                 tabWindows.put(index, newBrowser);
4773                 noteDirty.put(index, false);
4774                 
4775                 // noteTableViewの選択を変更するとselectionChangedが発生してしまうので一度切断
4776                 noteTableView.selectionModel().selectionChanged.disconnect(this, "noteTableSelection()");
4777                 loadNoteBrowserInformation(newBrowser.getBrowserWindow(), guid, note);
4778                 // 再接続
4779                 noteTableView.selectionModel().selectionChanged.connect(this, "noteTableSelection()");
4780                 
4781                 setupBrowserWindowListeners(newBrowser.getBrowserWindow(), false);
4782                 
4783                 // ExtendedInformationを必要があれば表示する
4784                 toggleNoteInformation();
4785                 // Sourceを必要があれば表示する
4786                 viewSource();
4787                 // EditorButtonsBarを必要があれば表示する
4788                 toggleEditorButtonBar();
4789
4790                 // 履歴記録のハッシュマップを初期化
4791                 ArrayList<String> histGuids = new ArrayList<String>();
4792                 historyGuids.put(index, histGuids);
4793                 historyPosition.put(index, 0);
4794                 fromHistory.put(index, false);
4795
4796                 // 履歴に今開いたノートを追加
4797                 histGuids.add(guid);
4798                 historyPosition.put(index, histGuids.size());
4799
4800                 tabBrowser.setCurrentIndex(index);
4801
4802                 if (guid != null && !guid.equals("")) {
4803                         if (!Global.showDeleted) { // ゴミ箱じゃなければ
4804                                 addBrowseHistory();
4805                         }
4806                 }
4807         }
4808
4809         // ICHANGED タブが閉じられた
4810         private void tabWindowClosing(int index) {
4811                 // タブが1つしかなかったら閉じない
4812                 if (tabBrowser.count() <= 1) {
4813                         return;
4814                 }
4815
4816                 TabBrowse t = (TabBrowse) tabBrowser.widget(index);
4817                 String guid = t.getBrowserWindow().getNote().getGuid();
4818                 String content = t.getBrowserWindow().getContent();
4819                 BrowserWindow browser = t.getBrowserWindow();
4820                 // ノートが変更されていたら保存
4821                 if (t.getNoteDirty()) {
4822                         saveNoteTabBrowser(guid, content, true, browser);
4823                 }
4824
4825                 // シグナル切断
4826                 browser.noteSignal.tagsChanged.disconnect();
4827                 browser.noteSignal.titleChanged.disconnect();
4828                 browser.noteSignal.noteChanged.disconnect();
4829                 browser.noteSignal.notebookChanged.disconnect();
4830                 browser.noteSignal.createdDateChanged.disconnect();
4831                 browser.noteSignal.alteredDateChanged.disconnect();
4832
4833                 // ノートを削除
4834                 tabWindows.remove(index);
4835                 tabBrowser.removeTab(index);
4836                 noteDirty.remove(index);
4837                 inkNote.remove(index);
4838                 readOnly.remove(index);
4839
4840                 // 履歴記録のハッシュマップを削除
4841                 historyGuids.remove(index);
4842                 historyPosition.remove(index);
4843                 fromHistory.remove(index);
4844                 
4845                 // タブのインデックスを更新(削除によって空いた部分を詰める)
4846                 for(int i = index ; tabWindows.containsKey(i + 1) ; i++){
4847                         // tabWindows
4848                         TabBrowse tab = tabWindows.get(i + 1);
4849                         tabWindows.put(i, tab);
4850                         tabWindows.remove(i + 1);
4851                         // noteDirty
4852                         boolean isNoteDirty = noteDirty.get(i + 1);
4853                         noteDirty.put(i, isNoteDirty);
4854                         noteDirty.remove(i + 1);
4855                         // inkNote
4856                         boolean isInkNote = inkNote.get(i + 1);
4857                         inkNote.put(i, isInkNote);
4858                         inkNote.remove(i + 1);
4859                         // readOnly
4860                         boolean isReadOnly = readOnly.get(i + 1);
4861                         readOnly.put(i, isReadOnly);
4862                         readOnly.remove(i + 1);
4863                         // historyGuids
4864                         ArrayList<String> histGuids = historyGuids.get(i + 1);
4865                         historyGuids.put(i, histGuids);
4866                         historyGuids.remove(i + 1);
4867                         // historyPosition
4868                         int histPosition = historyPosition.get(i + 1);
4869                         historyPosition.put(i, histPosition);
4870                         historyPosition.remove(i + 1);
4871                         // fromHistory
4872                         boolean fromHist = fromHistory.get(i + 1);
4873                         fromHistory.put(i,  fromHist);
4874                         fromHistory.remove(i + 1);
4875                 }
4876                 
4877                 // タブの閉じるボタンを押すと、tabWindowClosingより先にtabWindowChangedが呼ばれてしまうので、手動で呼びなおす
4878                 tabWindowChanged(tabBrowser.currentIndex());
4879         }
4880         
4881         @SuppressWarnings("unused")
4882         private void noteAddNewTab() {
4883                 saveNote();
4884                 
4885                 // ノート追加前に開いていたノートとの関連性を記録するためにguidをとっておく
4886                 TabBrowse prevTab = (TabBrowse)tabBrowser.currentWidget();
4887                 String prevTabGuid = prevTab.getBrowserWindow().getNote().getGuid();
4888                 
4889                 openEmptyTabEditor();
4890                 addNote();
4891                 
4892                 // 追加されたノートのguidを取得し、ノート追加操作履歴としてデータベースに登録
4893                 TabBrowse addedTab = (TabBrowse)tabBrowser.currentWidget();
4894                 String addedTabGuid = addedTab.getBrowserWindow().getNote().getGuid();
4895                 if (prevTabGuid != null && !prevTabGuid.equals("")) {
4896                         if (addedTabGuid != null && !addedTabGuid.equals("")) {
4897                                 if (!prevTabGuid.equals(addedTabGuid)) {
4898                                         conn.getHistoryTable().addHistory("addNewNote", prevTabGuid, addedTabGuid);
4899                                 }
4900                         }
4901                 }
4902         }
4903         
4904         // ICHANGED
4905         private void openEmptyTabEditor() {
4906                 // 新しいタブエディタを作成
4907                 TabBrowse newBrowser = new TabBrowse(conn, tabBrowser, cbObserver);
4908                 showEditorButtons(newBrowser.getBrowserWindow());
4909                 
4910                 setupBrowserWindowListeners(newBrowser.getBrowserWindow(), false);
4911                 
4912                 int index = tabBrowser.addNewTab(newBrowser, "");
4913                 tabWindows.put(index, newBrowser);
4914                 noteDirty.put(index, false);
4915                 
4916                 // ExtendedInformationを必要があれば表示する
4917                 toggleNoteInformation();
4918                 // Sourceを必要があれば表示する
4919                 viewSource();
4920                 // EditorButtonsBarを必要があれば表示する
4921                 toggleEditorButtonBar();
4922
4923                 // 履歴記録のハッシュマップを初期化
4924                 ArrayList<String> histGuids = new ArrayList<String>();
4925                 historyGuids.put(index, histGuids);
4926                 historyPosition.put(index, 0);
4927                 fromHistory.put(index, false);
4928
4929                 tabBrowser.setCurrentIndex(index);
4930         }
4931
4932     //***************************************************************
4933     //***************************************************************
4934     //** These functions deal with Note specific things
4935     //***************************************************************
4936     //***************************************************************    
4937         // ICHANGED
4938         private void setNoteDirty() {
4939                 for (String guid: selectedNoteGUIDs) {
4940                         setNoteDirty(guid);
4941                 }
4942         }
4943         
4944         // ICHANGED
4945         private void setNoteDirty(String targetGuid) {
4946                 logger.log(logger.EXTREME, "Entering NeverNote.setNoteDirty()");
4947                 
4948                 // Find if the note is being edited externally.  If it is, update it.
4949                 if (externalWindows.containsKey(targetGuid)) {
4950                         QTextCodec codec = QTextCodec.codecForName("UTF-8");
4951                 QByteArray unicode =  codec.fromUnicode(browserWindow.getContent());
4952                         ExternalBrowse window = externalWindows.get(targetGuid);
4953                 window.getBrowserWindow().setContent(unicode);
4954                 }
4955                 
4956                 // 他のタブで同じノートを開いていないか探す。もしあったら、内容を更新する。
4957                 Collection<Integer> tabIndexes = tabWindows.keySet();
4958                 Iterator<Integer>       indexIterator = tabIndexes.iterator();
4959                 
4960                 for (TabBrowse tab: tabWindows.values()) {
4961                         int index = indexIterator.next();
4962                         String guid = tab.getBrowserWindow().getNote().getGuid();
4963                         
4964                         QTextCodec codec = QTextCodec.codecForName("UTF-8");
4965                         QByteArray unicode = codec.fromUnicode(browserWindow.getContent());
4966                         
4967                         if (guid.equals(guid)) {
4968                                 if (index != tabBrowser.currentIndex()) {
4969                                         TabBrowse window = tabWindows.get(index);
4970                                         window.getBrowserWindow().setContent(unicode);
4971                                 }
4972                         }
4973                 }
4974                 
4975                 // ターゲットノートがタブで開かれていて、かつDirty = trueかどうかを取得する
4976                 // If the note is dirty, then it is unsynchronized by default.
4977                 int index = -1;
4978                 boolean isNoteDirty = false;
4979                 for (TabBrowse tab: tabWindows.values()) {
4980                         if (tab.getBrowserWindow().getNote().getGuid().equals(targetGuid)) {
4981                                 index = tabBrowser.indexOf(tab);
4982                                 isNoteDirty = noteDirty.get(index);
4983                                 break;
4984                         }
4985                 }
4986                 if (isNoteDirty) {
4987                         return;
4988                 }
4989                 
4990                 // Set the note as dirty and check if its status is synchronized in the display table
4991                 // まだダーティでなく、かつタブで開かれている場合にnoteDirty = trueにする
4992                 if (index >= 0) {
4993                         noteDirty.put(index, true);
4994                 }
4995
4996                 if (listManager.getNoteMetadata().containsKey(targetGuid) &&
4997                                 listManager.getNoteMetadata().get(targetGuid).isDirty()) {
4998                                 return;
4999                 }
5000                 
5001                 // If this wasn't already marked as unsynchronized, then we need to update the table
5002                 listManager.getNoteTableModel().updateNoteSyncStatus(targetGuid, false);
5003 //      listManager.getUnsynchronizedNotes().add(targetGuid);
5004         for (int i=0; i<listManager.getNoteTableModel().rowCount(); i++) {
5005                 QModelIndex modelIndex =  listManager.getNoteTableModel().index(i, Global.noteTableGuidPosition);
5006                 if (modelIndex != null) {
5007                         SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
5008                         String tableGuid =  (String)ix.values().toArray()[0];
5009                         if (tableGuid.equals(targetGuid)) {
5010                                 listManager.getNoteTableModel().proxyModel.setData(i, Global.noteTableSynchronizedPosition, "false");
5011                                 return;
5012                         }
5013                 }
5014         }
5015         
5016                 logger.log(logger.EXTREME, "Leaving NeverNote.setNoteDirty()");
5017     }
5018     @SuppressWarnings("unused")
5019         private void saveNoteExternalBrowser(String guid, String content, Boolean save, BrowserWindow browser) {
5020                 QTextCodec codec = QTextCodec.codecForName("UTF-8");
5021         QByteArray unicode =  codec.fromUnicode(content);
5022         noteCache.remove(guid);
5023                 noteCache.put(guid, unicode.toString());
5024         if (guid.equals(currentNoteGuid)) {
5025                 // ICHANGED
5026                 int index = tabBrowser.currentIndex();
5027                 noteDirty.put(index, true);
5028                 browserWindow.setContent(unicode);
5029         } 
5030         if (save) {
5031                 thumbnailRunner.addWork("GENERATE "+ guid);
5032                 saveNote(guid, browser);
5033         }
5034         
5035     }
5036     
5037         // ICHANGED
5038         private void saveNoteTabBrowser(String guid, String content, Boolean save,
5039                         BrowserWindow browser) {
5040                 QTextCodec codec = QTextCodec.codecForName("UTF-8");
5041                 QByteArray unicode = codec.fromUnicode(content);
5042                 noteCache.remove(guid);
5043                 noteCache.put(guid, unicode.toString());
5044                 if (save) {
5045                         thumbnailRunner.addWork("GENERATE " + guid);
5046                         saveNote(guid, browser);
5047                 }
5048         }
5049         
5050     private void saveNote() {
5051         // ICHANGED
5052         // すべてのタブに対して、Dirtyを確認し、trueならセーブする
5053         Collection<Integer> dirtyIndex = noteDirty.keySet();
5054         Iterator<Integer> indexIterator = dirtyIndex.iterator();
5055         for (boolean isNoteDirty: noteDirty.values()) {
5056                 int index = indexIterator.next();
5057                 if (isNoteDirty) {
5058                         if (index < 0) {
5059                                 return;
5060                         }
5061                         BrowserWindow b = tabWindows.get(index).getBrowserWindow();
5062                         String guid = b.getNote().getGuid();
5063                         saveNote(guid, b);
5064                         thumbnailRunner.addWork("GENERATE "+ guid);
5065                         noteDirty.put(index, false);
5066                 }
5067         }
5068     }
5069     private void saveNote(String guid, BrowserWindow window) {
5070                 logger.log(logger.EXTREME, "Inside NeverNote.saveNote()");
5071                 waitCursor(true);
5072                 
5073                 logger.log(logger.EXTREME, "Saving to cache");
5074                 QTextCodec codec = QTextCodec.codecForLocale();
5075 //              QTextDecoder decoder = codec.makeDecoder();
5076                 codec = QTextCodec.codecForName("UTF-8");
5077         QByteArray unicode =  codec.fromUnicode(window.getContent());
5078                 noteCache.put(guid, unicode.toString());
5079                         
5080                 logger.log(logger.EXTREME, "updating list manager");
5081                 listManager.updateNoteContent(guid, window.getContent());
5082                 logger.log(logger.EXTREME, "Updating title");
5083                 listManager.updateNoteTitle(guid, window.getTitle());
5084                 updateListDateChanged();
5085
5086                 logger.log(logger.EXTREME, "Looking through note index for refreshed note");
5087                 for (int i=0; i<listManager.getNoteIndex().size(); i++) {
5088                 if (listManager.getNoteIndex().get(i).getGuid().equals(guid)) {
5089                         currentNote = listManager.getNoteIndex().get(i);
5090                         i = listManager.getNoteIndex().size();
5091                 }
5092         }
5093         waitCursor(false);
5094     }
5095     // Get a note from Evernote (and put it in the browser)
5096         private void refreshEvernoteNote(boolean reload) {
5097                 logger.log(logger.HIGH, "Entering NeverNote.refreshEvernoteNote");
5098                 
5099                 if (Global.disableViewing) {
5100                         browserWindow.setEnabled(false);
5101                         return;
5102                 }
5103                 // ICHANGED
5104                 inkNote.put(tabBrowser.currentIndex(), false);
5105                 readOnly.put(tabBrowser.currentIndex(), false);
5106                 
5107                 if (Global.showDeleted || currentNoteGuid == null || currentNoteGuid.equals("")) {
5108                         readOnly.put(tabBrowser.currentIndex(), true);
5109                 }
5110                 Global.cryptCounter =0;
5111                 if (readOnly.get(tabBrowser.currentIndex())) {
5112                         browserWindow.setReadOnly(true);
5113                 }
5114                 
5115                 if (!reload)
5116                         return;
5117                 
5118                 waitCursor(true);
5119                 browserWindow.loadingData(true);
5120
5121                 currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true);
5122                 if (currentNote == null) {
5123                         waitCursor(false);
5124                         return;
5125                 }
5126                 
5127                 // ICHANGED
5128                 tabBrowser.setTabTitle(tabBrowser.currentIndex(), currentNote.getTitle());
5129                 
5130                 loadNoteBrowserInformation(browserWindow, currentNoteGuid, currentNote);
5131         }
5132
5133         // ICHANGED
5134         private void loadNoteBrowserInformation(BrowserWindow browser, String guid, Note note) {
5135                 NoteFormatter   formatter = new NoteFormatter(logger, conn, tempFiles);
5136                 formatter.setNote(note, Global.pdfPreview());
5137                 formatter.setHighlight(listManager.getEnSearch());
5138                 QByteArray js;
5139                 int tabIndex = -1;
5140                 
5141                 // 対象のタブインデックスを取得
5142                 for (TabBrowse tab: tabWindows.values()) {
5143                         if (tab.getBrowserWindow() == browser) {
5144                                 tabIndex = tabBrowser.indexOf(tab);
5145                                 break;
5146                         }
5147                 }
5148                 
5149                 if (!noteCache.containsKey(guid)) {
5150                         js = new QByteArray();
5151                         // We need to prepend the note with <HEAD></HEAD> or encoded characters are ugly 
5152                         js.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");               
5153                         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>");
5154                         js.append("<style type=\"text/css\">en-hilight { background-color: rgb(255,255,0) }</style>");
5155                         js.append("<style> img { height:auto; width:auto; max-height:auto; max-width:100%; }</style>");
5156                         if (Global.displayRightToLeft())
5157                                 js.append("<style> body { direction:rtl; }</style>");
5158                         js.append("<style type=\"text/css\">en-spell { text-decoration: none; border-bottom: dotted 1px #cc0000; }</style>");
5159                         js.append("</head>");
5160                         formatter.setNote(note, Global.pdfPreview());
5161                         js.append(formatter.rebuildNoteHTML());
5162                         js.append("</HTML>");
5163                         js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml.dtd'>", "");
5164                         js.replace("<!DOCTYPE en-note SYSTEM 'http://xml.evernote.com/pub/enml2.dtd'>", "");
5165                         js.replace("<?xml version='1.0' encoding='UTF-8'?>", "");
5166 //              if (Global.enableHTMLEntitiesFix) {
5167 //                      browser.getBrowser().setContent(new QByteArray(StringEscapeUtils.unescapeHtml(js.toString())));
5168 //              } else
5169                         browser.setContent(js);
5170                         noteCache.put(guid, js.toString());
5171
5172                         if (formatter.resourceError)
5173                                 resourceErrorMessage(tabIndex);
5174                         if (formatter.formatError) {
5175                                 waitCursor(false);
5176                              QMessageBox.information(this, tr("Error"),
5177                                                 tr("NeighborNote had issues formatting this note." +
5178                                                 " To protect your data this note is being marked as read-only."));      
5179                              waitCursor(true);
5180                         }
5181                         
5182                         if (tabIndex >= 0) {
5183                                 readOnly.put(tabIndex, formatter.readOnly);
5184                                 inkNote.put(tabIndex, formatter.inkNote);
5185                         } 
5186                         
5187                         if (tabIndex >= 0 && readOnly.get(tabIndex)) {
5188                                 readOnlyCache.put(guid, true);
5189                         }
5190                         if (tabIndex >= 0 && inkNote.get(tabIndex)) {
5191                                 inkNoteCache.put(guid, true);
5192                         }
5193                         
5194                 } else {
5195                         logger.log(logger.HIGH, "Note content is being pulled from the cache");
5196                         String cachedContent = formatter.modifyCachedTodoTags(noteCache.get(guid));
5197                         js = new QByteArray(cachedContent);
5198                         browser.setContent(js);
5199                         if (readOnlyCache.containsKey(guid) && tabIndex >= 0) {
5200                                 readOnly.put(tabIndex, true);
5201                         } else {
5202                                 readOnly.put(tabIndex, false);
5203                         }
5204                         if (inkNoteCache.containsKey(guid) && tabIndex >= 0) {
5205                                 inkNote.put(tabIndex, true);
5206                         } else {
5207                                 inkNote.put(tabIndex, false);
5208                         }
5209                 }
5210                 if (conn.getNoteTable().isThumbnailNeeded(guid)) {
5211                         thumbnailHTMLReady(guid, js, Global.calculateThumbnailZoom(js.toString()));
5212                 }
5213                 if (tabIndex >= 0 && (readOnly.get(tabIndex) || inkNote.get(tabIndex) || 
5214                                 (note.getAttributes() != null && note.getAttributes().getContentClass() != null && note.getAttributes().getContentClass() != "")))
5215                         browser.getBrowser().page().setContentEditable(false);  // We don't allow editing of ink notes
5216                 else
5217                         browser.getBrowser().page().setContentEditable(true);
5218                 if (tabIndex >= 0) {
5219                         browser.setReadOnly(readOnly.get(tabIndex));
5220                         deleteButton.setEnabled(!readOnly.get(tabIndex));
5221                         tagButton.setEnabled(!readOnly.get(tabIndex));
5222                         menuBar.noteDelete.setEnabled(!readOnly.get(tabIndex));
5223                         menuBar.noteTags.setEnabled(!readOnly.get(tabIndex));
5224                 }
5225                 browser.setNote(note);
5226                 
5227                 if (note != null && note.getNotebookGuid() != null && 
5228                                 conn.getNotebookTable().isLinked(note.getNotebookGuid())) {
5229                         deleteButton.setEnabled(false);
5230                         menuBar.notebookDeleteAction.setEnabled(false);
5231                 } else {
5232                         deleteButton.setEnabled(true);
5233                         menuBar.notebookDeleteAction.setEnabled(true);
5234                 }
5235                 
5236                 // Build a list of non-closed notebooks
5237                 List<Notebook> nbooks = new ArrayList<Notebook>();
5238                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
5239                         boolean found=false;
5240                         for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
5241                                 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid())) 
5242                                         found = true;
5243                         }
5244                         if (!found)
5245                                 nbooks.add(listManager.getNotebookIndex().get(i));
5246                 }
5247                 
5248                 browser.setTitle(note.getTitle());
5249                 browser.setTag(getTagNamesForNote(note));
5250                 browser.setAuthor(note.getAttributes().getAuthor());
5251
5252                 browser.setAltered(note.getUpdated());
5253                 browser.setCreation(note.getCreated());
5254                 if (note.getAttributes().getSubjectDate() > 0)
5255                         browser.setSubjectDate(note.getAttributes().getSubjectDate());
5256                 else
5257                         browser.setSubjectDate(note.getCreated());
5258                 browser.setUrl(note.getAttributes().getSourceURL());
5259                 
5260                 FilterEditorTags tagFilter = new FilterEditorTags(conn, logger);
5261                 List<Tag> tagList = tagFilter.getValidTags(note);
5262                 browser.setAllTags(tagList);
5263                 
5264                 browser.setCurrentTags(note.getTagNames());
5265                 // ICHANGED
5266                 for (TabBrowse tab: tabWindows.values()) {
5267                         if (tab.getBrowserWindow().getNote().getGuid().equals(guid)) {
5268                                 int index = tabBrowser.indexOf(tab);
5269                                 noteDirty.put(index, false);
5270                                 break;
5271                         }
5272                 }
5273                 
5274                 scrollToGuid(guid);
5275                 
5276                 browser.loadingData(false);
5277                 if (thumbnailViewer.isActiveWindow())
5278                         thumbnailView();
5279                 
5280                 FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger);
5281                 browser.setNotebookList(notebookFilter.getValidNotebooks(note, listManager.getNotebookIndex()));
5282
5283                 waitCursor(false);
5284                 logger.log(logger.HIGH, "Leaving NeverNote.refreshEvernoteNote");
5285         }
5286         
5287         // ICHANGED
5288         @SuppressWarnings("unused")
5289         private void toggleNoteAttributes() {
5290                 menuBar.noteAttributes.setChecked(!menuBar.noteAttributes.isChecked());
5291                 toggleNoteInformation();
5292         }
5293         
5294         // Save a generated thumbnail
5295         private void toggleNoteInformation() {
5296                 logger.log(logger.HIGH, "Entering NeverNote.toggleNoteInformation");
5297         
5298         // ICHANGED
5299                 boolean isChecked = menuBar.noteAttributes.isChecked();
5300                 
5301         for(int i = 0; i < tabBrowser.count(); i++){
5302                 BrowserWindow browser = ((TabBrowse) tabBrowser.widget(i)).getBrowserWindow();
5303                 boolean isExtended = browser.isExtended();
5304                 if((isChecked && !isExtended) || (!isChecked && isExtended)){
5305                         browser.toggleInformation();
5306                 }
5307         }
5308         
5309         menuBar.noteAttributes.setChecked(browserWindow.isExtended());
5310         Global.saveWindowVisible("noteInformation", browserWindow.isExtended());
5311         logger.log(logger.HIGH, "Leaving NeverNote.toggleNoteInformation");
5312     }
5313         
5314         // Listener triggered when a print button is pressed
5315     @SuppressWarnings("unused")
5316         private void printNote() {
5317                 logger.log(logger.HIGH, "Entering NeverNote.printNote");
5318
5319         QPrintDialog dialog = new QPrintDialog();
5320         if (dialog.exec() == QDialog.DialogCode.Accepted.value()) {
5321                 QPrinter printer = dialog.printer();
5322                 browserWindow.getBrowser().print(printer);
5323         }
5324                 logger.log(logger.HIGH, "Leaving NeverNote.printNote");
5325
5326     }
5327     // Listener triggered when the email button is pressed
5328     @SuppressWarnings("unused")
5329         private void emailNote() {
5330         logger.log(logger.HIGH, "Entering NeverNote.emailNote");
5331         
5332         if (Desktop.isDesktopSupported()) {
5333             Desktop desktop = Desktop.getDesktop();
5334             
5335             String text2 = browserWindow.getContentsToEmail();
5336             QUrl url = new QUrl("mailto:");
5337             url.addQueryItem("subject", currentNote.getTitle());
5338 //            url.addQueryItem("body", QUrl.toPercentEncoding(text2).toString());
5339             url.addQueryItem("body", text2);
5340             QDesktopServices.openUrl(url);
5341         }
5342 /*            
5343             
5344             if (desktop.isSupported(Desktop.Action.MAIL)) {
5345                 URI uriMailTo = null;
5346                 try {
5347                         //String text = browserWindow.getBrowser().page().currentFrame().toPlainText();
5348                         String text = browserWindow.getContentsToEmail();
5349                         //text = "<b>" +text +"</b>";
5350                                         uriMailTo = new URI("mailto", "&SUBJECT="+currentNote.getTitle()
5351                                                         +"&BODY=" +text, null);
5352                                         uriMailTo = new URI("mailto", "&SUBJECT="+currentNote.getTitle()
5353                                                         +"&ATTACHMENT=d:/test.pdf", null);
5354                                         desktop.mail(uriMailTo);
5355                                 } catch (URISyntaxException e) {
5356                                         e.printStackTrace();
5357                                 } catch (IOException e) {
5358                                         e.printStackTrace();
5359                                 }
5360
5361             }
5362
5363         }     
5364  */     
5365         logger.log(logger.HIGH, "Leaving NeverNote.emailNote");
5366     }
5367         // Reindex all notes
5368     @SuppressWarnings("unused")
5369         private void fullReindex() {
5370         logger.log(logger.HIGH, "Entering NeverNote.fullReindex");
5371         indexRunner.addWork("REINDEXALL");
5372         setMessage(tr("Database will be reindexed."));
5373         logger.log(logger.HIGH, "Leaving NeverNote.fullReindex");
5374     }
5375     // Listener when a user wants to reindex a specific note
5376     @SuppressWarnings("unused")
5377         private void reindexNote() {
5378         logger.log(logger.HIGH, "Entering NeverNote.reindexNote");
5379                 for (int i=0; i<selectedNoteGUIDs.size(); i++) {
5380                         indexRunner.addWork("REINDEXNOTE "+selectedNoteGUIDs.get(i));
5381                 }
5382                 if (selectedNotebookGUIDs.size() > 1)
5383                         setMessage(tr("Notes will be reindexed."));
5384                 else
5385                         setMessage(tr("Note will be reindexed."));
5386         logger.log(logger.HIGH, "Leaving NeverNote.reindexNote");
5387     }
5388     // Delete the note
5389     @SuppressWarnings("unused")
5390         private void deleteNote() {
5391         logger.log(logger.HIGH, "Entering NeverNote.deleteNote");
5392         if (currentNote == null) 
5393                 return;
5394         if (currentNoteGuid.equals(""))
5395                 return;
5396         String title = null;
5397         if (selectedNoteGUIDs.size() == 1)
5398                 title = conn.getNoteTable().getNote(selectedNoteGUIDs.get(0),false,false,false,false,false).getTitle();
5399
5400         // If we are deleting non-trash notes
5401         if (currentNote.isActive()) { 
5402                 if (Global.verifyDelete()) {
5403                         String msg;
5404                         if (selectedNoteGUIDs.size() > 1) {
5405                                 msg = new String(tr("Delete ") +selectedNoteGUIDs.size() +" notes?");
5406                         } else {
5407                                 if (title != null)
5408                                         msg = new String(tr("Delete note \"") +title +"\"?");
5409                                 else                            
5410                                         msg = new String(tr("Delete note selected note?"));
5411                         }
5412                         if (QMessageBox.question(this, tr("Confirmation"), msg,
5413                                         QMessageBox.StandardButton.Yes, 
5414                                         QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) {
5415                                         return;
5416                         }
5417                 }
5418                 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals("")) 
5419                         selectedNoteGUIDs.add(currentNoteGuid);
5420                 for (int i=0; i<selectedNoteGUIDs.size(); i++) {
5421                         listManager.deleteNote(selectedNoteGUIDs.get(i));
5422                 }
5423         } else { 
5424                 // If we are deleting from the trash.
5425                 if (Global.verifyDelete()) {
5426                         String msg;
5427                         if (selectedNoteGUIDs.size() > 1) {
5428                                 msg = new String(tr("Permanently delete ") +selectedNoteGUIDs.size() +" notes?");
5429                         } else {
5430                                 if (title != null)
5431                                 msg = new String(tr("Permanently delete note \"") +title +"\"?");
5432                                 else
5433                                         msg = new String(tr("Permanently delete note selected note?"));
5434                         }
5435                         if (QMessageBox.question(this, "Confirmation", msg,
5436                                 QMessageBox.StandardButton.Yes, 
5437                                         QMessageBox.StandardButton.No)==StandardButton.No.value()) {                                            
5438                                         return;
5439                         }
5440                 }
5441                 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals("")) 
5442                         selectedNoteGUIDs.add(currentNoteGuid);
5443                 for (int i=selectedNoteGUIDs.size()-1; i>=0; i--) {
5444                         for (int j=listManager.getNoteTableModel().rowCount()-1; j>=0; j--) {
5445                         QModelIndex modelIndex =  listManager.getNoteTableModel().index(j, Global.noteTableGuidPosition);
5446                         if (modelIndex != null) {
5447                                 SortedMap<Integer, Object> ix = listManager.getNoteTableModel().itemData(modelIndex);
5448                                 String tableGuid =  (String)ix.values().toArray()[0];
5449                                 if (tableGuid.equals(selectedNoteGUIDs.get(i))) {
5450                                         listManager.getNoteTableModel().removeRow(j);
5451                                         j=-1;
5452                                 }
5453                         }
5454                 }
5455                         listManager.expungeNote(selectedNoteGUIDs.get(i));
5456                         
5457                         // ICHANGED
5458                         conn.getHistoryTable().expungeHistory(selectedNoteGUIDs.get(i));
5459                         conn.getExcludedTable().expungeExcludedNote(selectedNoteGUIDs.get(i));
5460                         conn.getStaredTable().expungeStaredNote(selectedNoteGUIDs.get(i));
5461                         
5462                 }
5463         }
5464         currentNoteGuid = "";
5465         
5466         // ICHANGED ↓↓↓ここから↓↓↓
5467                 // 削除したノートを外部ウィンドウで開いていたら、閉じる
5468                 Collection<ExternalBrowse>      windows = externalWindows.values();
5469                 Iterator<ExternalBrowse>        windowIterator = windows.iterator();
5470                 Collection<String>                      guids = externalWindows.keySet();
5471                 Iterator<String>                        guidIterator = guids.iterator();
5472                 List<ExternalBrowse>            closeWindows = new ArrayList<ExternalBrowse>(); // イテレータ操作中に中身をいじっちゃダメなので
5473                 
5474                 while (windowIterator.hasNext()) {
5475                         ExternalBrowse browser = windowIterator.next();
5476                         String guid = guidIterator.next();
5477                         
5478                         for (int i = 0; i < selectedNoteGUIDs.size(); i++) {
5479                                 if (guid.equals(selectedNoteGUIDs.get(i))) {
5480                                         closeWindows.add(browser);
5481                                 }
5482                         }
5483                 }
5484                 
5485                 for (int i = closeWindows.size() - 1; i >= 0; i--) {
5486                         closeWindows.get(i).close();
5487                 }
5488                 // ICHANGED ↑↑↑ここまで↑↑↑
5489                 
5490         // ICHANGED ↓↓↓ここから↓↓↓
5491         // 削除したノートをタブで開いていたら、閉じる
5492                 Collection<TabBrowse> tabBrowsers = tabWindows.values();
5493                 Iterator<TabBrowse> tabIterator = tabBrowsers.iterator();
5494                 Collection<Integer> tabIndexes = tabWindows.keySet();
5495                 Iterator<Integer>       indexIterator = tabIndexes.iterator();
5496                 List<Integer> closeIndexes = new ArrayList<Integer>();  //イテレータ操作中に中身をいじっちゃダメなので
5497
5498                 while (tabIterator.hasNext()) {
5499                         TabBrowse tab = tabIterator.next();
5500                         int index = indexIterator.next();
5501                         String guid = tab.getBrowserWindow().getNote().getGuid();
5502                         
5503                         for(int i = 0; i < selectedNoteGUIDs.size(); i++){
5504                                 if(guid.equals(selectedNoteGUIDs.get(i))){
5505                                         closeIndexes.add(index);
5506                                 }
5507                         }
5508                 }
5509                 
5510                 for(int i = closeIndexes.size() - 1; i >= 0; i--){
5511                         tabWindowClosing(closeIndexes.get(i));
5512                 }
5513                 // ICHANGED ↑↑↑ここまで↑↑↑              
5514         
5515         listManager.loadNotesIndex();
5516         noteIndexUpdated(false);
5517         refreshEvernoteNote(true);
5518         scrollToGuid(currentNoteGuid);
5519         logger.log(logger.HIGH, "Leaving NeverNote.deleteNote");
5520     }
5521     // Add a new note
5522     // ICHANGED @SuppressWarnings("unused") を削除
5523         private void addNote() {
5524         logger.log(logger.HIGH, "Inside NeverNote.addNote");
5525 //      browserWindow.setEnabled(true);
5526         browserWindow.setReadOnly(false);
5527         saveNote();
5528         Calendar currentTime = new GregorianCalendar();
5529         StringBuffer noteString = new StringBuffer(100);
5530         noteString.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
5531                 "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">\n" +
5532                 "<en-note>\n");
5533         
5534         if (Global.overrideDefaultFont()) {
5535                 noteString.append("<font face=\"" +Global.getDefaultFont() +"\" >");
5536                 noteString.append("<span style=\"font-size:" +Global.getDefaultFontSize() +"pt;\">");
5537                 noteString.append("<br clear=\"none\" />\n");
5538                 noteString.append("</span>\n</font>\n");
5539         } else
5540                 noteString.append("<br clear=\"none\" />\n");
5541         noteString.append("</en-note>");
5542         
5543         Long l = new Long(currentTime.getTimeInMillis());
5544         String randint = new String(Long.toString(l));          
5545         
5546         // Find a notebook.  We first look for a selected notebook (the "All Notebooks" one doesn't count).  
5547         // Then we look
5548         // for the first non-archived notebook.  Finally, if nothing else we 
5549         // pick the first notebook in the list.
5550         String notebook = null;
5551         listManager.getNotebookIndex().get(0).getGuid();
5552         List<QTreeWidgetItem> selectedNotebook = notebookTree.selectedItems();
5553         if (selectedNotebook.size() > 0 && !selectedNotebook.get(0).text(0).equalsIgnoreCase("All Notebooks") && !selectedNotebook.get(0).text(2).equalsIgnoreCase("STACK")) {
5554                 QTreeWidgetItem currentSelectedNotebook = selectedNotebook.get(0);
5555                 notebook = currentSelectedNotebook.text(2);
5556         } else {
5557                 boolean found = false;
5558                 List<Notebook> goodNotebooks = new ArrayList<Notebook>();
5559                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
5560                         boolean match = false;
5561                         for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
5562                                 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid())) {
5563                                         match = true;
5564                                         j = listManager.getArchiveNotebookIndex().size();
5565                                 }
5566                         }
5567                         if (!match)
5568                                 //goodNotebooks.add(listManager.getNotebookIndex().get(i).deepCopy());
5569                                 goodNotebooks.add((Notebook)Global.deepCopy(listManager.getNotebookIndex().get(i)));
5570                 }
5571                 // Now we have a list of good notebooks, so we can look for the default
5572                 found = false;
5573                 for (int i=0; i<goodNotebooks.size(); i++) {
5574                         if (goodNotebooks.get(i).isDefaultNotebook()) {
5575                                 notebook = goodNotebooks.get(i).getGuid();
5576                                 found = true;
5577                                 i = goodNotebooks.size();
5578                         }
5579                 }
5580                 
5581                 if (goodNotebooks.size() > 0 && !found)
5582                         notebook = goodNotebooks.get(0).getGuid();
5583      
5584                 if (notebook==null)
5585                         notebook = listManager.getNotebookIndex().get(0).getGuid();             
5586         }
5587         
5588         Note newNote = new Note();
5589         newNote.setUpdateSequenceNum(0);
5590         newNote.setGuid(randint);
5591         newNote.setNotebookGuid(notebook);
5592         newNote.setTitle("Untitled Note");
5593         newNote.setContent(noteString.toString());
5594         newNote.setDeleted(0);
5595         newNote.setCreated(System.currentTimeMillis());
5596         newNote.setUpdated(System.currentTimeMillis());
5597         newNote.setActive(true);
5598         NoteAttributes na = new NoteAttributes();
5599         na.setLatitude(0.0);
5600         na.setLongitude(0.0);
5601         na.setAltitude(0.0);
5602         newNote.setAttributes(new NoteAttributes());
5603                 newNote.setTagGuids(new ArrayList<String>());
5604                 newNote.setTagNames(new ArrayList<String>());
5605         
5606         // If new notes are to be created based upon the selected tags, then we need to assign the tags
5607         if (Global.newNoteWithSelectedTags()) { 
5608                 List<QTreeWidgetItem> selections = tagTree.selectedItems();
5609                 QTreeWidgetItem currentSelection;
5610                 for (int i=0; i<selections.size(); i++) {
5611                         currentSelection = selections.get(i);
5612                         newNote.getTagGuids().add(currentSelection.text(2));
5613                         newNote.getTagNames().add(currentSelection.text(0));
5614                 }
5615         }
5616         
5617         conn.getNoteTable().addNote(newNote, true);
5618         NoteMetadata metadata = new NoteMetadata();
5619         metadata.setGuid(newNote.getGuid());
5620         metadata.setDirty(true);
5621         listManager.addNote(newNote, metadata);
5622 //      noteTableView.insertRow(newNote, true, -1);
5623         
5624         // ICHANGED
5625         String prevCurrentNoteGuid = new String(currentNoteGuid);
5626         
5627         currentNote = newNote;
5628         currentNoteGuid = currentNote.getGuid();
5629         // IFIXED こいつのせいで、ノート追加時にcurrentNoteGuidが更新されないので消す
5630         // noteTableView.clearSelection();
5631         
5632         refreshEvernoteNote(true);
5633         listManager.countNotebookResults(listManager.getNoteIndex());
5634         browserWindow.titleLabel.setFocus();
5635         browserWindow.titleLabel.selectAll();
5636 //      notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
5637         
5638         // ICHANGED 新規に作成したノートとそれまで開いていたノートの関連性を追加
5639         if (prevCurrentNoteGuid != null && !prevCurrentNoteGuid.equals("")) {
5640                 if (currentNoteGuid != null && !currentNoteGuid.equals("")) {
5641                         conn.getHistoryTable().addHistory("addNewNote", prevCurrentNoteGuid, currentNoteGuid);
5642                 }
5643         }
5644         
5645         // If the window is hidden, then we want to popup this in an external window & 
5646         if (!isVisible())
5647                 listDoubleClick();
5648         waitCursor(false);
5649         logger.log(logger.HIGH, "Leaving NeverNote.addNote");
5650     }
5651     // Restore a note from the trash;
5652     @SuppressWarnings("unused")
5653         private void restoreNote() {
5654         waitCursor(true);
5655                 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals("")) 
5656                         selectedNoteGUIDs.add(currentNoteGuid);
5657                 for (int i=0; i<selectedNoteGUIDs.size(); i++) {
5658                         listManager.restoreNote(selectedNoteGUIDs.get(i));
5659                 }
5660         currentNoteGuid = "";
5661         listManager.loadNotesIndex();
5662         noteIndexUpdated(false);
5663         waitCursor(false);
5664     }
5665     // Search a note for specific txt
5666     @SuppressWarnings("unused")
5667         private void findText() {
5668         find.show();
5669         find.setFocusOnTextField();
5670     }
5671     @SuppressWarnings("unused")
5672         private void doFindText() {
5673         browserWindow.getBrowser().page().findText(find.getText(), find.getFlags());
5674         find.setFocus();
5675     }
5676     @SuppressWarnings("unused")
5677         private void updateNoteTitle(String guid, String title) {
5678         listManager.setNoteSynchronized(guid, false);
5679         
5680         // We do this manually because if we've edited the note in an 
5681         // external window we run into the possibility of signal recursion
5682         // looping.
5683         if (guid.equals(currentNoteGuid)) {
5684                 browserWindow.titleLabel.blockSignals(true);
5685                 browserWindow.titleLabel.setText(title);
5686                 browserWindow.titleLabel.blockSignals(false);
5687         }
5688     }
5689     // Signal received that note content has changed.  Normally we just need the guid to remove
5690     // it from the cache.
5691     @SuppressWarnings("unused")
5692         private void invalidateNoteCache(String guid, String content) {
5693         noteCache.remove(guid);
5694                 refreshEvernoteNote(true);
5695     }
5696     // Signal received that a note guid has changed
5697     @SuppressWarnings("unused")
5698         private void noteGuidChanged(String oldGuid, String newGuid) {
5699         if (noteCache.containsKey(oldGuid)) {
5700                 if (!oldGuid.equals(currentNoteGuid)) {
5701                         String cache = noteCache.get(oldGuid);
5702                         noteCache.put(newGuid, cache);
5703                         noteCache.remove(oldGuid);
5704                 } else {
5705                         noteCache.remove(oldGuid);
5706                         noteCache.put(newGuid, browserWindow.getContent());
5707                 }
5708         }
5709   
5710         listManager.updateNoteGuid(oldGuid, newGuid, false);
5711         if (currentNoteGuid.equals(oldGuid)) {
5712                 if (currentNote != null)
5713                         currentNote.setGuid(newGuid);
5714                 currentNoteGuid = newGuid;
5715         }
5716                 
5717         if (externalWindows.containsKey(oldGuid)) {
5718                         ExternalBrowse b = externalWindows.get(oldGuid);
5719                         externalWindows.remove(oldGuid);
5720                         b.getBrowserWindow().getNote().setGuid(newGuid);
5721                         externalWindows.put(newGuid, b);
5722                 }
5723         
5724                 // ICHANGED
5725                 for(int i = 0; i < tabBrowser.count(); i++){
5726                         TabBrowse b = (TabBrowse)tabBrowser.widget(i);
5727                         if (b.getBrowserWindow().getNote().getGuid().equals(oldGuid)) {
5728                                 b.getBrowserWindow().getNote().setGuid(newGuid);
5729                         }
5730                 }
5731
5732         for (int i=0; i<listManager.getNoteIndex().size(); i++) {
5733                 if (listManager.getNoteIndex().get(i).getGuid().equals(newGuid)) {
5734                         noteTableView.proxyModel.addGuid(newGuid, listManager.getNoteMetadata().get(newGuid));
5735                         i=listManager.getNoteIndex().size();
5736                 }
5737         }
5738         
5739         if (listManager.getNoteTableModel().metaData.containsKey(oldGuid)) {
5740                 NoteMetadata meta = listManager.getNoteTableModel().metaData.get(oldGuid);
5741                 listManager.getNoteTableModel().metaData.put(newGuid, meta);
5742                 listManager.getNoteTableModel().metaData.remove(oldGuid);
5743         }
5744         
5745     }
5746         
5747     // Toggle the note editor button bar
5748     // ICHANGED すべてのタブに
5749     private void toggleEditorButtonBar() {
5750         boolean isChecked = menuBar.showEditorBar.isChecked();
5751         
5752         for(int i = 0; i < tabBrowser.count(); i++){
5753                 BrowserWindow browser = ((TabBrowse) tabBrowser.widget(i)).getBrowserWindow();
5754                 boolean isVisible = browser.buttonsVisible;
5755
5756                 if (isChecked && !isVisible) {
5757                         browser.buttonsVisible = true;
5758                         showEditorButtons(browser);
5759                 } else if(!isChecked && isVisible) {
5760                         browser.hideButtons();
5761                 }
5762         }
5763
5764         Global.saveWindowVisible("editorButtonBar", browserWindow.buttonsVisible);
5765     }
5766     
5767     // Show editor buttons
5768     private void showEditorButtons(BrowserWindow browser) {
5769                 browser.buttonLayout.setVisible(true);
5770                 browser.undoAction.setVisible(false);
5771                 
5772                 browser.undoButton.setVisible(false);
5773
5774                 browser.undoAction.setVisible(Global.isEditorButtonVisible("undo"));
5775                 browser.redoAction.setVisible(Global.isEditorButtonVisible("redo"));
5776                 browser.cutAction.setVisible(Global.isEditorButtonVisible("cut"));
5777                 browser.copyAction.setVisible(Global.isEditorButtonVisible("copy"));
5778                 browser.pasteAction.setVisible(Global.isEditorButtonVisible("paste"));
5779                 browser.strikethroughAction.setVisible(Global.isEditorButtonVisible("strikethrough"));
5780                 browser.underlineAction.setVisible(Global.isEditorButtonVisible("underline"));
5781                 browser.boldAction.setVisible(Global.isEditorButtonVisible("bold"));
5782                 browser.italicAction.setVisible(Global.isEditorButtonVisible("italic"));
5783                 browser.hlineAction.setVisible(Global.isEditorButtonVisible("hline"));
5784                 browser.indentAction.setVisible(Global.isEditorButtonVisible("indent"));
5785                 browser.outdentAction.setVisible(Global.isEditorButtonVisible("outdent"));
5786                 browser.bulletListAction.setVisible(Global.isEditorButtonVisible("bulletList"));
5787                 browser.numberListAction.setVisible(Global.isEditorButtonVisible("numberList"));
5788                 browser.fontListAction.setVisible(Global.isEditorButtonVisible("font"));
5789                 browser.fontSizeAction.setVisible(Global.isEditorButtonVisible("fontSize"));
5790                 browser.fontColorAction.setVisible(Global.isEditorButtonVisible("fontColor"));
5791                 browser.fontHilightAction.setVisible(Global.isEditorButtonVisible("fontHilight"));
5792                 browser.leftAlignAction.setVisible(Global.isEditorButtonVisible("alignLeft"));
5793                 browser.centerAlignAction.setVisible(Global.isEditorButtonVisible("alignCenter"));
5794                 browser.rightAlignAction.setVisible(Global.isEditorButtonVisible("alignRight"));
5795                 browser.spellCheckAction.setVisible(Global.isEditorButtonVisible("spellCheck"));
5796                 browser.todoAction.setVisible(Global.isEditorButtonVisible("todo"));
5797     }
5798     private void duplicateNote(String guid) {
5799                 
5800                 Note oldNote = conn.getNoteTable().getNote(guid, true, false,false,false,true);
5801                 List<Resource> resList = conn.getNoteTable().noteResourceTable.getNoteResources(guid, true);
5802                 oldNote.setContent(conn.getNoteTable().getNoteContentNoUTFConversion(guid));
5803                 oldNote.setResources(resList);
5804                 duplicateNote(oldNote);
5805         }
5806         private void duplicateNote(Note oldNote) {
5807                 waitCursor(true);
5808                 // Now that we have a good notebook guid, we need to move the conflicting note
5809                 // to the local notebook
5810                 Calendar currentTime = new GregorianCalendar();
5811                 Long l = new Long(currentTime.getTimeInMillis());
5812                 String newGuid = new String(Long.toString(l));
5813                                         
5814 //              Note newNote = oldNote.deepCopy();
5815                 Note newNote = (Note)Global.deepCopy(oldNote);
5816                 newNote.setUpdateSequenceNum(0);
5817                 newNote.setGuid(newGuid);
5818                 newNote.setDeleted(0);
5819                 newNote.setActive(true);
5820                 
5821                 /*
5822                 List<String> tagNames = new ArrayList<String>();
5823                 List<String> tagGuids = new ArrayList<String>();;
5824                 for (int i=0; i<oldNote.getTagGuidsSize(); i++) {
5825                         tagNames.add(oldNote.getTagNames().get(i));
5826                         tagGuids.add(oldNote.getTagGuids().get(i));
5827                 }
5828
5829                 // Sort note Tags to make them look nice
5830                 for (int i=0; i<tagNames.size()-1; i++) {
5831                         if (tagNames.get(i).compareTo(tagNames.get(i+1))<0) {
5832                                 String n1 = tagNames.get(i);
5833                                 String n2 = tagNames.get(i+1);
5834                                 tagNames.set(i, n2);
5835                                 tagNames.set(i+1, n1);
5836                         }
5837                 }
5838                 newNote.setTagGuids(tagGuids);
5839                 newNote.setTagNames(tagNames);
5840                 
5841                 // Add tag guids to note
5842                 */
5843                 
5844                 // Duplicate resources
5845                 List<Resource> resList = oldNote.getResources();
5846                 if (resList == null)
5847                         resList = new ArrayList<Resource>();
5848                 long prevGuid = 0;
5849                 for (int i=0; i<resList.size(); i++) {
5850                         l = prevGuid;
5851                         while (l == prevGuid) {
5852                                 currentTime = new GregorianCalendar();
5853                                 l = new Long(currentTime.getTimeInMillis());
5854                         }
5855                         prevGuid = l;
5856                         String newResGuid = new String(Long.toString(l));
5857                         resList.get(i).setNoteGuid(newGuid);
5858                         resList.get(i).setGuid(newResGuid);
5859                         resList.get(i).setUpdateSequenceNum(0);
5860                         resList.get(i).setActive(true);
5861                         conn.getNoteTable().noteResourceTable.saveNoteResource(
5862                                         (Resource)Global.deepCopy(resList.get(i)), true);
5863                 }
5864                 newNote.setResources(resList);
5865                 
5866                 // ICHANGED
5867                 // 操作履歴と除外ノートとスター付きノートも複製する
5868                 if(Global.getDuplicateRensoNote()) {
5869                         conn.getHistoryTable().duplicateHistory(newGuid, oldNote.getGuid());
5870                         conn.getExcludedTable().duplicateExcludedNotes(newGuid, oldNote.getGuid());
5871                         conn.getStaredTable().duplicateStaredNotes(newGuid, oldNote.getGuid());
5872                 }
5873                 
5874                 // Add note to the database
5875                 conn.getNoteTable().addNote(newNote, true);
5876                 NoteMetadata metaData = new NoteMetadata();
5877                 NoteMetadata oldMeta = listManager.getNoteMetadata().get(oldNote.getGuid());
5878                 metaData.copy(oldMeta);
5879                 metaData.setGuid(newNote.getGuid());
5880                 listManager.addNote(newNote, metaData);
5881                 noteTableView.insertRow(newNote, metaData, true, -1);
5882                 currentNoteGuid = newNote.getGuid();
5883                 currentNote = newNote;
5884                 refreshEvernoteNote(true);
5885                 listManager.countNotebookResults(listManager.getNoteIndex());
5886                 waitCursor(false);
5887                 
5888         }
5889         // View all notes
5890         @SuppressWarnings("unused")
5891         private void allNotes() {
5892                 clearAttributeFilter();
5893                 clearNotebookFilter();
5894                 clearSavedSearchFilter();
5895                 clearTrashFilter();
5896                 clearTagFilter();
5897                 searchField.clear();
5898                 if (Global.mimicEvernoteInterface) {
5899                         notebookTree.selectGuid("");
5900                 }
5901                 notebookTreeSelection();
5902                 refreshEvernoteNote(true);
5903                 
5904                 // ICHANGED ゴミ箱から元の画面に戻す。連想ノートリストをONに。
5905                 if (!rensoNoteListDock.isEnabled()) {
5906                         rensoNoteListDock.setEnabled(true);
5907                 }
5908         }
5909         // Merge notes
5910         @SuppressWarnings("unused")
5911         private void mergeNotes() {
5912                 logger.log(logger.HIGH, "Merging notes");
5913                 waitCursor(true);
5914                 saveNote();
5915                 String masterGuid = null;
5916                 List<String> sources = new ArrayList<String>();
5917                 QModelIndex index;
5918                 for (int i=0; i<noteTableView.selectionModel().selectedRows().size(); i++) {
5919                         int r = noteTableView.selectionModel().selectedRows().get(i).row();
5920                         index = noteTableView.proxyModel.index(r, Global.noteTableGuidPosition);
5921                         SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
5922                 if (i == 0) 
5923                         masterGuid = (String)ix.values().toArray()[0];
5924                 else 
5925                         sources.add((String)ix.values().toArray()[0]);  
5926                 }
5927                 
5928                 logger.log(logger.EXTREME, "Master guid=" +masterGuid);
5929                 logger.log(logger.EXTREME, "Children count: "+sources.size());
5930                 mergeNoteContents(masterGuid, sources);
5931                 currentNoteGuid = masterGuid;
5932                 
5933                 // ICHANGED 操作履歴と除外ノートとスター付きノートをマージ
5934                 if(Global.getMergeRensoNote()) {
5935                         for (int i = 0; i < sources.size(); i++) {
5936                                 String childGuid = sources.get(i);
5937                                 if(masterGuid != null && childGuid != null) {
5938                                         if(!masterGuid.equals(childGuid)) {
5939                                                 conn.getHistoryTable().mergeHistoryGuid(masterGuid, childGuid);
5940                                                 conn.getExcludedTable().mergeHistoryGuid(masterGuid, childGuid);
5941                                                 conn.getStaredTable().mergeHistoryGuid(masterGuid, childGuid);
5942                                         }
5943                                 }
5944                         }
5945                 }
5946                 
5947         // ICHANGED ↓↓↓ここから↓↓↓
5948                 // マージしたノート(child)を外部ウィンドウで開いていたら、閉じる
5949                 Collection<ExternalBrowse>      windows = externalWindows.values();
5950                 Iterator<ExternalBrowse>        windowIterator = windows.iterator();
5951                 Collection<String>                      guids = externalWindows.keySet();
5952                 Iterator<String>                        guidIterator = guids.iterator();
5953                 List<ExternalBrowse>            closeWindows = new ArrayList<ExternalBrowse>(); // イテレータ操作中に中身をいじっちゃダメなので
5954                 
5955                 while (windowIterator.hasNext()) {
5956                         ExternalBrowse browser = windowIterator.next();
5957                         String guid = guidIterator.next();
5958                         
5959                         for (int i = 0; i < sources.size(); i++) {
5960                                 if (guid.equals(sources.get(i))) {
5961                                         closeWindows.add(browser);
5962                                 }
5963                         }
5964                 }
5965                 
5966                 for (int i = closeWindows.size() - 1; i >= 0; i--) {
5967                         closeWindows.get(i).close();
5968                 }
5969                 // ICHANGED ↑↑↑ここまで↑↑↑
5970                 
5971         // ICHANGED ↓↓↓ここから↓↓↓
5972         // マージしたノート(child)をタブで開いていたら、閉じる
5973                 Collection<TabBrowse> tabBrowsers = tabWindows.values();
5974                 Iterator<TabBrowse> tabIterator = tabBrowsers.iterator();
5975                 Collection<Integer> tabIndexes = tabWindows.keySet();
5976                 Iterator<Integer>       indexIterator = tabIndexes.iterator();
5977                 List<Integer> closeIndexes = new ArrayList<Integer>();  //イテレータ操作中に中身をいじっちゃダメなので
5978
5979                 while (tabIterator.hasNext()) {
5980                         TabBrowse tab = tabIterator.next();
5981                         int tabIndex = indexIterator.next();
5982                         String guid = tab.getBrowserWindow().getNote().getGuid();
5983                         
5984                         for(int i = 0; i < sources.size(); i++){
5985                                 if(guid.equals(sources.get(i))){
5986                                         closeIndexes.add(tabIndex);
5987                                 }
5988                         }
5989                 }
5990                 
5991                 for(int i = closeIndexes.size() - 1; i >= 0; i--){
5992                         tabWindowClosing(closeIndexes.get(i));
5993                 }
5994                 // ICHANGED ↑↑↑ここまで↑↑↑              
5995                 
5996                 noteIndexUpdated(false);
5997                 // IFIXED 
5998                 // ICHANGED マージ後の新しいノートコンテンツを表示するためキャッシュを削除
5999                 noteCache.remove(masterGuid);
6000                 
6001                 refreshEvernoteNote(true);
6002                 waitCursor(false);
6003         }
6004         private void mergeNoteContents(String targetGuid, List<String> sources) {
6005                 Note target = conn.getNoteTable().getNote(targetGuid, true, false, false, false, false);
6006                 String newContent = target.getContent();
6007                 newContent = newContent.replace("</en-note>", "<br></br>");
6008                 
6009                 for (int i=0; i<sources.size(); i++) {
6010                         Note source = conn.getNoteTable().getNote(sources.get(i), true, true, false, false, false);
6011                         if (source.isSetTitle()) {
6012                                 newContent = newContent +("<table bgcolor=\"lightgrey\"><tr><td><font size=\"6\"><b>" +source.getTitle() +"</b></font></td></tr></table>");
6013                         }
6014                         String sourceContent = source.getContent();
6015                         logger.log(logger.EXTREME, "Merging contents into note");
6016                         logger.log(logger.EXTREME, sourceContent);
6017                         logger.log(logger.EXTREME, "End of content");
6018                         int startOfNote = sourceContent.indexOf("<en-note>");
6019                         sourceContent = sourceContent.substring(startOfNote+9);
6020                         int endOfNote = sourceContent.indexOf("</en-note>");
6021                         sourceContent = sourceContent.substring(0,endOfNote);
6022                         newContent = newContent + sourceContent;
6023                         logger.log(logger.EXTREME, "New note content");
6024                         logger.log(logger.EXTREME, newContent);
6025                         logger.log(logger.EXTREME, "End of content");
6026                         for (int j=0; j<source.getResourcesSize(); j++) {
6027                                 logger.log(logger.EXTREME, "Reassigning resource: "+source.getResources().get(j).getGuid());
6028                                 Resource r = source.getResources().get(j);
6029                                 Resource newRes = conn.getNoteTable().noteResourceTable.getNoteResource(r.getGuid(), true);
6030                                 
6031                                 Calendar currentTime = new GregorianCalendar();
6032                                 Long l = new Long(currentTime.getTimeInMillis());
6033                                                         
6034                                 long prevGuid = 0;
6035                                 l = prevGuid;
6036                                 while (l == prevGuid) {
6037                                         currentTime = new GregorianCalendar();
6038                                         l = new Long(currentTime.getTimeInMillis());
6039                                 }
6040                                 String newResGuid = new String(Long.toString(l));
6041                                 newRes.setNoteGuid(targetGuid);
6042                                 newRes.setGuid(newResGuid);
6043                                 newRes.setUpdateSequenceNum(0);
6044                                 newRes.setActive(true);
6045                                 conn.getNoteTable().noteResourceTable.saveNoteResource(newRes, true);
6046                         }
6047                 }
6048                 logger.log(logger.EXTREME, "Updating note");
6049                 conn.getNoteTable().updateNoteContent(targetGuid, newContent +"</en-note>");
6050                 for (int i=0; i<sources.size(); i++) {
6051                         logger.log(logger.EXTREME, "Deleting note " +sources.get(i));
6052                         listManager.deleteNote(sources.get(i));
6053                 }
6054                 logger.log(logger.EXTREME, "Exiting merge note");
6055         }
6056         // A resource within a note has had a guid change 
6057         @SuppressWarnings("unused")
6058         private void noteResourceGuidChanged(String noteGuid, String oldGuid, String newGuid) {
6059                 if (oldGuid != null && !oldGuid.equals(newGuid))
6060                         Global.resourceMap.put(oldGuid, newGuid);
6061         }
6062         // View a thumbnail of the note
6063         public void thumbnailView() {
6064                 
6065                 String thumbnailName = Global.getFileManager().getResDirPath("thumbnail-" + currentNoteGuid + ".png");
6066                 QFile thumbnail = new QFile(thumbnailName);
6067                 if (!thumbnail.exists()) {
6068                         
6069                         QImage img = new QImage();
6070                         img.loadFromData(conn.getNoteTable().getThumbnail(currentNoteGuid));
6071                         thumbnailViewer.setThumbnail(img);
6072                 } else
6073                         thumbnailViewer.setThumbnail(thumbnailName);
6074                 if (!thumbnailViewer.isVisible()) 
6075                         thumbnailViewer.showFullScreen();
6076         }
6077         // An error happened while saving a note.  Inform the user
6078         @SuppressWarnings("unused")
6079         private void saveRunnerError(String guid, String msg) {
6080                 if (msg == null) {
6081                         String title = "*Unknown*";
6082                         for (int i=0; i<listManager.getMasterNoteIndex().size(); i++) {
6083                                 if (listManager.getMasterNoteIndex().get(i).getGuid().equals(guid)) {
6084                                         title = listManager.getMasterNoteIndex().get(i).getTitle();
6085                                         i=listManager.getMasterNoteIndex().size();
6086                                 }
6087                         }
6088                         msg = tr("An error has happened while saving the note \"") +title+
6089                         tr("\".\n\nThis is probably due to a document that is too complex for NeighborNote to process.  "+
6090                         "As a result, changes to the note may not be saved properly in the database."+
6091                         "\n\nA cached copy is being preserved so you can recover any data, but data may" +
6092                         "\nbe lost.  Please review the note to recover any critical data before restarting.");
6093                         
6094                         QMessageBox.information(this, tr("Error Saving Note"), tr(msg));
6095                 }
6096         }
6097         private void thumbnailHTMLReady(String guid, QByteArray html, Integer zoom) {
6098                 logger.log(logger.HIGH, "Entering thumnailHTMLReady()");
6099                 logger.log(logger.HIGH, "Thumbnail ready for " +guid);
6100                 // Find an idle preview object
6101                 for (int i=0; i<thumbGenerators.size(); i++) {
6102                         if (thumbGenerators.get(i).mutex.tryLock()) {
6103                                 logger.log(logger.EXTREME, "Idle generator found - loading thumbnail for " +guid);
6104                                 thumbGenerators.get(i).loadContent(guid, html, zoom);
6105                                 return;
6106                         }
6107                 } 
6108                 if (thumbGenerators.size() >= 1) {
6109                         logger.log(logger.EXTREME, "No available thumbnail generators.  Aborting " +guid);
6110                         return;
6111                 }
6112                 
6113                 logger.log(logger.EXTREME, "Creating new thumbnail generator " +guid);
6114                 Thumbnailer preview = new Thumbnailer(logger, conn, listManager, thumbnailRunner);
6115                 thumbGenerators.add(preview);
6116
6117                 if (preview.mutex.tryLock()) {
6118                         logger.log(logger.EXTREME, "Loading thumbnail for  " +guid);
6119                         preview.loadContent(guid, html, zoom);
6120                 }
6121                 logger.log(logger.HIGH, "Exiting thumnailHTMLReady()");
6122         }
6123         
6124         
6125         
6126         //**********************************************************
6127     //**********************************************************
6128     //* Online user actions
6129     //**********************************************************
6130     //**********************************************************
6131     private void setupOnlineMenu() {
6132         if (!Global.isConnected) {
6133                 menuBar.noteOnlineHistoryAction.setEnabled(false);
6134                 menuBar.selectiveSyncAction.setEnabled(false);
6135                 return;
6136         } else {
6137                 menuBar.noteOnlineHistoryAction.setEnabled(true);
6138                 menuBar.selectiveSyncAction.setEnabled(true);
6139         }
6140     }
6141     @SuppressWarnings("unused")
6142         private void viewNoteHistory() {
6143         if (currentNoteGuid == null || currentNoteGuid.equals("")) 
6144                 return;
6145         if (currentNote.getUpdateSequenceNum() == 0) {
6146                 setMessage(tr("Note has never been synchronized."));
6147                         QMessageBox.information(this, tr("Error"), tr("This note has never been sent to Evernote, so there is no history."));
6148                         return;
6149         }
6150         
6151         setMessage(tr("Getting Note History"));
6152         waitCursor(true);
6153         Note currentOnlineNote = null;
6154         versions = null;
6155         try {
6156                 if (Global.isPremium())
6157                         versions = syncRunner.localNoteStore.listNoteVersions(syncRunner.authToken, currentNoteGuid);
6158                 else
6159                         versions = new ArrayList<NoteVersionId>();
6160                 currentOnlineNote = syncRunner.localNoteStore.getNote(syncRunner.authToken, currentNoteGuid, true, true, false, false);
6161                 } catch (EDAMUserException e) {
6162                         setMessage("EDAMUserException: " +e.getMessage());
6163                         return;
6164                 } catch (EDAMSystemException e) {
6165                         setMessage("EDAMSystemException: " +e.getMessage());
6166                         return;
6167                 } catch (EDAMNotFoundException e) {
6168                         setMessage(tr("Note not found on server."));
6169                         QMessageBox.information(this, tr("Error"), tr("This note could not be found on Evernote's servers."));
6170                         return;
6171                 } catch (TException e) {
6172                         setMessage("EDAMTransactionException: " +e.getMessage());
6173                         return;
6174                 }
6175                 
6176                 // If we've gotten this far, we have a good note.
6177                 if (historyWindow == null) {
6178                         // ICHANGED
6179                         historyWindow = new OnlineNoteHistory(logger, conn, cbObserver);
6180                         
6181                         historyWindow.historyCombo.activated.connect(this, "reloadHistoryWindow(String)");
6182                         historyWindow.restoreAsNew.clicked.connect(this, "restoreHistoryNoteAsNew()");
6183                         historyWindow.restore.clicked.connect(this, "restoreHistoryNote()");
6184                 } else {
6185                         historyWindow.historyCombo.clear();
6186                 }
6187                 boolean isDirty = conn.getNoteTable().isNoteDirty(currentNoteGuid);
6188                 if (currentNote.getUpdateSequenceNum() != currentOnlineNote.getUpdateSequenceNum())
6189                         isDirty = true;
6190                 historyWindow.setCurrent(isDirty);
6191                 
6192                 loadHistoryWindowContent(currentOnlineNote);
6193                 historyWindow.load(versions);
6194                 setMessage(tr("History retrieved"));
6195                 waitCursor(false);
6196                 historyWindow.exec();
6197     }
6198     private Note reloadHistoryWindow(String selection) {
6199         waitCursor(true);
6200                 String fmt = Global.getDateFormat() + " " + Global.getTimeFormat();
6201                 String dateTimeFormat = new String(fmt);
6202                 SimpleDateFormat simple = new SimpleDateFormat(dateTimeFormat);
6203                 int index = -1;
6204                 int usn = 0;
6205                 
6206                 for (int i=0; i<versions.size(); i++) {
6207                         StringBuilder versionDate = new StringBuilder(simple.format(versions.get(i).getSaved()));
6208                         if (versionDate.toString().equals(selection))
6209                                 index = i;
6210                 }
6211                 
6212                 if (index > -1 || selection.indexOf("Current") > -1) {
6213                         Note historyNote = null;
6214                         try {
6215                                 if (index > -1) {
6216                                         usn = versions.get(index).getUpdateSequenceNum();
6217                                         historyNote = syncRunner.localNoteStore.getNoteVersion(syncRunner.authToken, currentNoteGuid, usn, true, true, true);
6218                                 } else
6219                                         historyNote = syncRunner.localNoteStore.getNote(syncRunner.authToken, currentNoteGuid, true,true,true,true);
6220                         } catch (EDAMUserException e) {
6221                                 setMessage("EDAMUserException: " +e.getMessage());
6222                                 waitCursor(false);
6223                                 return null;
6224                         } catch (EDAMSystemException e) {
6225                                 setMessage("EDAMSystemException: " +e.getMessage());
6226                                 waitCursor(false);
6227                                 return null;
6228                         } catch (EDAMNotFoundException e) {
6229                                 setMessage("EDAMNotFoundException: " +e.getMessage());
6230                                 waitCursor(false);
6231                                 return null;
6232                         } catch (TException e) {
6233                                 setMessage("EDAMTransactionException: " +e.getMessage());
6234                                 waitCursor(false);
6235                                 return null;
6236                         }
6237                         
6238                         waitCursor(false);
6239                         if (historyNote != null) 
6240                                 historyWindow.setContent(historyNote);
6241                         return historyNote;
6242                 }
6243                 waitCursor(false);
6244                 return null;
6245     }
6246     private void loadHistoryWindowContent(Note note) {
6247         note.setUpdateSequenceNum(0);
6248                 historyWindow.setContent(note); 
6249     }
6250     @SuppressWarnings("unused")
6251         private void restoreHistoryNoteAsNew() {
6252         setMessage(tr("Restoring as new note."));
6253         duplicateNote(reloadHistoryWindow(historyWindow.historyCombo.currentText()));
6254         setMessage(tr("Note has been restored as a new note."));
6255     }
6256     @SuppressWarnings("unused")
6257         private void restoreHistoryNote() {
6258         setMessage(tr("Restoring note."));
6259         Note n = reloadHistoryWindow(historyWindow.historyCombo.currentText());
6260         conn.getNoteTable().expungeNote(n.getGuid(), true, false);
6261         n.setActive(true);
6262         n.setDeleted(0);
6263                 for (int i=0; i<n.getResourcesSize(); i++) {
6264                         n.getResources().get(i).setActive(true);
6265                         conn.getNoteTable().noteResourceTable.saveNoteResource(n.getResources().get(i), true);
6266                 }
6267                 NoteMetadata metadata = new NoteMetadata();
6268                 metadata.setGuid(n.getGuid());
6269         listManager.addNote(n, metadata);
6270         conn.getNoteTable().addNote(n, true);
6271         refreshEvernoteNote(true);
6272         setMessage(tr("Note has been restored."));
6273     }
6274     @SuppressWarnings("unused")
6275         private void setupSelectiveSync() {
6276         
6277         // Get a list of valid notebooks
6278         List<Notebook> notebooks = null; 
6279         List<Tag> tags = null;
6280         List<LinkedNotebook> linkedNotebooks = null;
6281         try {
6282                         notebooks = syncRunner.localNoteStore.listNotebooks(syncRunner.authToken);
6283                         tags = syncRunner.localNoteStore.listTags(syncRunner.authToken);
6284                         linkedNotebooks = syncRunner.localNoteStore.listLinkedNotebooks(syncRunner.authToken);
6285                 } catch (EDAMUserException e) {
6286                         setMessage("EDAMUserException: " +e.getMessage());
6287                         return;
6288                 } catch (EDAMSystemException e) {
6289                         setMessage("EDAMSystemException: " +e.getMessage());
6290                         return;
6291                 } catch (TException e) {
6292                         setMessage("EDAMTransactionException: " +e.getMessage());
6293                         return;
6294                 } catch (EDAMNotFoundException e) {
6295                         setMessage("EDAMNotFoundException: " +e.getMessage());
6296                         return;
6297                 }
6298         
6299                 // Split up notebooks into synchronized & non-synchronized
6300         List<Notebook> ignoredBooks = new ArrayList<Notebook>();
6301         List<String> dbIgnoredNotebooks = conn.getSyncTable().getIgnoreRecords("NOTEBOOK");
6302         
6303         for (int i=notebooks.size()-1; i>=0; i--) {
6304                 for (int j=0; j<dbIgnoredNotebooks.size(); j++) {
6305                         if (notebooks.get(i).getGuid().equalsIgnoreCase(dbIgnoredNotebooks.get(j))) {
6306                                 ignoredBooks.add(notebooks.get(i));
6307                                 j=dbIgnoredNotebooks.size();
6308                         }
6309                 }
6310         }
6311         
6312         // split up tags into synchronized & non-synchronized
6313         List<Tag> ignoredTags = new ArrayList<Tag>();
6314         List<String> dbIgnoredTags = conn.getSyncTable().getIgnoreRecords("TAG");
6315         
6316         for (int i=tags.size()-1; i>=0; i--) {
6317                 for (int j=0; j<dbIgnoredTags.size(); j++) {
6318                         if (tags.get(i).getGuid().equalsIgnoreCase(dbIgnoredTags.get(j))) {
6319                                 ignoredTags.add(tags.get(i));
6320                                 j=dbIgnoredTags.size();
6321                         }
6322                 }
6323         }
6324         
6325         // split up linked notebooks into synchronized & non-synchronized
6326         List<LinkedNotebook> ignoredLinkedNotebooks = new ArrayList<LinkedNotebook>();
6327         List<String> dbIgnoredLinkedNotebooks = conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK");
6328         for (int i=linkedNotebooks.size()-1; i>=0; i--) {
6329                 String notebookGuid = linkedNotebooks.get(i).getGuid();
6330                 for (int j=0; j<dbIgnoredLinkedNotebooks.size(); j++) {
6331                         if (notebookGuid.equalsIgnoreCase(dbIgnoredLinkedNotebooks.get(j))) {
6332                                 ignoredLinkedNotebooks.add(linkedNotebooks.get(i));
6333                                 j=dbIgnoredLinkedNotebooks.size();
6334                         }
6335                 }
6336         }
6337         
6338                 IgnoreSync ignore = new IgnoreSync(notebooks, ignoredBooks, tags, ignoredTags, linkedNotebooks, ignoredLinkedNotebooks);
6339                 ignore.exec();
6340                 if (!ignore.okClicked())
6341                         return;
6342                 
6343                 waitCursor(true);
6344                 
6345                 // Clear out old notebooks & add  the new ones
6346                 List<String> oldIgnoreNotebooks = conn.getSyncTable().getIgnoreRecords("NOTEBOOK");
6347                 for (int i=0; i<oldIgnoreNotebooks.size(); i++) {
6348                         conn.getSyncTable().deleteRecord("IGNORENOTEBOOK-"+oldIgnoreNotebooks.get(i));
6349                 }
6350                 
6351                 List<String> newNotebooks = new ArrayList<String>();
6352                 for (int i=ignore.getIgnoredBookList().count()-1; i>=0; i--) {
6353                         String text = ignore.getIgnoredBookList().takeItem(i).text();
6354                         for (int j=0; j<notebooks.size(); j++) {
6355                                 if (notebooks.get(j).getName().equalsIgnoreCase(text)) {
6356                                         Notebook n = notebooks.get(j);
6357                                         conn.getSyncTable().addRecord("IGNORENOTEBOOK-"+n.getGuid(), n.getGuid());
6358                                         j=notebooks.size();
6359                                         newNotebooks.add(n.getGuid());
6360                                 }
6361                         }
6362                 }
6363                 
6364                 // Clear out old tags & add new ones
6365                 List<String> oldIgnoreTags = conn.getSyncTable().getIgnoreRecords("TAG");
6366                 for (int i=0; i<oldIgnoreTags.size(); i++) {
6367                         conn.getSyncTable().deleteRecord("IGNORETAG-"+oldIgnoreTags.get(i));
6368                 }
6369                 
6370                 List<String> newTags = new ArrayList<String>();
6371                 for (int i=ignore.getIgnoredTagList().count()-1; i>=0; i--) {
6372                         String text = ignore.getIgnoredTagList().takeItem(i).text();
6373                         for (int j=0; j<tags.size(); j++) {
6374                                 if (tags.get(j).getName().equalsIgnoreCase(text)) {
6375                                         Tag t = tags.get(j);
6376                                         conn.getSyncTable().addRecord("IGNORETAG-"+t.getGuid(), t.getGuid());
6377                                         newTags.add(t.getGuid());
6378                                         j=tags.size();
6379                                 }
6380                         }
6381                 }
6382                 
6383                 // Clear out old tags & add new ones
6384                 List<String> oldIgnoreLinkedNotebooks = conn.getSyncTable().getIgnoreRecords("LINKEDNOTEBOOK");
6385                 for (int i=0; i<oldIgnoreLinkedNotebooks.size(); i++) {
6386                         conn.getSyncTable().deleteRecord("IGNORELINKEDNOTEBOOK-"+oldIgnoreLinkedNotebooks.get(i));
6387                 }
6388                 
6389                 List<String> newLinked = new ArrayList<String>();
6390                 for (int i=ignore.getIgnoredLinkedNotebookList().count()-1; i>=0; i--) {
6391                         String text = ignore.getIgnoredLinkedNotebookList().takeItem(i).text();
6392                         for (int j=0; j<linkedNotebooks.size(); j++) {
6393                                 if (linkedNotebooks.get(j).getShareName().equalsIgnoreCase(text)) {
6394                                         LinkedNotebook t = linkedNotebooks.get(j);
6395                                         conn.getSyncTable().addRecord("IGNORELINKEDNOTEBOOK-"+t.getGuid(), t.getGuid());
6396                                         newLinked.add(t.getGuid());
6397                                         j=linkedNotebooks.size();
6398                                 }
6399                         }
6400                 }
6401                 
6402                 conn.getNoteTable().expungeIgnoreSynchronizedNotes(newNotebooks, newTags, newLinked);
6403                 waitCursor(false);
6404                 refreshLists();
6405     }
6406     
6407     
6408         //**********************************************************
6409         //**********************************************************
6410         //* XML Modifying methods
6411         //**********************************************************
6412         //**********************************************************
6413         // An error has happended fetching a resource.  let the user know
6414     // ICHANGED
6415         private void resourceErrorMessage(int tabIndex) {
6416                 if (tabIndex < 0) {
6417                         return;
6418                 }
6419                 if (inkNote.get(tabIndex))
6420                         return;
6421                 waitCursor(false);
6422                 QMessageBox.information(this, tr("DOUGH!!!"), tr("Well, this is embarrassing."+
6423                 "\n\nSome attachments or images for this note appear to be missing from my database.\n"+
6424                 "In a perfect world this wouldn't happen, but it has.\n" +
6425                 "It is embarasing when a program like me, designed to save all your\n"+
6426                 "precious data, has a problem finding data.\n\n" +
6427                 "I guess life isn't fair, but I'll survive.  Somehow...\n\n" +
6428                 "In the mean time, I'm not going to let you make changes to this note.\n" +
6429                 "Don't get angry.  I'm doing it to prevent you from messing up\n"+
6430                 "this note on the Evernote servers.  Sorry."+
6431                 "\n\nP.S. You might want to re-synchronize to see if it corrects this problem.\nWho knows, you might get lucky."));
6432                 inkNote.put(tabIndex, true);
6433                 browserWindow.setReadOnly(true);
6434                 waitCursor(true);
6435         }
6436
6437         
6438         
6439         
6440         //**********************************************************
6441         //**********************************************************
6442         //* Timer functions
6443         //**********************************************************
6444         //**********************************************************
6445         // We should now do a sync with Evernote
6446         private void syncTimer() {
6447                 logger.log(logger.EXTREME, "Entering NeverNote.syncTimer()");
6448                 syncRunner.syncNeeded = true;
6449                 syncRunner.disableUploads = Global.disableUploads;
6450                 syncStart();
6451                 logger.log(logger.EXTREME, "Leaving NeverNote.syncTimer()");
6452         }
6453         private void syncStart() {
6454                 logger.log(logger.EXTREME, "Entering NeverNote.syncStart()");
6455                 saveNote();
6456                 if (!syncRunning && Global.isConnected) {
6457                         syncRunner.setConnected(true);
6458                         syncRunner.setKeepRunning(Global.keepRunning);
6459                         syncRunner.syncDeletedContent = Global.synchronizeDeletedContent();
6460                         
6461                         if (syncThreadsReady > 0) {
6462                                 thumbnailRunner.interrupt = true;
6463                                 saveNoteIndexWidth();
6464                                 saveNoteColumnPositions();
6465                                 if (syncRunner.addWork("SYNC")) {
6466                                         syncRunning = true;
6467                                         syncRunner.syncNeeded = true;
6468                                         syncThreadsReady--;
6469                                 }                               
6470                         }
6471                 }
6472                 logger.log(logger.EXTREME, "Leaving NeverNote.syncStart");
6473         }
6474         @SuppressWarnings("unused")
6475         private void syncThreadComplete(Boolean refreshNeeded) {
6476                 setMessage(tr("Finalizing Synchronization"));
6477                 syncThreadsReady++;
6478                 syncRunning = false;
6479                 syncRunner.syncNeeded = false;
6480                 synchronizeAnimationTimer.stop();
6481                 synchronizeButton.setIcon(new QIcon(iconPath+"synchronize.png"));
6482                 saveNote();
6483                 if (currentNote == null) {
6484                         currentNote = conn.getNoteTable().getNote(currentNoteGuid, false, false, false, false, true);
6485                 }
6486                 listManager.refreshNoteMetadata();
6487                 noteIndexUpdated(true);
6488                 noteTableView.selectionModel().blockSignals(true);
6489                 scrollToGuid(currentNoteGuid);
6490                 noteTableView.selectionModel().blockSignals(false);
6491                 refreshEvernoteNote(false);
6492                 scrollToGuid(currentNoteGuid);
6493                 waitCursor(false);
6494                 
6495                 // Check to see if there were any shared notebook errors
6496                 if (syncRunner.error && syncRunner.errorSharedNotebooks.size() > 0) {
6497                         String guid = syncRunner.errorSharedNotebooks.get(0);
6498                         String notebookGuid = conn.getLinkedNotebookTable().getLocalNotebookGuid(guid);
6499                         String localName = listManager.getNotebookNameByGuid(notebookGuid);
6500                         SharedNotebookSyncError syncDialog = new SharedNotebookSyncError(localName);
6501                         syncDialog.exec();
6502                         if (syncDialog.okPressed()) {
6503                                 if (syncDialog.doNothing.isChecked()) {
6504                                         syncRunner.errorSharedNotebooksIgnored.put(guid, guid);
6505                                         evernoteSync();
6506                                 }
6507                                 if (syncDialog.deleteNotebook.isChecked()) {
6508                                         conn.getNoteTable().expungeNotesByNotebook(notebookGuid, true, false);
6509                                         conn.getNotebookTable().expungeNotebook(notebookGuid, false);
6510                                         conn.getLinkedNotebookTable().expungeNotebook(guid, false);
6511                                         conn.getLinkedNotebookTable().expungeNotebook(guid, false);
6512                                         evernoteSync();
6513                                 }
6514                                 refreshLists();
6515                                 return;
6516                         }
6517                 }
6518                 
6519                 // Finalize the synchronization
6520                 if (!syncRunner.error)
6521                         setMessage(tr("Synchronization Complete"));
6522                 else
6523                         setMessage(tr("Synchronization completed with errors.  Please check the log for details."));
6524                 logger.log(logger.MEDIUM, "Sync complete.");
6525         }   
6526         public void saveUploadAmount(long t) {
6527                 Global.saveUploadAmount(t);
6528         }
6529         public void saveUserInformation(User user) {
6530                 Global.saveUserInformation(user);
6531         }
6532         public void saveEvernoteUpdateCount(int i) {
6533                 Global.saveEvernoteUpdateCount(i);
6534         }
6535         public void refreshLists() {
6536                 logger.log(logger.EXTREME, "Entering NeverNote.refreshLists");
6537                 updateQuotaBar();
6538                 // ICHANGED
6539                 // すべてのタブのノートを調べて、Dirtyならばセーブする。その後refreshListsする。
6540                 Collection<Integer> tabIndex = noteDirty.keySet();
6541                 Iterator<Integer> indexIterator = tabIndex.iterator();
6542                 HashMap<Integer, Note> saveNotes = new HashMap<Integer, Note>();
6543                 HashMap<Integer, String> saveContents = new HashMap<Integer, String>();
6544                 for (boolean isNoteDirty: noteDirty.values()) {
6545                         int index = indexIterator.next();
6546                         if (isNoteDirty) {
6547                                 saveNotes.put(index, tabWindows.get(index).getBrowserWindow().getNote());
6548                                 saveContents.put(index, tabWindows.get(index).getBrowserWindow().getContent());
6549                         }
6550                 }
6551                 
6552                 listManager.saveUpdatedNotes(saveNotes, saveContents);
6553                 listManager.refreshLists();
6554
6555                 tagIndexUpdated(true);
6556                 notebookIndexUpdated();
6557                 savedSearchIndexUpdated();
6558                 listManager.loadNotesIndex();
6559
6560                 noteTableView.selectionModel().blockSignals(true);
6561         noteIndexUpdated(true);
6562                 noteTableView.selectionModel().blockSignals(false);
6563                 logger.log(logger.EXTREME, "Leaving NeverNote.refreshLists");
6564         }
6565
6566         
6567         @SuppressWarnings("unused")
6568         private void authTimer() {
6569         Calendar cal = Calendar.getInstance();
6570                 
6571         // If we are not connected let's get out of here
6572         if (!Global.isConnected)
6573                 return;
6574                 
6575                 // If this is the first time through, then we need to set this
6576  //             if (syncRunner.authRefreshTime == 0 || cal.getTimeInMillis() > syncRunner.authRefreshTime) 
6577 //                      syncRunner.authRefreshTime = cal.getTimeInMillis();
6578                 
6579 //              long now = new Date().getTime();
6580 //              if (now > Global.authRefreshTime && Global.isConnected) {
6581                         syncRunner.authRefreshNeeded = true;
6582                         syncStart();
6583 //              }
6584         }
6585         @SuppressWarnings("unused")
6586         private void authRefreshComplete(boolean goodSync) {
6587                 logger.log(logger.EXTREME, "Entering NeverNote.authRefreshComplete");
6588                 Global.isConnected = syncRunner.isConnected;
6589                 if (goodSync) {
6590 //                      authTimer.start((int)syncRunner.authTimeRemaining/4);
6591                         authTimer.start(1000*60*15);
6592                         logger.log(logger.LOW, "Authentication token has been renewed");
6593 //                      setMessage("Authentication token has been renewed.");
6594                 } else {
6595                         authTimer.start(1000*60*5);
6596                         logger.log(logger.LOW, "Authentication token renew has failed - retry in 5 minutes.");
6597 //                      setMessage("Authentication token renew has failed - retry in 5 minutes.");
6598                 }
6599                 logger.log(logger.EXTREME, "Leaving NeverNote.authRefreshComplete");
6600         }
6601         
6602         
6603         @SuppressWarnings("unused")
6604         private synchronized void indexTimer() {
6605                 logger.log(logger.EXTREME, "Index timer activated.  Sync running="+syncRunning);
6606                 if (syncRunning) 
6607                         return;
6608                 if (!indexDisabled && indexRunner.idle) { 
6609                         thumbnailRunner.interrupt = true;
6610                         indexRunner.addWork("SCAN");
6611                 }
6612                 logger.log(logger.EXTREME, "Leaving NeighborNote index timer");
6613         }
6614
6615         @SuppressWarnings("unused")
6616         private void indexStarted() {
6617                 setMessage(tr("Indexing notes"));
6618         }
6619         @SuppressWarnings("unused")
6620         private void indexComplete() {
6621                 setMessage(tr("Index complete"));
6622         }
6623         @SuppressWarnings("unused")
6624         private synchronized void toggleNoteIndexing() {
6625                 logger.log(logger.HIGH, "Entering NeverNote.toggleIndexing");
6626                 indexDisabled = !indexDisabled;
6627                 if (!indexDisabled)
6628                         setMessage(tr("Indexing is now enabled."));
6629                 else
6630                         setMessage(tr("Indexing is now disabled."));
6631                 menuBar.disableIndexing.setChecked(indexDisabled);
6632         logger.log(logger.HIGH, "Leaving NeverNote.toggleIndexing");
6633     }  
6634         
6635         @SuppressWarnings("unused")
6636         private void threadMonitorCheck() {
6637                 int MAX=3;
6638                 
6639                 
6640                 boolean alive;
6641                 alive = listManager.threadCheck(Global.tagCounterThreadId);
6642                 if (!alive) {
6643                         tagDeadCount++;
6644                         if (tagDeadCount > MAX && !disableTagThreadCheck) {
6645                                 QMessageBox.information(this, tr("A thread has died."), tr("It appears as the tag counter thread has died.  I recommend "+
6646                                 "checking stopping NeighborNote, saving the logs for later viewing, and restarting.  Sorry."));
6647                                 disableTagThreadCheck = true;
6648                         }
6649                 } else
6650                         tagDeadCount=0;
6651                 
6652                 alive = listManager.threadCheck(Global.notebookCounterThreadId);
6653                 if (!alive) {
6654                         notebookThreadDeadCount++;
6655                         if (notebookThreadDeadCount > MAX && !disableNotebookThreadCheck) {
6656                                 QMessageBox.information(this, tr("A thread has died."), tr("It appears as the notebook counter thread has died.  I recommend "+
6657                                         "checking stopping NeighborNote, saving the logs for later viewing, and restarting.  Sorry."));
6658                                 disableNotebookThreadCheck=true;
6659                         }
6660                 } else
6661                         notebookThreadDeadCount=0;
6662                 
6663                 alive = listManager.threadCheck(Global.trashCounterThreadId);
6664                 if (!alive) {
6665                         trashDeadCount++;
6666                         if (trashDeadCount > MAX && !disableTrashThreadCheck) {
6667                                 QMessageBox.information(this, tr("A thread has died."), ("It appears as the trash counter thread has died.  I recommend "+
6668                                         "checking stopping NeighborNote, saving the logs for later viewing, and restarting.  Sorry."));
6669                                 disableTrashThreadCheck = true;
6670                         }
6671                 } else
6672                         trashDeadCount = 0;
6673
6674                 alive = listManager.threadCheck(Global.saveThreadId);
6675                 if (!alive) {
6676                         saveThreadDeadCount++;
6677                         if (saveThreadDeadCount > MAX && !disableSaveThreadCheck) {
6678                                 QMessageBox.information(this, tr("A thread has died."), tr("It appears as the note saver thread has died.  I recommend "+
6679                                         "checking stopping NeighborNote, saving the logs for later viewing, and restarting.  Sorry."));
6680                                 disableSaveThreadCheck = true;
6681                         }
6682                 } else
6683                         saveThreadDeadCount=0;
6684
6685                 if (!syncThread.isAlive()) {
6686                         syncThreadDeadCount++;
6687                         if (syncThreadDeadCount > MAX && !disableSyncThreadCheck) {
6688                                 QMessageBox.information(this, tr("A thread has died."), tr("It appears as the synchronization thread has died.  I recommend "+
6689                                         "checking stopping NeighborNote, saving the logs for later viewing, and restarting.  Sorry."));
6690                                 disableSyncThreadCheck = true;
6691                         }
6692                 } else
6693                         syncThreadDeadCount=0;
6694
6695                 if (!indexThread.isAlive()) {
6696                         indexThreadDeadCount++;
6697                         if (indexThreadDeadCount > MAX && !disableIndexThreadCheck) {
6698                                 QMessageBox.information(this, tr("A thread has died."), tr("It appears as the index thread has died.  I recommend "+
6699                                         "checking stopping NeighborNote, saving the logs for later viewing, and restarting.  Sorry."));
6700                                 disableIndexThreadCheck = true;
6701                         }
6702                 } else
6703                         indexThreadDeadCount=0;
6704
6705                 
6706         }
6707
6708         private void thumbnailTimer() {
6709                 if (Global.enableThumbnails() && !syncRunning && indexRunner.idle) {
6710                         thumbnailRunner.addWork("SCAN");
6711                 }
6712         }
6713         
6714         //**************************************************
6715         //* Backup & Restore
6716         //**************************************************
6717         @SuppressWarnings("unused")
6718         private void databaseBackup() {
6719                 QFileDialog fd = new QFileDialog(this);
6720                 fd.setFileMode(FileMode.AnyFile);
6721                 fd.setConfirmOverwrite(true);
6722                 fd.setWindowTitle(tr("Backup Database"));
6723                 fd.setFilter(tr("NixNote Export (*.nnex);;All Files (*.*)"));
6724                 fd.setAcceptMode(AcceptMode.AcceptSave);
6725                 if (saveLastPath == null || saveLastPath.equals(""))
6726                         fd.setDirectory(System.getProperty("user.home"));
6727                 else
6728                         fd.setDirectory(saveLastPath);
6729                 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
6730                         return;
6731                 }
6732                 
6733                 
6734         waitCursor(true);
6735         saveLastPath = fd.selectedFiles().get(0);
6736         saveLastPath = saveLastPath.substring(0,saveLastPath.lastIndexOf("/"));
6737         setMessage(tr("Backing up database"));
6738         saveNote();
6739 //      conn.backupDatabase(Global.getUpdateSequenceNumber(), Global.getSequenceDate());
6740         
6741         ExportData noteWriter = new ExportData(conn, true);
6742         String fileName = fd.selectedFiles().get(0);
6743
6744         if (!fileName.endsWith(".nnex"))
6745                 fileName = fileName +".nnex";
6746         noteWriter.exportData(fileName);
6747         setMessage(tr("Database backup completed."));
6748  
6749
6750         waitCursor(false);
6751         }
6752         @SuppressWarnings("unused")
6753         private void databaseRestore() {
6754                 if (QMessageBox.question(this, tr("Confirmation"),
6755                                 tr("This is used to restore a database from backups.\n" +
6756                                 "It is HIGHLY recommened that this only be used to populate\n" +
6757                                 "an empty database.  Restoring into a database that\n already has data" +
6758                                 " can cause problems.\n\nAre you sure you want to continue?"),
6759                                 QMessageBox.StandardButton.Yes, 
6760                                 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
6761                                         return;
6762                                 }
6763                 
6764                 
6765                 QFileDialog fd = new QFileDialog(this);
6766                 fd.setFileMode(FileMode.ExistingFile);
6767                 fd.setConfirmOverwrite(true);
6768                 fd.setWindowTitle(tr("Restore Database"));
6769                 fd.setFilter(tr("NixNote Export (*.nnex);;All Files (*.*)"));
6770                 fd.setAcceptMode(AcceptMode.AcceptOpen);
6771                 if (saveLastPath == null || saveLastPath.equals(""))
6772                         fd.setDirectory(System.getProperty("user.home"));
6773                 else
6774                         fd.setDirectory(saveLastPath);
6775                 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
6776                         return;
6777                 }
6778                 
6779                 
6780                 waitCursor(true);
6781         saveLastPath = fd.selectedFiles().get(0);
6782         saveLastPath = saveLastPath.substring(0,saveLastPath.lastIndexOf("/"));
6783
6784                 setMessage(tr("Restoring database"));
6785         ImportData noteReader = new ImportData(conn, true);
6786         noteReader.importData(fd.selectedFiles().get(0));
6787         
6788         if (noteReader.lastError != 0) {
6789                 setMessage(noteReader.getErrorMessage());
6790                 logger.log(logger.LOW, "Restore problem: " +noteReader.lastError);
6791                 waitCursor(false);
6792                 return;
6793         }
6794         
6795         listManager.loadNoteTitleColors();
6796         refreshLists();
6797         refreshEvernoteNote(true);
6798         setMessage(tr("Database has been restored."));
6799         waitCursor(false);
6800         }
6801         @SuppressWarnings("unused")
6802         private void exportNotes() {
6803                 QFileDialog fd = new QFileDialog(this);
6804                 fd.setFileMode(FileMode.AnyFile);
6805                 fd.setConfirmOverwrite(true);
6806                 fd.setWindowTitle(tr("Backup Database"));
6807                 fd.setFilter(tr("NixNote Export (*.nnex);;All Files (*.*)"));
6808                 fd.setAcceptMode(AcceptMode.AcceptSave);
6809                 fd.setDirectory(System.getProperty("user.home"));
6810                 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
6811                         return;
6812                 }
6813                 
6814                 
6815         waitCursor(true);
6816         setMessage(tr("Exporting Notes"));
6817         saveNote();
6818         
6819                 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals("")) 
6820                         selectedNoteGUIDs.add(currentNoteGuid);
6821                 
6822         ExportData noteWriter = new ExportData(conn, false, selectedNoteGUIDs);
6823         String fileName = fd.selectedFiles().get(0);
6824
6825         if (!fileName.endsWith(".nnex"))
6826                 fileName = fileName +".nnex";
6827         noteWriter.exportData(fileName);
6828         setMessage(tr("Export completed."));
6829  
6830
6831         waitCursor(false);
6832                 
6833         }
6834         @SuppressWarnings("unused")
6835         private void importNotes() {
6836                 QFileDialog fd = new QFileDialog(this);
6837                 fd.setFileMode(FileMode.ExistingFile);
6838                 fd.setConfirmOverwrite(true);
6839                 fd.setWindowTitle(tr("Import Notes"));
6840                 fd.setFilter(tr("NixNote Export (*.nnex);;Evernote Export (*.enex);;All Files (*.*)"));
6841                 fd.setAcceptMode(AcceptMode.AcceptOpen);
6842                 if (saveLastPath == null || saveLastPath.equals(""))
6843                         fd.setDirectory(System.getProperty("user.home"));
6844                 else
6845                         fd.setDirectory(saveLastPath);
6846                 if (fd.exec() == 0 || fd.selectedFiles().size() == 0) {
6847                         return;
6848                 }
6849                 
6850                 
6851         waitCursor(true);
6852         setMessage(tr("Importing Notes"));
6853         saveNote();
6854         
6855                 if (selectedNoteGUIDs.size() == 0 && !currentNoteGuid.equals("")) 
6856                         selectedNoteGUIDs.add(currentNoteGuid);
6857                 
6858         String fileName = fd.selectedFiles().get(0);
6859 //      saveLastPath.substring(0,fileName.lastIndexOf("/"));
6860
6861         if (fileName.endsWith(".nnex")) {
6862                 ImportData noteReader = new ImportData(conn, false);
6863                 if (selectedNotebookGUIDs != null && selectedNotebookGUIDs.size() > 0) 
6864                         noteReader.setNotebookGuid(selectedNotebookGUIDs.get(0));
6865                 else
6866                         noteReader.setNotebookGuid(listManager.getNotebookIndex().get(0).getGuid());
6867   
6868                 noteReader.importData(fileName);
6869         
6870                 if (noteReader.lastError != 0) {
6871                         setMessage(noteReader.getErrorMessage());
6872                         logger.log(logger.LOW, "Import problem: " +noteReader.lastError);
6873                         waitCursor(false);
6874                         return;
6875                 }
6876         } else {
6877                 if (fileName.endsWith(".enex")) {
6878                 ImportEnex noteReader = new ImportEnex(conn, false);
6879                         if (selectedNotebookGUIDs != null && selectedNotebookGUIDs.size() > 0) 
6880                                 noteReader.setNotebookGuid(selectedNotebookGUIDs.get(0));
6881                         else
6882                                 noteReader.setNotebookGuid(listManager.getNotebookIndex().get(0).getGuid());
6883   
6884                         waitCursor(false);
6885                         if (QMessageBox.question(this, tr("Confirmation"), 
6886                                         tr("Create new tags from import?"),
6887                                         QMessageBox.StandardButton.Yes, 
6888                                         QMessageBox.StandardButton.No) == StandardButton.Yes.value()) {
6889                                                                 noteReader.createNewTags = true;
6890                         } else
6891                                 noteReader.createNewTags = false;
6892                         waitCursor(true);
6893                         noteReader.importData(fileName);
6894         
6895                         if (noteReader.lastError != 0) {
6896                                 setMessage(noteReader.getErrorMessage());
6897                                 logger.log(logger.LOW, "Import problem: " +noteReader.lastError);
6898                                 waitCursor(false);
6899                                 return;
6900                         }
6901                 }
6902         }
6903         
6904         listManager.loadNoteTitleColors();
6905         refreshLists();
6906         refreshEvernoteNote(false);
6907         setMessage(tr("Notes have been imported."));
6908         waitCursor(false);
6909         
6910         setMessage(tr("Import completed."));
6911  
6912
6913         waitCursor(false);
6914                 
6915         }
6916         
6917         //**************************************************
6918         //* Duplicate a note 
6919         //**************************************************
6920         @SuppressWarnings("unused")
6921         private void duplicateNote() {
6922                 saveNote();
6923                 duplicateNote(currentNoteGuid);
6924         }
6925
6926         //**************************************************
6927         //* Action from when a user clicks Copy As URL
6928         //**************************************************
6929         @SuppressWarnings("unused")
6930         private void copyAsUrlClicked() {
6931                 QClipboard clipboard = QApplication.clipboard();
6932                 QMimeData mime = new QMimeData();
6933                 String url;
6934                 mime.setText(currentNoteGuid);
6935                 List<QUrl> urls = new ArrayList<QUrl>();
6936                 
6937                 // Start building the URL
6938                 User user = Global.getUserInformation();
6939
6940                 // Check that we have everything we need
6941                 if ((user.getShardId().equals("") || user.getId() == 0) && !Global.bypassSynchronizationWarning()) {
6942                         SynchronizationRequiredWarning warning = new SynchronizationRequiredWarning(this);
6943                         warning.exec();
6944                         if (!warning.neverSynchronize())
6945                                 return;
6946                         else {
6947                                 Global.setBypassSynchronizationWarning(true);
6948                                 user.setShardId("s0");
6949                                 user.setId(0);
6950                         }       
6951                 }
6952
6953                 
6954                 // Start building a list of URLs based upon the selected notes
6955         noteTableView.showColumn(Global.noteTableGuidPosition);
6956         
6957         List<QModelIndex> selections = noteTableView.selectionModel().selectedRows();
6958         if (!Global.isColumnVisible("guid"))
6959                 noteTableView.hideColumn(Global.noteTableGuidPosition);
6960
6961                 // Check that the note is either synchronized, or in a local notebook
6962                 for (int i=0; i<selections.size(); i++) {
6963                         QModelIndex index;
6964                         int row = selections.get(i).row();
6965                 index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
6966                 SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
6967                 String selectedGuid = (String)ix.values().toArray()[0];
6968                 
6969                 Note n = conn.getNoteTable().getNote(selectedGuid, false, false, false, false, false);
6970                 if (n.getUpdateSequenceNum() == 0 && !conn.getNotebookTable().isNotebookLocal(n.getNotebookGuid())) {
6971                         QMessageBox.critical(this, tr("Please Synchronize") ,tr("Please either synchronize or move any " +
6972                                         "new notes to a local notebook."));
6973                         return; 
6974                 }
6975                 }
6976
6977                 // Start building the URLs
6978         for (int i=0; i<selections.size(); i++) {
6979                 QModelIndex index;
6980                         int row = selections.get(i).row();
6981                 index = noteTableView.proxyModel.index(row, Global.noteTableGuidPosition);
6982                 SortedMap<Integer, Object> ix = noteTableView.proxyModel.itemData(index);
6983                 String selectedGuid = (String)ix.values().toArray()[0];
6984                 mime.setText(selectedGuid);
6985                 
6986                 String lid;
6987                 String gid;
6988                 Note selectedNote = conn.getNoteTable().getNote(selectedGuid, false, false, false, false, false);
6989                 if (selectedNote.getUpdateSequenceNum() > 0) {
6990                         gid = selectedGuid;
6991                         lid = selectedGuid;
6992                 } else {
6993                         gid = "00000000-0000-0000-0000-000000000000";
6994                         lid = selectedGuid;
6995                 }
6996                 url = new String("evernote://///view/") + new String(user.getId() + "/" +user.getShardId() +"/"
6997                                 +gid+"/"+lid +"/");
6998                 urls.add(new QUrl(url));
6999         }
7000                 mime.setUrls(urls);
7001                 clipboard.setMimeData(mime);
7002         }
7003         
7004         
7005         //**************************************************
7006         //* Folder Imports
7007         //**************************************************
7008         public void setupFolderImports() {
7009                 List<WatchFolderRecord> records = conn.getWatchFolderTable().getAll();
7010                 
7011                 if (importKeepWatcher == null)
7012                         importKeepWatcher = new QFileSystemWatcher();
7013                 if (importDeleteWatcher == null) {
7014                         importDeleteWatcher = new QFileSystemWatcher();
7015                         for (int i=0; i<records.size(); i++) {
7016                                 if (!records.get(i).keep)
7017                                         folderImportDelete(records.get(i).folder); 
7018                         }
7019                 }
7020
7021                                 
7022                 
7023 //              importKeepWatcher.addPath(records.get(i).folder.replace('\\', '/'));
7024                 for (int i=0; i<records.size(); i++) {
7025                         logger.log(logger.LOW, "Adding file monitor: " +records.get(i).folder);
7026                         if (records.get(i).keep) 
7027                                 importKeepWatcher.addPath(records.get(i).folder);
7028                         else
7029                                 importDeleteWatcher.addPath(records.get(i).folder);
7030                 }
7031                 
7032                 logger.log(logger.EXTREME, "List of directories being watched (kept)...");
7033                 List<String> monitorDelete = importKeepWatcher.directories();
7034                 for (int i=0; i<monitorDelete.size(); i++) {
7035                         logger.log(logger.EXTREME, monitorDelete.get(i));
7036                 }
7037                 logger.log(logger.EXTREME, "<end of list>");
7038                 logger.log(logger.EXTREME, "List of directories being watched (delete)...");
7039                 monitorDelete = importDeleteWatcher.directories();
7040                 for (int i=0; i<monitorDelete.size(); i++) {
7041                         logger.log(logger.EXTREME, monitorDelete.get(i));
7042                 }
7043                 logger.log(logger.EXTREME, "<end of list>");
7044                 
7045                 importKeepWatcher.directoryChanged.connect(this, "folderImportKeep(String)");
7046                 importDeleteWatcher.directoryChanged.connect(this, "folderImportDelete(String)");
7047                 
7048                 // Look at the files already there so we don't import them again if a new file is created
7049                 if (importedFiles == null) {
7050                         importedFiles = new ArrayList<String>();
7051                         for (int j=0; j<records.size(); j++) {
7052                                 QDir dir = new QDir(records.get(j).folder);
7053                                 List<QFileInfo> list = dir.entryInfoList();
7054                                 for (int k=0; k<list.size(); k++) {
7055                                         if (list.get(k).isFile())
7056                                                 importedFiles.add(list.get(k).absoluteFilePath());
7057                                 }
7058                         }
7059                 }
7060         }
7061         
7062         // Menu folderImport action triggered
7063         public void folderImport() {
7064                 List<WatchFolderRecord> recs = conn.getWatchFolderTable().getAll();
7065                 WatchFolder dialog = new WatchFolder(recs, listManager.getNotebookIndex());
7066                 dialog.exec();
7067                 if (!dialog.okClicked())
7068                         return;
7069                 
7070                 // We have some sort of update.
7071                 if (importKeepWatcher.directories().size() > 0)
7072                         importKeepWatcher.removePaths(importKeepWatcher.directories());
7073                 if (importDeleteWatcher.directories().size() > 0)
7074                         importDeleteWatcher.removePaths(importDeleteWatcher.directories());
7075                 
7076                 conn.getWatchFolderTable().expungeAll();
7077                 // Start building from the table
7078                 for (int i=0; i<dialog.table.rowCount(); i++) {
7079                         QTableWidgetItem item = dialog.table.item(i, 0);
7080                         String dir = item.text();
7081                         item = dialog.table.item(i, 1);
7082                         String notebook = item.text();
7083                         item = dialog.table.item(i, 2);
7084                         boolean keep;
7085                         if (item.text().equalsIgnoreCase("Keep"))
7086                                 keep = true;
7087                         else
7088                                 keep = false;
7089                         
7090                         String guid = conn.getNotebookTable().findNotebookByName(notebook);
7091                         conn.getWatchFolderTable().addWatchFolder(dir, guid, keep, 0);
7092                 }
7093                 setupFolderImports();
7094         }
7095         
7096         
7097         public void folderImportKeep(String dirName) throws NoSuchAlgorithmException {
7098                 logger.log(logger.LOW, "Inside folderImportKeep");
7099                 String whichOS = System.getProperty("os.name");
7100                 if (whichOS.contains("Windows")) 
7101                         dirName = dirName.replace('/','\\');
7102                 
7103                 FileImporter importer = new FileImporter(logger, conn);
7104                 
7105                 QDir dir = new QDir(dirName);
7106                 List<QFileInfo> list = dir.entryInfoList();
7107                 String notebook = conn.getWatchFolderTable().getNotebook(dirName);
7108
7109                 for (int i=0; i<list.size(); i++){
7110                         logger.log(logger.LOW, "File found: " +list.get(i).fileName());
7111                         boolean redundant = false;
7112                         // Check if we've already imported this one or if it existed before
7113                         for (int j=0; j<importedFiles.size(); j++) {
7114                                 logger.log(logger.LOW, "redundant file list: " +list.get(i).absoluteFilePath());
7115                                 if (importedFiles.get(j).equals(list.get(i).absoluteFilePath()))
7116                                         redundant = true;
7117                         }
7118                         
7119                         logger.log(logger.LOW, "Checking if redundant: " +redundant);
7120                         if (!redundant) {
7121                                 importer.setFileInfo(list.get(i));
7122                                 importer.setFileName(list.get(i).absoluteFilePath());
7123                         
7124                         
7125                                 logger.log(logger.LOW, "File importing is a file: " +list.get(i).isFile());
7126                                 logger.log(logger.LOW, "File importing is a valid: " +importer.isValidType());
7127                                 if (list.get(i).isFile() && importer.isValidType()) {
7128                         
7129                                         if (!importer.importFile()) {
7130                                                 // If we can't get to the file, it is probably locked.  We'll try again later.
7131                                                 logger.log(logger.LOW, "Unable to save externally edited file.  Saving for later.");
7132                                                 importFilesKeep.add(list.get(i).absoluteFilePath());
7133                                         } else {
7134
7135                                                 Note newNote = importer.getNote();
7136                                                 newNote.setNotebookGuid(notebook);
7137                                                 newNote.setTitle(dir.at(i));
7138                                                 NoteMetadata metadata = new NoteMetadata();
7139                                                 metadata.setDirty(true);
7140                                                 metadata.setGuid(newNote.getGuid());
7141                                                 listManager.addNote(newNote, metadata);
7142                                                 conn.getNoteTable().addNote(newNote, true);
7143                                                 noteTableView.insertRow(newNote, metadata, true, -1);
7144                                                 listManager.updateNoteContent(newNote.getGuid(), importer.getNoteContent());
7145                                                 listManager.countNotebookResults(listManager.getNoteIndex());
7146                                                 importedFiles.add(list.get(i).absoluteFilePath());
7147                                         }
7148                                 }
7149                         }
7150                 }
7151         
7152         
7153         }
7154         
7155         public void folderImportDelete(String dirName) {
7156                 logger.log(logger.LOW, "Inside folderImportDelete");
7157                 String whichOS = System.getProperty("os.name");
7158                 if (whichOS.contains("Windows")) 
7159                         dirName = dirName.replace('/','\\');
7160                 
7161                 FileImporter importer = new FileImporter(logger, conn);
7162                 QDir dir = new QDir(dirName);
7163                 List<QFileInfo> list = dir.entryInfoList();
7164                 String notebook = conn.getWatchFolderTable().getNotebook(dirName);
7165                 
7166                 for (int i=0; i<list.size(); i++){
7167                         logger.log(logger.LOW, "File found: " +list.get(i).fileName());
7168                         importer.setFileInfo(list.get(i));
7169                         importer.setFileName(list.get(i).absoluteFilePath());
7170                         
7171                         logger.log(logger.LOW, "File importing is a file: " +list.get(i).isFile());
7172                         logger.log(logger.LOW, "File importing is a valid: " +importer.isValidType());
7173                         if (list.get(i).isFile() && importer.isValidType()) {
7174                 
7175                                 if (!importer.importFile()) {
7176                                         // If we can't get to the file, it is probably locked.  We'll try again later.
7177                                         logger.log(logger.LOW, "Unable to save externally edited file.  Saving for later.");
7178                                         importFilesKeep.add(list.get(i).absoluteFilePath());
7179                                 } else {
7180                 
7181                                         Note newNote = importer.getNote();
7182                                         newNote.setNotebookGuid(notebook);
7183                                         newNote.setTitle(dir.at(i));
7184                                         NoteMetadata metadata = new NoteMetadata();
7185                                         metadata.setDirty(true);
7186                                         metadata.setGuid(newNote.getGuid());
7187                                         listManager.addNote(newNote, metadata);
7188                                         conn.getNoteTable().addNote(newNote, true);
7189                                         noteTableView.insertRow(newNote, metadata, true, -1);
7190                                         listManager.updateNoteContent(newNote.getGuid(), importer.getNoteContent());
7191                                         listManager.countNotebookResults(listManager.getNoteIndex());
7192                                         dir.remove(dir.at(i));
7193                                 }
7194                         }
7195                 }
7196         }
7197         
7198         
7199         //**************************************************
7200         //* External events
7201         //**************************************************
7202         private void externalFileEdited(String fileName) throws NoSuchAlgorithmException {
7203                 logger.log(logger.HIGH, "Entering exernalFileEdited");
7204
7205                 // Strip URL prefix and base dir path
7206                 String dPath = FileUtils.toForwardSlashedPath(Global.getFileManager().getResDirPath());
7207                 String name = fileName.replace(dPath, "");
7208                 int pos = name.lastIndexOf('.');
7209                 String guid = name;
7210                 if (pos > -1) {
7211                         guid = guid.substring(0,pos);
7212                 }
7213                 pos = name.lastIndexOf(Global.attachmentNameDelimeter);
7214                 if (pos > -1) {
7215                         guid = name.substring(0, pos);
7216                 }
7217                 
7218                 QFile file = new QFile(fileName);
7219         if (!file.open(new QIODevice.OpenMode(QIODevice.OpenModeFlag.ReadOnly))) {
7220                 // If we can't get to the file, it is probably locked.  We'll try again later.
7221                 logger.log(logger.LOW, "Unable to save externally edited file.  Saving for later.");
7222                 externalFiles.add(fileName);
7223                 return;
7224                 }
7225                 QByteArray binData = file.readAll();
7226         file.close();
7227         if (binData.size() == 0) {
7228                 // If we can't get to the file, it is probably locked.  We'll try again later.
7229                 logger.log(logger.LOW, "Unable to save externally edited file.  Saving for later.");
7230                 externalFiles.add(fileName);
7231                 return;
7232         }
7233         
7234         Resource r = conn.getNoteTable().noteResourceTable.getNoteResource(guid, true);
7235         if (r==null)
7236                 r = conn.getNoteTable().noteResourceTable.getNoteResource(Global.resourceMap.get(guid), true);
7237         if (r == null || r.getData() == null || r.getData().getBody() == null)
7238                 return;
7239         String oldHash = Global.byteArrayToHexString(r.getData().getBodyHash());
7240         MessageDigest md = MessageDigest.getInstance("MD5");
7241                 md.update(binData.toByteArray());
7242                 byte[] hash = md.digest();
7243         String newHash = Global.byteArrayToHexString(hash);
7244         if (r.getNoteGuid().equalsIgnoreCase(currentNoteGuid)) {
7245                 updateResourceContentHash(browserWindow, r.getGuid(), oldHash, newHash);
7246         }
7247         if (externalWindows.containsKey(r.getNoteGuid())) {
7248                 updateResourceContentHash(externalWindows.get(r.getNoteGuid()).getBrowserWindow(), 
7249                                 r.getGuid(), oldHash, newHash);
7250         }
7251         conn.getNoteTable().updateResourceContentHash(r.getNoteGuid(), oldHash, newHash);
7252         Data data = r.getData();
7253         data.setBody(binData.toByteArray());
7254         data.setBodyHash(hash);
7255         logger.log(logger.LOW, "externalFileEdited: " +data.getSize() +" bytes");
7256         r.setData(data);
7257         conn.getNoteTable().noteResourceTable.updateNoteResource(r,true);
7258         
7259         if (r.getNoteGuid().equals(currentNoteGuid)) {
7260                         QWebSettings.setMaximumPagesInCache(0);
7261                         QWebSettings.setObjectCacheCapacities(0, 0, 0);
7262                         refreshEvernoteNote(true);
7263                         browserWindow.getBrowser().triggerPageAction(WebAction.Reload);
7264         }
7265         
7266         if (externalWindows.containsKey(r.getNoteGuid())) {
7267                 QWebSettings.setMaximumPagesInCache(0);
7268                         QWebSettings.setObjectCacheCapacities(0, 0, 0);
7269                         externalWindows.get(r.getNoteGuid()).getBrowserWindow().getBrowser().triggerPageAction(WebAction.Reload);
7270                         
7271         }
7272         
7273                 logger.log(logger.HIGH, "Exiting externalFielEdited");
7274         }
7275         // This is a timer event that tries to save any external files that were edited.  This
7276         // is only needed if we couldn't save a file earlier.
7277         public void externalFileEditedSaver() {
7278                 for (int i=externalFiles.size()-1; i>=0; i--) {
7279                         try {
7280                                 logger.log(logger.MEDIUM, "Trying to save " +externalFiles.get(i));
7281                                 externalFileEdited(externalFiles.get(i));
7282                                 externalFiles.remove(i);
7283                         } catch (NoSuchAlgorithmException e) {e.printStackTrace();}
7284                 }
7285                 for (int i=0; i<importFilesKeep.size(); i++) {
7286                         try {
7287                                 logger.log(logger.MEDIUM, "Trying to save " +importFilesKeep.get(i));
7288                                 folderImportKeep(importFilesKeep.get(i));
7289                                 importFilesKeep.remove(i);
7290                         } catch (NoSuchAlgorithmException e) {e.printStackTrace();}
7291                 }
7292                 for (int i=0; i<importFilesDelete.size(); i++) {
7293                         logger.log(logger.MEDIUM, "Trying to save " +importFilesDelete.get(i));
7294                         folderImportDelete(importFilesDelete.get(i));
7295                         importFilesDelete.remove(i);
7296                 }
7297         }
7298         
7299         
7300         
7301         
7302         // If an attachment on the current note was edited, we need to update the current notes's hash
7303         // Update a note content's hash.  This happens if a resource is edited outside of NN
7304         public void updateResourceContentHash(BrowserWindow browser, String guid, String oldHash, String newHash) {
7305                 int position = browserWindow.getContent().indexOf("en-tag=\"en-media\" guid=\""+guid+"\" type=");
7306                 int endPos;
7307                 for (;position>-1;) {
7308                         endPos = browser.getContent().indexOf(">", position+1);
7309                         String oldSegment = browser.getContent().substring(position,endPos);
7310                         int hashPos = oldSegment.indexOf("hash=\"");
7311                         int hashEnd = oldSegment.indexOf("\"", hashPos+7);
7312                         String hash = oldSegment.substring(hashPos+6, hashEnd);
7313                         if (hash.equalsIgnoreCase(oldHash)) {
7314                                 String newSegment = oldSegment.replace(oldHash, newHash);
7315                                 String content = browser.getContent().substring(0,position) +
7316                                                  newSegment +
7317                                                  browser.getContent().substring(endPos);
7318                                 browser.setContent(new QByteArray(content));;
7319                         }
7320                         
7321                         position = browser.getContent().indexOf("en-tag=\"en-media\" guid=\""+guid+"\" type=", position+1);
7322                 }
7323         }
7324
7325
7326         //*************************************************
7327         //* Minimize to tray
7328         //*************************************************
7329         @Override
7330         public void changeEvent(QEvent e) {
7331                 if (e.type() == QEvent.Type.WindowStateChange) {
7332                         if (QSystemTrayIcon.isSystemTrayAvailable()) {
7333                                 if (isMinimized() && (Global.showTrayIcon() || Global.showTrayIcon())) {
7334                                         e.accept();
7335                                         QTimer.singleShot(10, this, "hide()");
7336                                         return;
7337                                 }
7338                                 if (isMaximized())
7339                                         windowMaximized = true;
7340                                 else 
7341                                         windowMaximized = false;
7342                         }
7343                 }
7344         }
7345         
7346         //*************************************************
7347         //* Check database userid & passwords
7348         //*************************************************
7349         private static boolean databaseCheck(String url,String userid, String userPassword, String cypherPassword) {
7350                         Connection connection;
7351                         
7352                         try {
7353                                 Class.forName("org.h2.Driver");
7354                         } catch (ClassNotFoundException e1) {
7355                                 e1.printStackTrace();
7356                                 System.exit(16);
7357                         }
7358
7359                         try {
7360                                 String passwordString = null;
7361                                 if (cypherPassword==null || cypherPassword.trim().equals(""))
7362                                         passwordString = userPassword;
7363                                 else
7364                                         passwordString = cypherPassword+" "+userPassword;
7365                                 connection = DriverManager.getConnection(url,userid,passwordString);
7366                         } catch (SQLException e) {
7367                                 return false;
7368                         }
7369                         try {
7370                                 connection.close();
7371                         } catch (SQLException e) {
7372                                 e.printStackTrace();
7373                         }
7374                         return true;
7375         }
7376
7377         //*************************************************
7378         //* View / Hide source HTML for a note
7379         //*************************************************
7380         public void viewSource() {
7381                 // ICHANGED すべてのタブに対して
7382         for(int i = 0; i < tabBrowser.count(); i++){
7383                 BrowserWindow browser = ((TabBrowse) tabBrowser.widget(i)).getBrowserWindow();
7384                 browser.showSource(menuBar.viewSource.isChecked());
7385         }
7386         }
7387         //*************************************************
7388         // Block the program.  This is used for things  
7389         // like async web calls.
7390         //*************************************************
7391         @SuppressWarnings("unused")
7392         private void blockApplication(BrowserWindow b) {
7393                 // Block all signals
7394                 waitCursor(true);
7395                 blockSignals(true);
7396                 
7397                 blockTimer = new QTimer();
7398                 blockTimer.setSingleShot(true);
7399                 blockTimer.setInterval(15000);
7400                 blockTimer.timeout.connect(this, "unblockApplication()");
7401                 blockingWindow  = b;
7402                 blockTimer.start();
7403         }
7404         
7405         @SuppressWarnings("unused")
7406         private void unblockApplication() {
7407                 waitCursor(false);
7408                 if (blockingWindow != null && new GregorianCalendar().getTimeInMillis() > blockingWindow.unblockTime && blockingWindow.unblockTime != -1) {
7409                         QMessageBox.critical(null, tr("No Response from CodeCogs") ,tr("Unable to contact CodeCogs for LaTeX formula."));
7410                         blockingWindow.unblockTime = -1;
7411                         blockingWindow.awaitingHttpResponse = false;
7412                 }
7413                 blockingWindow = null;
7414                 blockSignals(false);
7415         }
7416         
7417         // ICHANGED
7418         // タブが変更された
7419         private void tabWindowChanged(int index) {
7420                 if (index < 0 || index >= tabBrowser.count()) {
7421                         return;
7422                 }
7423                 
7424                 saveNote();
7425
7426                 TabBrowse tab = (TabBrowse) tabBrowser.widget(index);
7427                 if (tab.getBrowserWindow().getNote() != null) {
7428                         currentNoteGuid = tab.getBrowserWindow().getNote().getGuid();
7429                         currentNote = tab.getBrowserWindow().getNote();
7430                 } else {
7431                         currentNoteGuid = "";
7432                         currentNote = null;
7433                 }
7434
7435                 // 選択ノートを更新
7436                 selectedNoteGUIDs.clear();
7437                 if (currentNoteGuid != null && !currentNoteGuid.equals("")) {
7438                         selectedNoteGUIDs.add(currentNoteGuid);
7439                 }
7440                 
7441                 // browserWindowを更新
7442                 browserWindow.noteSignal.noteChanged.disconnect(this,"setNoteDirty()");
7443                 browserWindow.focusLost.disconnect(this, "saveNote()");
7444                 browserWindow = tab.getBrowserWindow();
7445                 browserWindow.noteSignal.noteChanged.connect(this, "setNoteDirty()");
7446                 browserWindow.focusLost.connect(this, "saveNote()");
7447                 // メニューバーのボタンを新しいbrowserWindowに合わせる
7448                 menuBar.refreshTargetWindow();
7449                 
7450                 // 現在ゴミ箱かつ移るタブがアクティブなら通常テーブルに、現在通常テーブルかつこれから非アクティブのタブに移るならゴミ箱を表示させる
7451                 boolean nextIsActive;
7452                 if (tab.getBrowserWindow().getNote() != null) {
7453                         nextIsActive = tab.getBrowserWindow().getNote().isActive();
7454                 } else {
7455                         nextIsActive = true;
7456                 }
7457                 if (Global.showDeleted && nextIsActive) {
7458                         switchNoteTable(false);
7459                 } else if (!Global.showDeleted && !nextIsActive) {
7460                         switchNoteTable(true);
7461                 }
7462
7463                 // noteTableViewの選択を変更するとselectionChangedが発生してしまうので一度切断
7464                 noteTableView.selectionModel().selectionChanged.disconnect(this,"noteTableSelection()");
7465                 scrollToGuid(currentNoteGuid);
7466                 // 再接続
7467                 noteTableView.selectionModel().selectionChanged.connect(this,"noteTableSelection()");
7468
7469                 menuBar.noteDuplicateAction.setEnabled(true);
7470                 menuBar.noteOnlineHistoryAction.setEnabled(true);
7471                 menuBar.noteMergeAction.setEnabled(true);
7472                 
7473                 if (Global.showDeleted) {
7474                         menuBar.noteDuplicateAction.setEnabled(false);
7475                 }
7476                 if (!Global.isConnected) {
7477                         menuBar.noteOnlineHistoryAction.setEnabled(false);
7478                 }
7479                 menuBar.noteMergeAction.setEnabled(false);
7480                 try {
7481                         int row = noteTableView.selectionModel().selectedRows().get(0).row();
7482                         if (row == 0)
7483                                 upButton.setEnabled(false);
7484                         else
7485                                 upButton.setEnabled(true);
7486                         if (row < listManager.getNoteTableModel().rowCount() - 1)
7487                                 downButton.setEnabled(true);
7488                         else
7489                                 downButton.setEnabled(false);
7490                 } catch (Exception e) {
7491                         upButton.setEnabled(false);
7492                         downButton.setEnabled(false);
7493                 }
7494                 
7495                 int currentIndex = tabBrowser.currentIndex();
7496                 ArrayList<String> histGuids = historyGuids.get(currentIndex);
7497                 int histPosition = historyPosition.get(currentIndex);
7498
7499                 // prev, nextボタンの有効・無効化
7500                 nextButton.setEnabled(true);
7501                 prevButton.setEnabled(true);
7502
7503                 if (histPosition <= 1){
7504                         prevButton.setEnabled(false);
7505                 }
7506                 if (histPosition == histGuids.size()){
7507                         nextButton.setEnabled(false);
7508                 }
7509
7510                 refreshEvernoteNote(true);
7511
7512                 // 連想ノートリストを更新
7513                 rensoNoteList.refreshRensoNoteList(currentNoteGuid);
7514         }
7515         
7516         // ICHANGD
7517         // 生存ノートテーブル→ゴミ箱(またはその逆)に切り替える
7518         private void switchNoteTable(boolean toDeleted) {
7519         clearNotebookFilter();
7520         clearTagFilter();
7521         clearAttributeFilter();
7522         clearSavedSearchFilter();
7523         
7524         listManager.getSelectedNotebooks().clear();
7525         listManager.getSelectedTags().clear();
7526         listManager.setSelectedSavedSearch("");
7527     
7528         // toggle the add buttons
7529         newButton.setEnabled(!newButton.isEnabled());
7530         menuBar.noteAdd.setEnabled(newButton.isEnabled());
7531         menuBar.noteAdd.setVisible(true);
7532         
7533         if (!toDeleted) {       // 生存ノートテーブルへ
7534                 trashTree.itemSelectionChanged.disconnect(this, "trashTreeSelection()");
7535                 trashTree.clearSelection();
7536                 trashTree.itemSelectionChanged.connect(this, "trashTreeSelection()");
7537                 Global.showDeleted = false;
7538                 menuBar.noteRestoreAction.setEnabled(false);
7539                 menuBar.noteRestoreAction.setVisible(false);
7540                 // ICHANGED ゴミ箱から元の画面に戻す。連想ノートリストをONに。
7541                 rensoNoteListDock.setEnabled(true);
7542         } else {        // ゴミ箱へ
7543                 trashTree.itemSelectionChanged.disconnect(this, "trashTreeSelection()");
7544                 trashTree.setCurrentItem(trashTree.getTrashItem());
7545                 trashTree.itemSelectionChanged.connect(this, "trashTreeSelection()");
7546                 Global.showDeleted = true;
7547                 menuBar.noteRestoreAction.setEnabled(true);
7548                 menuBar.noteRestoreAction.setVisible(true);
7549                 // ICHANGED ゴミ箱を開く。連想ノートリストをOFFに。
7550                 rensoNoteListDock.setEnabled(false);
7551         }
7552         
7553         listManager.loadNotesIndex();
7554         // noteTableViewの選択を変更するとselectionChangedが発生してしまうので一度切断
7555         noteTableView.selectionModel().selectionChanged.disconnect(this,"noteTableSelection()");
7556         noteIndexUpdated(false);
7557         // 再接続
7558         noteTableView.selectionModel().selectionChanged.connect(this,"noteTableSelection()");
7559         
7560         browserWindow.setReadOnly(!newButton.isEnabled());
7561         }
7562
7563         // ICHANGED
7564         // ユーザが連想ノートリストのアイテムを選択した時の処理
7565         @SuppressWarnings("unused")
7566         private void rensoNoteItemPressed(QListWidgetItem current) {
7567                 logger.log(logger.HIGH, "Nevernote.rensoNoteSelectionChangeに入った");
7568
7569                 rensoNotePressedItemGuid = rensoNoteList.getNoteGuid(current);
7570                 
7571                 // 右クリックだったら終了
7572                 if (QApplication.mouseButtons().isSet(MouseButton.RightButton)) {
7573                         return;
7574                 }
7575                 
7576                 saveNote();
7577
7578                 String prevCurrentNoteGuid = new String(currentNoteGuid);
7579                 
7580                 for (int i = 0; i < noteTableView.model().rowCount(); i++) {
7581                         QModelIndex modelIndex = noteTableView.model().index(i,
7582                                         Global.noteTableGuidPosition);
7583                         if (modelIndex != null) {
7584                                 SortedMap<Integer, Object> ix = noteTableView.model().itemData(
7585                                                 modelIndex);
7586                                 String tableGuid = (String) ix.values().toArray()[0];
7587                                 if (tableGuid.equals(rensoNotePressedItemGuid)) {
7588                                         noteTableView.selectRow(i);
7589                                         return;
7590                                 }
7591                         }
7592                 }
7593                 
7594                 // 連想ノートリストアイテムクリック操作を記録
7595                 conn.getHistoryTable().addHistory("rensoItemClick", prevCurrentNoteGuid, currentNoteGuid);
7596
7597                 logger.log(logger.HIGH, "Nevernote.rensoNoteSelectionChangeを出た");
7598         }
7599         
7600         // ICHANGED
7601         // 関連ノートリストからノートを除外する
7602         @SuppressWarnings("unused")
7603         private void excludeNote() {
7604                 if (rensoNotePressedItemGuid != null) {
7605                         saveNote();
7606                         excludeNote(rensoNotePressedItemGuid);
7607                 }
7608         }
7609         
7610         // ICHANGED
7611         // 関連ノートリストからノートを除外する
7612         private void excludeNote(String guid) {
7613                 if (Global.verifyExclude()) {
7614                         String msg;
7615                         Note note = conn.getNoteTable().getNote(guid, false, false, false, false, false);
7616                         String title = note.getTitle();
7617                         if (title != null) {
7618                                 msg = new String(tr("Exclude note \"") +title +"\"?");
7619                         } else {                                
7620                                 msg = new String(tr("Exclude note selected note?"));
7621                         }
7622                         
7623                         if (QMessageBox.question(this, tr("Confirmation"), msg,
7624                                         QMessageBox.StandardButton.Yes, 
7625                                         QMessageBox.StandardButton.No)==StandardButton.No.value() && Global.verifyDelete() == true) {
7626                                         return;
7627                         }
7628                 }
7629                 
7630                 // Historyデータベースから除外するノートのデータを削除
7631                 conn.getHistoryTable().expungeHistory(guid, currentNoteGuid);
7632                 
7633                 // 除外ノートテーブルに追加
7634                 conn.getExcludedTable().addExclusion(guid, currentNoteGuid);
7635                 
7636                 rensoNoteList.refreshRensoNoteList(currentNoteGuid);
7637         }
7638         
7639         // ICHANGED
7640         // 関連ノートリストのノートにスターを付ける
7641         @SuppressWarnings("unused")
7642         private void starNote() {
7643                 if (rensoNotePressedItemGuid != null) {
7644                         saveNote();
7645                         starNote(rensoNotePressedItemGuid);
7646                 }
7647         }
7648         
7649         // ICHANGED
7650         // 関連ノートリストのノートにスターを付ける
7651         private void starNote(String guid) {
7652                 // スター付きノートテーブルに追加
7653                 conn.getStaredTable().addStaredItem(currentNoteGuid, guid);
7654                 
7655                 rensoNoteList.refreshRensoNoteList(currentNoteGuid);
7656         }
7657         
7658         // ICHANGED
7659         // 関連ノートリストのノートからスターを外す
7660         @SuppressWarnings("unused")
7661         private void unstarNote() {
7662                 if (rensoNotePressedItemGuid != null) {
7663                         saveNote();
7664                         unstarNote(rensoNotePressedItemGuid);
7665                 }
7666         }
7667         
7668         // ICHANGED
7669         // 関連ノートリストのノートからスターを外す
7670         private void unstarNote(String guid) {
7671                 // スター付きノートテーブルから削除
7672                 conn.getStaredTable().removeStaredItem(currentNoteGuid, guid);
7673                 
7674                 rensoNoteList.refreshRensoNoteList(currentNoteGuid);
7675         }
7676         
7677         // ICHANGED
7678         // currentNoteGuidを返す
7679         public String getCurrentNoteGuid() {
7680                 return currentNoteGuid;
7681         }
7682         
7683         @SuppressWarnings("unused")
7684         // タブ入れ替えによってタブインデックスが変わったので、インデックスで管理しているハッシュマップ達も入れ替える
7685         private void tabIndexChanged(int from, int to) {
7686                 // tabWindows
7687                 TabBrowse tab = tabWindows.get(from);
7688                 tabWindows.put(from, tabWindows.get(to));
7689                 tabWindows.put(to, tab);
7690                 // noteDirty
7691                 boolean isNoteDirty = noteDirty.get(from);
7692                 noteDirty.put(from, noteDirty.get(to));
7693                 noteDirty.put(to, isNoteDirty);
7694                 // inkNote
7695                 boolean isInkNote = inkNote.get(from);
7696                 inkNote.put(from, inkNote.get(to));
7697                 inkNote.put(to, isInkNote);
7698                 // readOnly
7699                 boolean isReadOnly = readOnly.get(from);
7700                 readOnly.put(from, readOnly.get(to));
7701                 readOnly.put(to, isReadOnly);
7702                 // historyGuids
7703                 ArrayList<String> histGuids = historyGuids.get(from);
7704                 historyGuids.put(from, historyGuids.get(to));
7705                 historyGuids.put(to, histGuids);
7706                 // historyPosition
7707                 int histPosition = historyPosition.get(from);
7708                 historyPosition.put(from, historyPosition.get(to));
7709                 historyPosition.put(to, histPosition);
7710                 // fromHistory
7711                 boolean fromHist = fromHistory.get(from);
7712                 fromHistory.put(from,  fromHistory.get(to));
7713                 fromHistory.put(to, fromHist);
7714         }
7715 }