OSDN Git Service

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