OSDN Git Service

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