OSDN Git Service

帯域制限超過時のメッセージを更新した
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / NeverNote.java
1 /*
2   * This file is part of NixNote/NeighborNote 
3  * Copyright 2009 Randy Baumgarte
4  * Copyright 2013 Yuki Takahashi
5  * 
6  * This file may be licensed under the terms of of the
7  * GNU General Public License Version 2 (the ``GPL'').
8  *
9  * Software distributed under the License is distributed
10  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
11  * express or implied. See the GPL for the specific language
12  * governing rights and limitations.
13  *
14  * You should have received a copy of the GPL along with this
15  * program. If not, go to http://www.gnu.org/licenses/gpl.html
16  * or write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19 */
20 package cx.fbn.nevernote;
21 import java.awt.Desktop;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileNotFoundException;
25 import java.io.FileOutputStream;
26 import java.net.Authenticator;
27 import java.net.PasswordAuthentication;
28 import java.security.MessageDigest;
29 import java.security.NoSuchAlgorithmException;
30 import java.sql.Connection;
31 import java.sql.DriverManager;
32 import java.sql.SQLException;
33 import java.sql.Statement;
34 import java.text.SimpleDateFormat;
35 import java.util.ArrayList;
36 import java.util.Calendar;
37 import java.util.Collection;
38 import java.util.Collections;
39 import java.util.Comparator;
40 import java.util.Date;
41 import java.util.GregorianCalendar;
42 import java.util.HashMap;
43 import java.util.Iterator;
44 import java.util.List;
45 import java.util.Map;
46 import java.util.SortedMap;
47 import java.util.Vector;
48
49 import org.apache.log4j.Level;
50 import org.apache.log4j.Logger;
51 import org.h2.tools.ChangeFileEncryption;
52
53 import com.evernote.edam.error.EDAMErrorCode;
54 import com.evernote.edam.error.EDAMNotFoundException;
55 import com.evernote.edam.error.EDAMSystemException;
56 import com.evernote.edam.error.EDAMUserException;
57 import com.evernote.edam.notestore.NoteFilter;
58 import com.evernote.edam.notestore.NoteVersionId;
59 import com.evernote.edam.type.Data;
60 import com.evernote.edam.type.LinkedNotebook;
61 import com.evernote.edam.type.Note;
62 import com.evernote.edam.type.NoteAttributes;
63 import com.evernote.edam.type.Notebook;
64 import com.evernote.edam.type.Publishing;
65 import com.evernote.edam.type.QueryFormat;
66 import com.evernote.edam.type.Resource;
67 import com.evernote.edam.type.SavedSearch;
68 import com.evernote.edam.type.Tag;
69 import com.evernote.edam.type.User;
70 import com.evernote.thrift.TException;
71 import com.trolltech.qt.QThread;
72 import com.trolltech.qt.core.QByteArray;
73 import com.trolltech.qt.core.QDateTime;
74 import com.trolltech.qt.core.QDir;
75 import com.trolltech.qt.core.QEvent;
76 import com.trolltech.qt.core.QFile;
77 import com.trolltech.qt.core.QFileInfo;
78 import com.trolltech.qt.core.QFileSystemWatcher;
79 import com.trolltech.qt.core.QIODevice;
80 import com.trolltech.qt.core.QIODevice.OpenModeFlag;
81 import com.trolltech.qt.core.QLocale;
82 import com.trolltech.qt.core.QMimeData;
83 import com.trolltech.qt.core.QModelIndex;
84 import com.trolltech.qt.core.QSize;
85 import com.trolltech.qt.core.QTemporaryFile;
86 import com.trolltech.qt.core.QTextCodec;
87 import com.trolltech.qt.core.QTextStream;
88 import com.trolltech.qt.core.QThreadPool;
89 import com.trolltech.qt.core.QTimer;
90 import com.trolltech.qt.core.QTranslator;
91 import com.trolltech.qt.core.QUrl;
92 import com.trolltech.qt.core.Qt;
93 import com.trolltech.qt.core.Qt.BGMode;
94 import com.trolltech.qt.core.Qt.DockWidgetArea;
95 import com.trolltech.qt.core.Qt.ItemDataRole;
96 import com.trolltech.qt.core.Qt.KeyboardModifier;
97 import com.trolltech.qt.core.Qt.MouseButton;
98 import com.trolltech.qt.core.Qt.SortOrder;
99 import com.trolltech.qt.core.Qt.WidgetAttribute;
100 import com.trolltech.qt.gui.QAbstractItemView;
101 import com.trolltech.qt.gui.QAbstractItemView.ScrollHint;
102 import com.trolltech.qt.gui.QAction;
103 import com.trolltech.qt.gui.QApplication;
104 import com.trolltech.qt.gui.QClipboard;
105 import com.trolltech.qt.gui.QCloseEvent;
106 import com.trolltech.qt.gui.QColor;
107 import com.trolltech.qt.gui.QComboBox;
108 import com.trolltech.qt.gui.QCursor;
109 import com.trolltech.qt.gui.QDesktopServices;
110 import com.trolltech.qt.gui.QDialog;
111 import com.trolltech.qt.gui.QFileDialog;
112 import com.trolltech.qt.gui.QFileDialog.AcceptMode;
113 import com.trolltech.qt.gui.QFileDialog.FileMode;
114 import com.trolltech.qt.gui.QGridLayout;
115 import com.trolltech.qt.gui.QHBoxLayout;
116 import com.trolltech.qt.gui.QIcon;
117 import com.trolltech.qt.gui.QImage;
118 import com.trolltech.qt.gui.QKeySequence;
119 import com.trolltech.qt.gui.QLabel;
120 import com.trolltech.qt.gui.QListWidgetItem;
121 import com.trolltech.qt.gui.QMainWindow;
122 import com.trolltech.qt.gui.QMenu;
123 import com.trolltech.qt.gui.QMessageBox;
124 import com.trolltech.qt.gui.QMessageBox.StandardButton;
125 import com.trolltech.qt.gui.QPainter;
126 import com.trolltech.qt.gui.QPalette.ColorRole;
127 import com.trolltech.qt.gui.QPixmap;
128 import com.trolltech.qt.gui.QPrintDialog;
129 import com.trolltech.qt.gui.QPrinter;
130 import com.trolltech.qt.gui.QShortcut;
131 import com.trolltech.qt.gui.QSizePolicy;
132 import com.trolltech.qt.gui.QSizePolicy.Policy;
133 import com.trolltech.qt.gui.QSpinBox;
134 import com.trolltech.qt.gui.QSplashScreen;
135 import com.trolltech.qt.gui.QSplitter;
136 import com.trolltech.qt.gui.QStatusBar;
137 import com.trolltech.qt.gui.QSystemTrayIcon;
138 import com.trolltech.qt.gui.QTableWidgetItem;
139 import com.trolltech.qt.gui.QTextEdit;
140 import com.trolltech.qt.gui.QToolBar;
141 import com.trolltech.qt.gui.QTreeWidgetItem;
142 import com.trolltech.qt.network.QNetworkAccessManager;
143 import com.trolltech.qt.network.QNetworkProxy;
144 import com.trolltech.qt.network.QNetworkProxy.ProxyType;
145 import com.trolltech.qt.network.QNetworkReply;
146 import com.trolltech.qt.network.QNetworkRequest;
147 import com.trolltech.qt.webkit.QWebPage.WebAction;
148 import com.trolltech.qt.webkit.QWebSettings;
149
150 import cx.fbn.nevernote.clipboard.ClipBoardObserver;
151 import cx.fbn.nevernote.config.InitializationException;
152 import cx.fbn.nevernote.config.StartupConfig;
153 import cx.fbn.nevernote.dialog.AccountDialog;
154 import cx.fbn.nevernote.dialog.ConfigDialog;
155 import cx.fbn.nevernote.dialog.DBEncryptDialog;
156 import cx.fbn.nevernote.dialog.DatabaseLoginDialog;
157 import cx.fbn.nevernote.dialog.DatabaseStatus;
158 import cx.fbn.nevernote.dialog.FindDialog;
159 import cx.fbn.nevernote.dialog.IgnoreSync;
160 import cx.fbn.nevernote.dialog.LogFileDialog;
161 import cx.fbn.nevernote.dialog.NotebookArchive;
162 import cx.fbn.nevernote.dialog.NotebookEdit;
163 import cx.fbn.nevernote.dialog.OnlineNoteHistory;
164 import cx.fbn.nevernote.dialog.PublishNotebook;
165 import cx.fbn.nevernote.dialog.SavedSearchEdit;
166 import cx.fbn.nevernote.dialog.SetIcon;
167 import cx.fbn.nevernote.dialog.ShareNotebook;
168 import cx.fbn.nevernote.dialog.SharedNotebookSyncError;
169 import cx.fbn.nevernote.dialog.StackNotebook;
170 import cx.fbn.nevernote.dialog.SynchronizationRequiredWarning;
171 import cx.fbn.nevernote.dialog.TagEdit;
172 import cx.fbn.nevernote.dialog.TagMerge;
173 import cx.fbn.nevernote.dialog.ThumbnailViewer;
174 import cx.fbn.nevernote.dialog.UpgradeAvailableDialog;
175 import cx.fbn.nevernote.dialog.WatchFolder;
176 import cx.fbn.nevernote.evernote.NoteMetadata;
177 import cx.fbn.nevernote.filters.FilterEditorNotebooks;
178 import cx.fbn.nevernote.filters.FilterEditorTags;
179 import cx.fbn.nevernote.gui.AttributeTreeWidget;
180 import cx.fbn.nevernote.gui.BrowserWindow;
181 import cx.fbn.nevernote.gui.DateAttributeFilterTable;
182 import cx.fbn.nevernote.gui.ExternalBrowse;
183 import cx.fbn.nevernote.gui.MainMenuBar;
184 import cx.fbn.nevernote.gui.NotebookTreeWidget;
185 import cx.fbn.nevernote.gui.RensoNoteList;
186 import cx.fbn.nevernote.gui.RensoNoteListDock;
187 import cx.fbn.nevernote.gui.SavedSearchTreeWidget;
188 import cx.fbn.nevernote.gui.SearchPanel;
189 import cx.fbn.nevernote.gui.TabBrowse;
190 import cx.fbn.nevernote.gui.TabBrowserWidget;
191 import cx.fbn.nevernote.gui.TableView;
192 import cx.fbn.nevernote.gui.TagTreeWidget;
193 import cx.fbn.nevernote.gui.Thumbnailer;
194 import cx.fbn.nevernote.gui.TrashTreeWidget;
195 import cx.fbn.nevernote.gui.controls.QuotaProgressBar;
196 import cx.fbn.nevernote.oauth.OAuthTokenizer;
197 import cx.fbn.nevernote.oauth.OAuthWindow;
198 import cx.fbn.nevernote.sql.DatabaseConnection;
199 import cx.fbn.nevernote.sql.WatchFolderRecord;
200 import cx.fbn.nevernote.threads.IndexRunner;
201 import cx.fbn.nevernote.threads.SyncRunner;
202 import cx.fbn.nevernote.threads.ThumbnailRunner;
203 import cx.fbn.nevernote.utilities.AESEncrypter;
204 import cx.fbn.nevernote.utilities.ApplicationLogger;
205 import cx.fbn.nevernote.utilities.FileImporter;
206 import cx.fbn.nevernote.utilities.FileUtils;
207 import cx.fbn.nevernote.utilities.ListManager;
208 import cx.fbn.nevernote.utilities.SyncTimes;
209 import cx.fbn.nevernote.xml.ExportData;
210 import cx.fbn.nevernote.xml.ImportData;
211 import cx.fbn.nevernote.xml.ImportEnex;
212 import cx.fbn.nevernote.xml.NoteFormatter;
213
214
215 public class NeverNote extends QMainWindow{
216         
217         QStatusBar                              statusBar;                                      // Application status bar
218         
219         DatabaseConnection              conn;
220         
221         MainMenuBar                             menuBar;                                        // Main menu bar
222         FindDialog                              find;                                           // Text search in note dialog
223         List<String>                    emitLog;                                        // Messages displayed in the status bar;
224         QSystemTrayIcon                 trayIcon;                                       // little tray icon
225         QMenu                                   trayMenu;                                       // System tray menu
226         QAction                                 trayExitAction;                         // Exit the application
227         QAction                                 trayShowAction;                         // toggle the show/hide action          
228         QAction                                 trayAddNoteAction;                      // Add a note from the system tray
229         QNetworkAccessManager   versionChecker;                         // Used when checking for new versions
230         
231     NotebookTreeWidget          notebookTree;                           // List of notebooks
232     AttributeTreeWidget         attributeTree;                          // List of note attributes
233     TagTreeWidget                       tagTree;                                        // list of user created tags
234     SavedSearchTreeWidget       savedSearchTree;                        // list of saved searches
235     TrashTreeWidget                     trashTree;                                      // Trashcan
236     TableView                           noteTableView;                          //      List of notes (the widget).
237
238     public BrowserWindow        browserWindow;                          // Window containing browser & labels
239     public QToolBar             toolBar;                                        // The tool bar under the menu
240     QComboBox                           searchField;                            // search filter bar on the toolbar;
241     QShortcut                           searchShortcut;                         // Shortcut to search bar
242     boolean                                     searchPerformed = false;        // Search was done?
243     QuotaProgressBar            quotaBar;                                       // The current quota usage
244     
245     ApplicationLogger           logger;
246     List<String>                        selectedNotebookGUIDs;          // List of notebook GUIDs
247     List<String>                        selectedTagGUIDs;                       // List of selected tag GUIDs
248     List<String>                        selectedNoteGUIDs;                      // List of selected notes
249     String                                      selectedSavedSearchGUID;        // Currently selected saved searches
250     private final HashMap<String, ExternalBrowse>       externalWindows;        // Notes being edited by an external window;
251     
252     NoteFilter                          filter;                                         // Note filter
253     String                                      currentNoteGuid;                        // GUID of the current note 
254     Note                                        currentNote;                            // The currently viewed note
255     HashMap<Integer, Boolean>   noteDirty;                              // Has the note been changed?
256     HashMap<Integer, Boolean>   inkNote;                // if this is an ink note, it is read only
257     HashMap<Integer, Boolean>   readOnly;                               // Is this note read-only?
258         
259   
260     ListManager                         listManager;                                    // DB runnable task
261     
262     List<QTemporaryFile>        tempFiles;                                      // Array of temporary files;
263     
264     QTimer                                      indexTimer;                                     // timer to start the index thread
265     IndexRunner                         indexRunner;                            // thread to index notes
266     QThread                                     indexThread;
267     
268     QTimer                                      syncTimer;                                      // Sync on an interval
269     QTimer                                      syncDelayTimer;                         // Sync delay to free up database
270     SyncRunner                          syncRunner;                                     // thread to do a sync.
271     QThread                                     syncThread;                                     // Thread which talks to evernote
272     ThumbnailRunner                     thumbnailRunner;                        // Runner for thumbnail thread
273     QThread                                     thumbnailThread;                        // Thread that generates pretty pictures
274     QTimer                                      saveTimer;                                      // Timer to save note contents
275     
276     QTimer                                      authTimer;                                      // Refresh authentication
277     QTimer                                      externalFileSaveTimer;          // Save files altered externally
278     QTimer                                      thumbnailTimer;                         // Wakeup & scan for thumbnails
279     QTimer                                      debugTimer;
280     List<String>                        externalFiles;                          // External files to save later
281     List<String>                        importFilesKeep;                        // Auto-import files to save later
282     List<String>                        importFilesDelete;                      // Auto-import files to save later
283     
284     int                                         indexTime;                                      // how often to try and index
285     boolean                                     indexRunning;                           // Is indexing running?
286     boolean                                     indexDisabled;                          // Is indexing disabled?
287     
288     int                                         syncThreadsReady;                       // number of sync threads that are free
289     int                                         syncTime;                                       // Sync interval
290     boolean                                     syncRunning;                            // Is sync running?
291     boolean                                     automaticSync;                          // do sync automatically?
292     QTreeWidgetItem                     attributeTreeSelected;
293
294     QAction                             prevButton;                                     // Go to the previous item viewed
295     QAction                             nextButton;                                     // Go to the next item in the history
296     QAction                             downButton;                                     // Go to the next item in the list
297     QAction                             upButton;                                       // Go to the prev. item in the list;
298     QAction                             synchronizeButton;                      // Synchronize with Evernote
299     QAction                             allNotesButton;                         // Reset & view all notes
300     QTimer                              synchronizeAnimationTimer;      // Timer to change animation button
301     int                                 synchronizeIconAngle;           // Used to rotate sync icon
302     QAction                     printButton;                            // Print Button
303     QAction                             tagButton;                                      // Tag edit button
304     QAction                             attributeButton;                        // Attribute information button
305     QAction                     emailButton;                            // Email button
306     QAction                     deleteButton;                           // Delete button
307     QAction                             newButton;                                      // new Note Button;
308     QSpinBox                    zoomSpinner;                            // Zoom zoom
309     QAction                             searchClearButton;                      // Clear the search field
310     
311     SearchPanel                 searchLayout;                           // Widget to hold search field, zoom, & quota
312     
313     QSplitter                   mainLeftRightSplitter;          // main splitter for left/right side
314     QSplitter                   leftSplitter1;                          // first left hand splitter
315     QSplitter                   browserIndexSplitter;           // splitter between note index & note text
316     
317     QFileSystemWatcher  importKeepWatcher;                      // Watch & keep auto-import
318     QFileSystemWatcher  importDeleteWatcher;            // Watch & Delete auto-import
319     List<String>                importedFiles;                          // History of imported files (so we don't import twice)
320     
321     OnlineNoteHistory   historyWindow;                          // online history window 
322     List<NoteVersionId> versions;                                       // history versions
323     
324     QTimer                              threadMonitorTimer;                     // Timer to watch threads.
325     int                                 dbThreadDeadCount=0;            // number of consecutive dead times for the db thread
326     int                                 syncThreadDeadCount=0;          // number of consecutive dead times for the sync thread
327     int                                 indexThreadDeadCount=0;         // number of consecutive dead times for the index thread
328     int                                 notebookThreadDeadCount=0;      // number of consecutive dead times for the notebook thread
329     int                                 tagDeadCount=0;                         // number of consecutive dead times for the tag thread
330     int                                 trashDeadCount=0;                       // number of consecutive dead times for the trash thread
331     int                                 saveThreadDeadCount=0;          // number of consecutive dead times for the save thread
332     int                                 enRelatedNotesThreadDeadCount=0;        // number of consecutive dead times for the EvernoteRelatedNotes Thread
333     boolean                             disableTagThreadCheck=false;
334     boolean                             disableNotebookThreadCheck=false;
335     boolean                             disableTrashThreadCheck=false;
336     boolean                             disableSaveThreadCheck=false;
337     boolean                             disableSyncThreadCheck=false;
338     boolean                             disableIndexThreadCheck=false;
339     boolean                             disableENRelatedNotesThreadCheck=false;
340     
341     HashMap<String, String>             noteCache;                      // Cash of note content 
342     HashMap<String, Boolean>    readOnlyCache;          // List of cashe notes that are read-only
343     HashMap<String, Boolean>    inkNoteCache;           // List of cache notes that are ink notes 
344         HashMap<Integer, ArrayList<String>> historyGuids;  // タブごとの以前見たノートのGUID
345         HashMap<Integer, Integer> historyPosition; // Position within the viewed items
346         HashMap<Integer, Boolean> fromHistory; // Is this from the history queue?
347         
348     String                              trashNoteGuid;                          // Guid to restore / set into or out of trash to save position
349     List<Thumbnailer>   thumbGenerators;                                // generate preview image
350     ThumbnailViewer             thumbnailViewer;                        // View preview thumbnail; 
351     boolean                             encryptOnShutdown;                      // should I encrypt when I close?
352     boolean                             decryptOnShutdown;                      // should I decrypt on shutdown;
353     String                              encryptCipher;                          // What cipher should I use?
354     //Signal0                   minimizeToTray;
355     boolean                             windowMaximized = false;        // Keep track of the window state for restores
356     List<String>                pdfReadyQueue;                          // Queue of PDFs that are ready to be rendered.
357     List<QPixmap>               syncIcons;                                      // Array of icons used in sync animation
358     private boolean             closeAction = false;            // Used to say when to close or when to minimize
359     private static Logger log = Logger.getLogger(NeverNote.class); 
360     private String              saveLastPath;                           // last path we used
361     private final QTimer                messageTimer;                           // Timer to clear the status message.
362     private QTimer              blockTimer;
363     BrowserWindow               blockingWindow;
364     
365         private final TabBrowserWidget tabBrowser;                              // ブラウザウィンドウをタブ化
366         private final HashMap<Integer, TabBrowse> tabWindows;   // タブウィンドウ
367         private final RensoNoteListDock rensoNoteListDock;              // 連想ノートリストドックウィジェット
368         ClipBoardObserver cbObserver;
369         String rensoNotePressedItemGuid;
370         
371     String iconPath = new String("classpath:cx/fbn/nevernote/icons/");
372         
373         
374     //***************************************************************
375     //***************************************************************
376     //** Constructor & main entry point
377     //***************************************************************
378     //***************************************************************
379     // Application Constructor  
380         @SuppressWarnings("static-access")
381         public NeverNote(DatabaseConnection dbConn)  {
382                 cbObserver = new ClipBoardObserver();
383                 
384                 conn = dbConn;          
385                 if (conn.getConnection() == null) {
386                         String msg = new String(tr("Unable to connect to the database.\n\nThe most probable reason is that some other process\n" +
387                                 "is accessing the database or NeighborNote is already running.\n\n" +
388                                 "Please end any other process or shutdown the other NeighborNote before starting.\n\nExiting program."));
389                         
390             QMessageBox.critical(null, tr("Database Connection Error") ,msg);
391                         System.exit(16);
392                 }
393                 setObjectName("mainWindow");
394 //              thread().setPriority(Thread.MAX_PRIORITY);
395                 
396                 logger = new ApplicationLogger("nevernote.log");
397                 logger.log(logger.HIGH, "Starting Application");
398                 
399                 decryptOnShutdown = false;
400                 encryptOnShutdown = false;
401                 conn.checkDatabaseVersion();
402                 
403                 
404                 
405                 // Start building the invalid XML tables
406                 Global.invalidElements = conn.getInvalidXMLTable().getInvalidElements();
407                 List<String> elements = conn.getInvalidXMLTable().getInvalidAttributeElements();
408                 
409                 for (int i=0; i<elements.size(); i++) {
410                         Global.invalidAttributes.put(elements.get(i), conn.getInvalidXMLTable().getInvalidAttributes(elements.get(i)));
411                 }
412                 
413                 logger.log(logger.EXTREME, "Starting GUI build");
414
415                 QTranslator nevernoteTranslator = new QTranslator();
416                 nevernoteTranslator.load(Global.getFileManager().getTranslateFilePath("neighbornote_" + QLocale.system().name() + ".qm"));
417                 QApplication.instance().installTranslator(nevernoteTranslator);
418
419                 Global.originalPalette = QApplication.palette();
420                 QApplication.setStyle(Global.getStyle());
421                 if (Global.useStandardPalette())
422                         QApplication.setPalette(QApplication.style().standardPalette());
423         setWindowTitle(tr("NeighborNote"));
424
425         mainLeftRightSplitter = new QSplitter();
426                 mainLeftRightSplitter.setOrientation(Qt.Orientation.Horizontal);
427                 
428         setCentralWidget(mainLeftRightSplitter);
429         leftSplitter1 = new QSplitter();
430         leftSplitter1.setOrientation(Qt.Orientation.Vertical);
431                 
432         browserIndexSplitter = new QSplitter();
433         browserIndexSplitter.setOrientation(Qt.Orientation.Vertical);
434         
435         //* Setup threads & thread timers
436 //        int indexRunnerCount = Global.getIndexThreads();
437 //       indexRunnerCount = 1;
438         QThreadPool.globalInstance().setMaxThreadCount(Global.threadCount);     // increase max thread count
439
440                 logger.log(logger.EXTREME, "Building list manager");
441         listManager = new ListManager(conn, logger);
442         
443                 logger.log(logger.EXTREME, "Building index runners & timers");
444                 indexRunner = new IndexRunner("indexRunner.log",
445                                 Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(),
446                                 Global.getResourceDatabaseUrl(),
447                                 Global.getBehaviorDatabaseUrl(), Global.getDatabaseUserid(),
448                                 Global.getDatabaseUserPassword(), Global.cipherPassword);
449                 
450                 indexThread = new QThread(indexRunner, "Index Thread");
451         indexRunner.indexAttachmentsLocally = Global.indexAttachmentsLocally();
452         indexRunner.indexImageRecognition = Global.indexImageRecognition();
453 //        indexRunner.indexNoteBody = Global.indexNoteBody();
454 //        indexRunner.indexNoteTitle = Global.indexNoteTitle();
455 //        indexRunner.specialIndexCharacters = Global.getSpecialIndexCharacters();
456                 indexThread.start();
457                 
458         synchronizeAnimationTimer = new QTimer();
459         synchronizeAnimationTimer.timeout.connect(this, "updateSyncButton()");
460         
461                 indexTimer = new QTimer();
462                 indexTime = 1000*Global.getIndexThreadSleepInterval();  
463                 indexTimer.start(indexTime);  // Start indexing timer
464                 indexTimer.timeout.connect(this, "indexTimer()");
465                 indexDisabled = false;
466                 indexRunning = false;
467                                 
468                 logger.log(logger.EXTREME, "Setting sync thread & timers");
469                 syncThreadsReady=1;
470                 syncRunner = new SyncRunner("syncRunner.log", Global.getDatabaseUrl(),
471                                 Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(),
472                                 Global.getBehaviorDatabaseUrl(), Global.getDatabaseUserid(),
473                                 Global.getDatabaseUserPassword(), Global.cipherPassword);
474                 
475                 syncTime = new SyncTimes().timeValue(Global.getSyncInterval());
476                 syncTimer = new QTimer();
477                 syncTimer.timeout.connect(this, "syncTimer()");
478         syncRunner.status.message.connect(this, "setMessage(String)");
479         syncRunner.syncSignal.finished.connect(this, "syncThreadComplete(Boolean)");
480         syncRunner.syncSignal.errorDisconnect.connect(this, "remoteErrorDisconnect()");
481         syncRunner.limitSignal.rateLimitReached.connect(this, "informRateLimit(Integer)");
482         syncRunning = false;    
483                 if (syncTime > 0) {
484                         automaticSync = true;
485                         syncTimer.start(syncTime*60*1000);
486                 } else {
487                         automaticSync = false;
488                         syncTimer.stop();
489                 }
490                 syncRunner.setEvernoteUpdateCount(Global.getEvernoteUpdateCount());
491                 syncThread = new QThread(syncRunner, "Synchronization Thread");
492                 syncThread.start();
493                 
494                 
495                 logger.log(logger.EXTREME, "Starting thumnail thread");
496                 pdfReadyQueue = new ArrayList<String>();
497                 thumbnailRunner = new ThumbnailRunner("thumbnailRunner.log",
498                                 Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(),
499                                 Global.getResourceDatabaseUrl(),
500                                 Global.getBehaviorDatabaseUrl(), Global.getDatabaseUserid(),
501                                 Global.getDatabaseUserPassword(), Global.cipherPassword);
502                 
503                 thumbnailThread = new QThread(thumbnailRunner, "Thumbnail Thread");
504                 thumbnailRunner.noteSignal.thumbnailPageReady.connect(this, "thumbnailHTMLReady(String,QByteArray,Integer)");
505                 thumbnailThread.start();
506                 thumbGenerators = new ArrayList<Thumbnailer>();
507                 thumbnailTimer = new QTimer();
508                 thumbnailTimer.timeout.connect(this, "thumbnailTimer()");
509                 thumbnailTimer();
510                 thumbnailTimer.setInterval(500*1000);  // Thumbnail every minute
511                 thumbnailTimer.start();
512                 
513 //              debugTimer = new QTimer();
514 //              debugTimer.timeout.connect(this, "debugDirty()");
515 //              debugTimer.start(1000*60);
516                 
517                 logger.log(logger.EXTREME, "Starting authentication timer");
518                 authTimer = new QTimer();
519                 authTimer.timeout.connect(this, "authTimer()");
520                 authTimer.start(1000*60*15);
521                 syncRunner.syncSignal.authRefreshComplete.connect(this, "authRefreshComplete(boolean)");
522                 
523                 logger.log(logger.EXTREME, "Setting save note timer");
524                 saveTimer = new QTimer();
525                 saveTimer.timeout.connect(this, "saveNote()");
526                 if (Global.getAutoSaveInterval() > 0) {
527                         saveTimer.setInterval(1000*60*Global.getAutoSaveInterval()); 
528                         saveTimer.start();
529                 }
530                 listManager.saveRunner.noteSignals.noteSaveRunnerError.connect(this, "saveRunnerError(String, String)");
531                 
532                 logger.log(logger.EXTREME, "Starting external file monitor timer");
533                 externalFileSaveTimer = new QTimer();
534                 externalFileSaveTimer.timeout.connect(this, "externalFileEditedSaver()");
535                 externalFileSaveTimer.setInterval(1000*5);   // save every 5 seconds;
536                 externalFiles = new ArrayList<String>();
537                 importFilesDelete = new ArrayList<String>();
538                 importFilesKeep = new ArrayList<String>();
539                 externalFileSaveTimer.start();
540                 
541         notebookTree = new NotebookTreeWidget(conn);
542         attributeTree = new AttributeTreeWidget();
543         tagTree = new TagTreeWidget(conn);
544         savedSearchTree = new SavedSearchTreeWidget();
545         trashTree = new TrashTreeWidget();
546                 noteTableView = new TableView(logger, listManager, this);     
547         
548         searchField = new QComboBox();
549         searchField.setObjectName("searchField");
550         //setStyleSheet("QComboBox#searchField { background-color: yellow }");
551         searchField.setEditable(true);
552         searchField.activatedIndex.connect(this, "searchFieldChanged()");
553         searchField.setDuplicatesEnabled(false);
554         searchField.editTextChanged.connect(this,"searchFieldTextChanged(String)");
555         searchShortcut = new QShortcut(this);
556         setupShortcut(searchShortcut, "Focus_Search");
557         searchShortcut.activated.connect(this, "focusSearch()");
558         
559         quotaBar = new QuotaProgressBar();
560         // Setup the zoom
561         zoomSpinner = new QSpinBox();
562         zoomSpinner.setMinimum(10);
563         zoomSpinner.setMaximum(1000);
564         zoomSpinner.setAccelerated(true);
565         zoomSpinner.setSingleStep(10);
566         zoomSpinner.setValue(100);
567         zoomSpinner.valueChanged.connect(this, "zoomChanged()");
568         
569         searchLayout = new SearchPanel(searchField, quotaBar, notebookTree, zoomSpinner);
570         
571         
572         QGridLayout leftGrid = new QGridLayout();
573         leftSplitter1.setContentsMargins(5, 0, 0, 7);
574         leftSplitter1.setLayout(leftGrid);
575         leftGrid.addWidget(searchLayout,1,1);
576         leftGrid.addWidget(tagTree,2,1);
577         leftGrid.addWidget(attributeTree,3,1);
578         leftGrid.addWidget(savedSearchTree,4,1);
579         leftGrid.addWidget(trashTree,5, 1);
580         
581         // Setup the browser window
582         noteCache = new HashMap<String,String>();
583         readOnlyCache = new HashMap<String, Boolean>();
584         inkNoteCache = new HashMap<String, Boolean>();
585         browserWindow = new BrowserWindow(conn, cbObserver);
586
587                 // 下から移動してきた。
588                 historyGuids = new HashMap<Integer, ArrayList<String>>();
589                 historyPosition = new HashMap<Integer, Integer>();
590                 fromHistory = new HashMap<Integer, Boolean>();
591                 
592                 // タブブラウザ作成
593                 tabWindows = new HashMap<Integer, TabBrowse>();
594                 tabBrowser = new TabBrowserWidget(this);
595                 tabBrowser.setStyleSheet("QTabBar::tab{width:150px;}");
596                 tabBrowser.setMovable(true);
597                 tabBrowser.setTabsClosable(true);
598                 TabBrowse tab = new TabBrowse(conn, tabBrowser, cbObserver);
599                 browserWindow = tab.getBrowserWindow();
600                 int index = tabBrowser.addNewTab(tab, "");
601                 tabWindows.put(index, tab);
602                 tabBrowser.currentChanged.connect(this, "tabWindowChanged(int)");
603                 tabBrowser.tabCloseRequested.connect(this, "tabCloseRequested(int)");
604                 
605                 noteDirty = new HashMap<Integer, Boolean>();
606                 noteDirty.put(index, false);
607                 
608                 inkNote = new HashMap<Integer, Boolean>();
609                 readOnly = new HashMap<Integer, Boolean>();
610
611                 // 履歴記録のハッシュマップを初期化
612                 historyGuids.put(index, new ArrayList<String>());
613                 historyPosition.put(index, 0);
614                 fromHistory.put(index, false);
615                 
616         mainLeftRightSplitter.addWidget(leftSplitter1);
617         mainLeftRightSplitter.addWidget(browserIndexSplitter);
618         
619                 // 連想ノートリストをセットアップ
620         rensoNoteListDock = new RensoNoteListDock(conn, this, syncRunner, iconPath, tr("Renso Note List"));
621                 addDockWidget(DockWidgetArea.RightDockWidgetArea, rensoNoteListDock);
622
623                 if (Global.getListView() == Global.View_List_Wide) {
624                         browserIndexSplitter.addWidget(noteTableView);
625                         browserIndexSplitter.addWidget(tabBrowser);
626                 } else {
627                         mainLeftRightSplitter.addWidget(noteTableView);
628                         mainLeftRightSplitter.addWidget(tabBrowser);
629                 }
630         
631         // Setup the thumbnail viewer
632         thumbnailViewer = new ThumbnailViewer();
633         thumbnailViewer.upArrow.connect(this, "upAction()");
634         thumbnailViewer.downArrow.connect(this, "downAction()");
635         thumbnailViewer.leftArrow.connect(this, "nextViewedAction()");
636         thumbnailViewer.rightArrow.connect(this, "previousViewedAction()");
637         
638         //Setup external browser manager
639         externalWindows = new HashMap<String, ExternalBrowse>();
640
641         listManager.loadNotesIndex();
642         initializeNotebookTree();
643         initializeTagTree();
644         initializeSavedSearchTree();
645         attributeTree.itemClicked.connect(this, "attributeTreeClicked(QTreeWidgetItem, Integer)");
646         attributeTreeSelected = null;
647         initializeNoteTable();    
648
649                 selectedNoteGUIDs = new ArrayList<String>();
650                 statusBar = new QStatusBar();
651                 setStatusBar(statusBar);
652                 menuBar = new MainMenuBar(this);
653                 emitLog = new ArrayList<String>();
654                 
655                 tagTree.setDeleteAction(menuBar.tagDeleteAction);
656                 tagTree.setMergeAction(menuBar.tagMergeAction);
657                 tagTree.setEditAction(menuBar.tagEditAction);
658                 tagTree.setAddAction(menuBar.tagAddAction);
659                 tagTree.setIconAction(menuBar.tagIconAction);
660                 tagTree.setVisible(Global.isWindowVisible("tagTree"));
661                 leftSplitter1.setVisible(Global.isWindowVisible("leftPanel"));
662                 tagTree.noteSignal.tagsAdded.connect(this, "tagsAdded(String, String)");
663                 menuBar.hideTags.setChecked(Global.isWindowVisible("tagTree"));
664                 listManager.tagSignal.listChanged.connect(this, "reloadTagTree()");
665                 
666                 if (!Global.isWindowVisible("zoom")) {
667                         searchLayout.hideZoom();
668                         menuBar.hideZoom.setChecked(false);
669                 } 
670         
671                 notebookTree.setDeleteAction(menuBar.notebookDeleteAction);
672                 notebookTree.setEditAction(menuBar.notebookEditAction);
673                 notebookTree.setAddAction(menuBar.notebookAddAction);
674                 notebookTree.setIconAction(menuBar.notebookIconAction);
675                 notebookTree.setStackAction(menuBar.notebookStackAction);
676                 notebookTree.setPublishAction(menuBar.notebookPublishAction);
677                 notebookTree.setShareAction(menuBar.notebookShareAction);
678                 notebookTree.setVisible(Global.isWindowVisible("notebookTree"));
679                 notebookTree.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
680                 notebookTree.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)");
681             notebookTree.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)");
682                 menuBar.hideNotebooks.setChecked(Global.isWindowVisible("notebookTree"));
683
684                 savedSearchTree.setAddAction(menuBar.savedSearchAddAction);
685                 savedSearchTree.setEditAction(menuBar.savedSearchEditAction);
686                 savedSearchTree.setDeleteAction(menuBar.savedSearchDeleteAction);
687                 savedSearchTree.setIconAction(menuBar.savedSearchIconAction);
688                 savedSearchTree.itemSelectionChanged.connect(this, "updateSavedSearchSelection()");
689                 savedSearchTree.setVisible(Global.isWindowVisible("savedSearchTree"));
690                 menuBar.hideSavedSearches.setChecked(Global.isWindowVisible("savedSearchTree"));
691                 
692                 // noteTableViewに新しいタブで開くを追加
693                 noteTableView.setOpenNewTabAction(menuBar.noteOpenNewTab);
694                         
695                 noteTableView.setAddAction(menuBar.noteAdd);
696                 
697                 // noteTableViewに新しいタブでノート追加を追加
698                 noteTableView.setAddNoteNewTabAction(menuBar.noteAddNewTab);
699                 
700                 noteTableView.setDeleteAction(menuBar.noteDelete);
701                 noteTableView.setRestoreAction(menuBar.noteRestoreAction);
702                 noteTableView.setNoteDuplicateAction(menuBar.noteDuplicateAction);
703                 noteTableView.setNoteHistoryAction(menuBar.noteOnlineHistoryAction);
704                 noteTableView.noteSignal.titleColorChanged.connect(this, "titleColorChanged(Integer)");
705                 noteTableView.noteSignal.notePinned.connect(this, "notePinned()");
706                 noteTableView.setMergeNotesAction(menuBar.noteMergeAction);
707                 noteTableView.setCopyAsUrlAction(menuBar.noteCopyAsUrlAction);
708                 noteTableView.doubleClicked.connect(this, "listDoubleClick()");
709                 listManager.trashSignal.countChanged.connect(trashTree, "updateCounts(Integer)");
710                 
711                 quotaBar.setMouseClickAction(menuBar.accountAction);
712                 
713                 trashTree.load();
714         trashTree.itemSelectionChanged.connect(this, "trashTreeSelection()");
715                 trashTree.setEmptyAction(menuBar.emptyTrashAction);
716                 trashTree.setVisible(Global.isWindowVisible("trashTree"));
717                 menuBar.hideTrash.setChecked(Global.isWindowVisible("trashTree"));
718                 trashTree.updateCounts(listManager.getTrashCount());
719                 attributeTree.setVisible(Global.isWindowVisible("attributeTree"));
720                 menuBar.hideAttributes.setChecked(Global.isWindowVisible("attributeTree"));
721
722                 noteTableView.setVisible(Global.isWindowVisible("noteList"));
723                 menuBar.hideNoteList.setChecked(Global.isWindowVisible("noteList"));
724                 
725                 if (!Global.isWindowVisible("editorButtonBar")) {
726                         menuBar.showEditorBar.setChecked(false);
727                         toggleEditorButtonBar();
728                 }
729                 
730                 if (!Global.isWindowVisible("leftPanel"))
731                         menuBar.hideLeftSide.setChecked(true);
732                 
733                 if (Global.isWindowVisible("noteInformation")) {
734                         menuBar.noteAttributes.setChecked(true);
735                         toggleNoteInformation();
736                 }
737                 
738                 quotaBar.setVisible(Global.isWindowVisible("quota"));
739                 // IFIXED quotaBar.isVisible() → Global.isWindowVisible("quota")
740                 // なぜかquotaBar.isVisible()が常にfalseを返すようなので修正
741                 if (!Global.isWindowVisible("quota"))
742                         menuBar.hideQuota.setChecked(false);
743                 
744                 searchField.setVisible(Global.isWindowVisible("searchField"));
745                 // IFIXED !searchField.isVisible() → !Global.isWindowVisible("searchField")
746                 // なぜかsearchField.isVisible()が常にfalseを返すようなので修正
747                 if (!Global.isWindowVisible("searchField"))
748                         menuBar.hideSearch.setChecked(false);
749                 
750                 if (searchField.isHidden() && quotaBar.isHidden() && zoomSpinner.isHidden() && notebookTree.isHidden())
751                         searchLayout.hide();
752                 
753                 setMenuBar(menuBar);
754                 setupToolBar();
755                 find = new FindDialog();
756                 find.getOkButton().clicked.connect(this, "doFindText()");
757                 
758                 // Setup the tray icon menu bar
759                 trayShowAction = new QAction(tr("Show/Hide"), this);
760                 trayExitAction = new QAction(tr("Exit"), this);
761                 trayAddNoteAction = new QAction(tr("Add Note"), this);
762                 
763                 trayExitAction.triggered.connect(this, "closeNeverNote()");
764                 trayAddNoteAction.triggered.connect(this, "addNote()");
765                 trayShowAction.triggered.connect(this, "trayToggleVisible()");
766                 
767                 trayMenu = new QMenu(this);
768                 trayMenu.addAction(trayAddNoteAction);
769                 trayMenu.addAction(trayShowAction);
770                 trayMenu.addAction(trayExitAction);
771                 
772                 
773                 trayIcon = new QSystemTrayIcon(this);
774                 trayIcon.setToolTip(tr("NeighborNote"));
775                 trayIcon.setContextMenu(trayMenu);
776                 trayIcon.activated.connect(this, "trayActivated(com.trolltech.qt.gui.QSystemTrayIcon$ActivationReason)");
777
778                 currentNoteGuid="";
779                 currentNoteGuid = Global.getLastViewedNoteGuid();
780                 if (currentNoteGuid.equals(""))
781                         currentNote = new Note();
782                 
783                 /* 上に移動したのでここには不要
784                  * historyGuids = new ArrayList<String>();
785                  * historyPosition = 0;
786                  * fromHistory = false;
787                  */
788                 
789                 if (!currentNoteGuid.trim().equals("")) {
790                         currentNote = conn.getNoteTable().getNote(currentNoteGuid, true,true,false,false,true);
791                 }
792                 
793                 noteIndexUpdated(true);
794                 showColumns();
795                 menuBar.showEditorBar.setChecked(Global.isWindowVisible("editorButtonBar"));
796                 if (menuBar.showEditorBar.isChecked())
797                 showEditorButtons(browserWindow);
798                 tagIndexUpdated(true);
799                 savedSearchIndexUpdated();
800                 notebookIndexUpdated();
801                 updateQuotaBar();
802         setupSyncSignalListeners();        
803         setupBrowserSignalListeners();
804         setupIndexListeners();
805               
806         
807         tagTree.tagSignal.listChanged.connect(this, "tagIndexUpdated()");
808         tagTree.showAllTags(true);
809
810                 QIcon appIcon = new QIcon(iconPath+"nevernote.png");
811                 if (QSystemTrayIcon.isSystemTrayAvailable()) {
812                         setWindowIcon(appIcon);
813                         trayIcon.setIcon(appIcon);
814                         if (Global.showTrayIcon() || Global.minimizeOnClose())
815                                 trayIcon.show();
816                         else
817                                 trayIcon.hide();
818                 }
819         
820         scrollToGuid(currentNoteGuid);
821         if (Global.automaticLogin()) {
822                 remoteConnect();
823                 if (Global.isConnected)
824                         syncTimer();
825         }
826         setupFolderImports();
827         
828         loadStyleSheet();
829         restoreWindowState(true);
830         
831         if (Global.mimicEvernoteInterface) {
832                 notebookTree.selectGuid("");
833         }
834         
835         threadMonitorTimer = new QTimer();
836         threadMonitorTimer.timeout.connect(this, "threadMonitorCheck()");
837         threadMonitorTimer.start(1000*10);  // Check for threads every 10 seconds;              
838         
839                 // IFIXED 恐らく不要なのでコメントアウト
840                 /*
841                  * historyGuids.add(currentNoteGuid);
842                  * historyPosition = 1;
843                  */
844         
845         menuBar.blockSignals(true);
846         menuBar.narrowListView.blockSignals(true);
847         menuBar.wideListView.blockSignals(true);
848         if (Global.getListView() == Global.View_List_Narrow) { 
849                 menuBar.narrowListView.setChecked(true);
850         }
851         else{ 
852                 menuBar.wideListView.setChecked(true);
853         }
854         menuBar.blockSignals(false);
855         menuBar.narrowListView.blockSignals(false);
856         menuBar.wideListView.blockSignals(false);
857         
858                 // IFIXED 上に同じコードがあるのでコメントアウト
859                 /*
860                  * if (Global.getListView() == Global.View_List_Wide) {
861                  * browserIndexSplitter.addWidget(noteTableView);
862                  * browserIndexSplitter.addWidget(tabBrowser);
863                  * browserIndexSplitter.addWidget(browserWindow); } else {
864                  * mainLeftRightSplitter.addWidget(noteTableView);
865                  * mainLeftRightSplitter.addWidget(tabBrowser);
866                  * mainLeftRightSplitter.addWidget(browserWindow); }
867                  */
868         
869                 messageTimer = new QTimer();
870                 messageTimer.timeout.connect(this, "clearMessage()");
871                 messageTimer.setInterval(1000*15);
872                 clearMessage();
873         
874         int sortCol = Global.getSortColumn();
875                 int sortOrder = Global.getSortOrder();
876                 noteTableView.proxyModel.blocked = true;
877                 // We sort the table twice to fix a bug.  For some reaosn the table won't sort properly if it is in narrow
878                 // list view and sorted descending on the date  created.  By sorting it twice it forces the proper sort.  Ugly.
879                 if (sortCol == 0 && sortOrder == 1 && Global.getListView() == Global.View_List_Narrow) 
880                         noteTableView.sortByColumn(sortCol, SortOrder.resolve(0));   
881                 noteTableView.sortByColumn(sortCol, SortOrder.resolve(sortOrder));
882                 noteTableView.proxyModel.blocked = false;
883                 noteTableView.proxyModel.sortChanged.connect(this, "tableSortOrderChanged(Integer,Integer)");
884                 
885                 // Set the startup notebook
886         String defaultNotebook = Global.getStartupNotebook();
887         if (!defaultNotebook.equals("AllNotebooks") && !defaultNotebook.equals("")) {
888                 for (int k=0; k<listManager.getNotebookIndex().size(); k++) {
889                         if (listManager.getNotebookIndex().get(k).isDefaultNotebook()) {
890                                 notebookTree.clearSelection();
891                                 notebookTree.selectGuid(listManager.getNotebookIndex().get(k).getGuid());
892                                 notebookTree.selectionSignal.emit();
893                         }
894                 }
895         }
896                 
897                 if (Global.checkVersionUpgrade()) {
898                         checkForUpdates();
899                 }
900                 
901                 if (currentNoteGuid == null || currentNoteGuid.equals("")) {
902                         menuBar.noteAddNewTab.setEnabled(false);
903                 }
904         }
905         
906         
907         public void debugDirty() {
908                 List<Note> dirty = conn.getNoteTable().getDirty();
909                 logger.log(logger.LOW, "------ Dirty Notes List Begin ------");
910                 for (int i=0; i<dirty.size(); i++) {
911                         logger.log(logger.LOW, "GUID: " +dirty.get(i).getGuid() + " Title:" + dirty.get(i).getTitle());
912                 }
913                 logger.log(logger.LOW, "------ Dirty Notes List End ------");
914         }
915                 
916         // Main entry point
917         public static void main(String[] args) {
918                 log.setLevel(Level.FATAL);
919                 QApplication.initialize(args);
920                 QPixmap pixmap = new QPixmap("classpath:cx/fbn/nevernote/icons/splash_logo.png");
921                 QSplashScreen splash = new QSplashScreen(pixmap);
922                 boolean showSplash;
923                 
924                 DatabaseConnection dbConn;
925
926         try {
927             initializeGlobalSettings(args);
928
929             showSplash = Global.isWindowVisible("SplashScreen");
930             if (showSplash)
931                 splash.show();
932
933             dbConn = setupDatabaseConnection();
934
935             // Must be last stage of setup - only safe once DB is open hence we know we are the only instance running
936             Global.getFileManager().purgeResDirectory(true);
937
938         } catch (InitializationException e) {
939             // Fatal
940             e.printStackTrace();
941             QMessageBox.critical(null, "Startup error", "Aborting: " + e.getMessage());
942             return;
943         }
944         
945                 // Setup proxy crap
946                 String proxyUrl = Global.getProxyValue("url");
947                 String proxyPort = Global.getProxyValue("port");
948                 String proxyUserid = Global.getProxyValue("userid");
949                 String proxyPassword = Global.getProxyValue("password");
950                 boolean proxySet = false;
951                 QNetworkProxy proxy = new QNetworkProxy();
952                 proxy.setType(ProxyType.HttpProxy);
953                 if (!proxyUrl.trim().equals("")) {
954                         System.out.println("Proxy URL found: " +proxyUrl);
955                         proxySet = true;
956                         proxy.setHostName(proxyUrl);
957                 }
958                 if (!proxyPort.trim().equals("")) {
959                         System.out.println("Proxy Port found: " +proxyPort);
960                         proxySet = true;
961                         proxy.setPort(Integer.parseInt(proxyPort));
962                 }
963                 if (!proxyUserid.trim().equals("")) {
964                         System.out.println("Proxy Userid found: " +proxyUserid);
965                         proxySet = true;
966                         proxy.setUser(proxyUserid);
967                 }
968                 if (!proxyPassword.trim().equals("")) {
969                         System.out.println("Proxy URL found: " +proxyPassword);
970                         proxySet = true;
971                         proxy.setPassword(proxyPassword);
972                 }
973                 if (proxySet) {
974                         QNetworkProxy.setApplicationProxy(proxy);
975                 }
976                         
977
978         NeverNote application = new NeverNote(dbConn);
979                 if (Global.syncOnly) {
980                         System.out.println("Performing synchronization only.");
981                         application.remoteConnect();
982                         if (Global.isConnected) {
983                                 application.syncRunner.syncNeeded = true;
984                                 application.syncRunner.addWork("SYNC");
985                                 application.syncRunner.addWork("STOP");
986                                 while(!application.syncRunner.isIdle());
987                                 application.closeNeverNote();
988                         }
989                         return;
990                 }
991
992                 application.setAttribute(WidgetAttribute.WA_DeleteOnClose, true);
993                 if (Global.startMinimized()) 
994                         application.showMinimized();
995                 else {
996                         if (Global.wasWindowMaximized())
997                                 application.showMaximized();
998                         else
999                                 application.show();
1000                 }
1001                 
1002                 if (showSplash)
1003                         splash.finish(application);
1004                 QApplication.exec();
1005                 System.out.println("Goodbye.");
1006                 QApplication.exit();
1007         }
1008
1009     /**
1010      * Open the internal database, or create if not present
1011      *
1012      * @throws InitializationException when opening the database fails, e.g. because another process has it locked
1013      */
1014     private static DatabaseConnection setupDatabaseConnection() throws InitializationException {
1015         ApplicationLogger logger = new ApplicationLogger("nevernote-database.log");
1016         
1017         File f = Global.getFileManager().getDbDirFile(Global.databaseName + ".h2.db");
1018         File fr = Global.getFileManager().getDbDirFile(Global.resourceDatabaseName + ".h2.db");
1019                 // IFIXED resourceDatabaseNameになっていたので修正
1020                 File fi = Global.getFileManager().getDbDirFile(Global.indexDatabaseName + ".h2.db");
1021                 File fb = Global.getFileManager().getDbDirFile(Global.behaviorDatabaseName + ".h2.db");
1022                                 
1023                 if (!f.exists())
1024                         Global.setDatabaseUrl("");
1025                 if (!fr.exists())
1026                         Global.setResourceDatabaseUrl("");              
1027                 if (!fi.exists())
1028                         Global.setIndexDatabaseUrl(""); 
1029                 if (!fb.exists())
1030                         Global.setBehaviorDatabaseUrl("");
1031         
1032         if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") > -1) {
1033             boolean goodCheck = false;
1034             while (!goodCheck) {
1035                 DatabaseLoginDialog dialog = new DatabaseLoginDialog();
1036                 dialog.exec();
1037                 if (!dialog.okPressed())
1038                     System.exit(0);
1039                 Global.cipherPassword = dialog.getPassword();
1040                 goodCheck = databaseCheck(Global.getDatabaseUrl(), Global.getDatabaseUserid(),
1041                         Global.getDatabaseUserPassword(), Global.cipherPassword);
1042             }
1043         }
1044         DatabaseConnection dbConn = new DatabaseConnection(logger,Global.getDatabaseUrl(), 
1045                         Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), Global.getBehaviorDatabaseUrl(),
1046                         Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword, 0);
1047        return dbConn;
1048     }
1049     
1050     // Encrypt the database upon shutdown
1051     private void encryptOnShutdown() {
1052         String dbPath= Global.getFileManager().getDbDirPath("");
1053         try {
1054                 
1055                 Statement st = conn.getConnection().createStatement();  
1056                 st.execute("shutdown");
1057                 st = conn.getResourceConnection().createStatement();
1058                 st.execute("shutdown");
1059                 st = conn.getIndexConnection().createStatement();
1060                 st.execute("shutdown");
1061                 st = conn.getBehaviorConnection().createStatement();
1062                 st.execute("shutdown");
1063                 
1064                 if (QMessageBox.question(this, tr("Are you sure"), 
1065                                 tr("Are you sure you wish to encrypt the database?"),
1066                                 QMessageBox.StandardButton.Yes, 
1067                                 QMessageBox.StandardButton.No) == StandardButton.Yes.value()) {
1068                         ChangeFileEncryption.execute(dbPath, "NeverNote", encryptCipher, null, Global.cipherPassword.toCharArray(), true);
1069                         ChangeFileEncryption.execute(dbPath, "Resources", encryptCipher, null, Global.cipherPassword.toCharArray(), true);
1070                         ChangeFileEncryption.execute(dbPath, "Index", encryptCipher, null, Global.cipherPassword.toCharArray(), true);
1071                         ChangeFileEncryption.execute(dbPath, "Behavior", encryptCipher, null, Global.cipherPassword.toCharArray(), true);
1072                         
1073                         Global.setDatabaseUrl(Global.getDatabaseUrl() + ";CIPHER="+encryptCipher);
1074                         Global.setResourceDatabaseUrl(Global.getResourceDatabaseUrl() + ";CIPHER="+encryptCipher);
1075                         Global.setIndexDatabaseUrl(Global.getIndexDatabaseUrl() + ";CIPHER="+encryptCipher);
1076                                 Global.setBehaviorDatabaseUrl(Global.getBehaviorDatabaseUrl() + ";CIPHER=" + encryptCipher);
1077
1078                         QMessageBox.information(this, tr("Encryption Complete"), tr("Encryption is complete"));
1079                 }
1080         } catch (SQLException e) {
1081                         e.printStackTrace();
1082                 }       
1083     }
1084     
1085     // Decrypt the database upon shutdown
1086     private void decryptOnShutdown() {
1087         String dbPath= Global.getFileManager().getDbDirPath("");
1088         String dbName = "NeverNote";
1089         try {
1090                 Statement st = conn.getConnection().createStatement();  
1091                 st.execute("shutdown");
1092                 if (Global.getDatabaseUrl().toUpperCase().indexOf(";CIPHER=AES") > -1)
1093                         encryptCipher = "AES";
1094                 else
1095                         encryptCipher = "XTEA";
1096                 if (QMessageBox.question(this, tr("Confirmation"), tr("Are you sure", 
1097                                 "Are you sure you wish to decrypt the database?"),
1098                                 QMessageBox.StandardButton.Yes, 
1099                                 QMessageBox.StandardButton.No) == StandardButton.Yes.value()) {
1100
1101                         ChangeFileEncryption.execute(dbPath, dbName, encryptCipher, Global.cipherPassword.toCharArray(), null, true);
1102                         Global.setDatabaseUrl("");
1103                         Global.setResourceDatabaseUrl("");
1104                         Global.setIndexDatabaseUrl("");
1105                         QMessageBox.information(this, tr("Decryption Complete"), tr("Decryption is complete"));
1106                 }
1107                 } catch (SQLException e) {
1108                         e.printStackTrace();
1109                 }       
1110     }
1111     /**
1112      * Encrypt/Decrypt the local database
1113      **/
1114     public void doDatabaseEncrypt() {
1115         // The database is not currently encrypted
1116         if (Global.getDatabaseUrl().toUpperCase().indexOf("CIPHER=") == -1) {
1117                 if (QMessageBox.question(this, tr("Confirmation"), tr("Encrypting the database is used" +
1118                                 "to enhance security and is performed\nupon shutdown, but please be aware that if"+
1119                                 " you lose the password your\nis lost forever.\n\nIt is highly recommended you " +
1120                                 "perform a backup and/or fully synchronize\n prior to executing this funtction.\n\n" +
1121                                 "Do you wish to proceed?"),
1122                                 QMessageBox.StandardButton.Yes, 
1123                                 QMessageBox.StandardButton.No)==StandardButton.No.value()) {
1124                                 return;
1125                 }
1126                 DBEncryptDialog dialog = new DBEncryptDialog();
1127                 dialog.exec();
1128                 if (dialog.okPressed()) {
1129                         Global.cipherPassword = dialog.getPassword();
1130                         encryptOnShutdown  = true;
1131                         encryptCipher = dialog.getEncryptionMethod();
1132                 }
1133         } else {
1134             DBEncryptDialog dialog = new DBEncryptDialog();
1135             dialog.setWindowTitle(tr("Database Decryption"));
1136             dialog.hideEncryption();
1137             dialog.exec();
1138             if (dialog.okPressed()) {
1139                 if (!dialog.getPassword().equals(Global.cipherPassword)) {
1140                         QMessageBox.critical(null, tr("Incorrect Password"), tr("Incorrect Password"));
1141                         return;
1142                 }
1143                 decryptOnShutdown  = true;
1144                 encryptCipher = "";
1145             }
1146         }
1147         return;
1148     }
1149
1150         private static void initializeGlobalSettings(String[] args) throws InitializationException {
1151                 StartupConfig   startupConfig = new StartupConfig();
1152
1153         for (String arg : args) {
1154             String lower = arg.toLowerCase();
1155             if (lower.startsWith("--name="))
1156                startupConfig.setName(arg.substring(arg.indexOf('=') + 1));
1157             if (lower.startsWith("--home="))
1158                startupConfig.setHomeDirPath(arg.substring(arg.indexOf('=') + 1));
1159             if (lower.startsWith("--disable-viewing"))
1160                startupConfig.setDisableViewing(true);
1161             if (lower.startsWith("--sync-only=true"))
1162                 startupConfig.setSyncOnly(true);
1163         }
1164         Global.setup(startupConfig);
1165         
1166     }
1167
1168     // Exit point
1169         @Override
1170         public void closeEvent(QCloseEvent event) {     
1171                 if (Global.minimizeOnClose() && !closeAction) {
1172                         event.ignore();
1173                         hide();
1174                         return;
1175                 }
1176                 logger.log(logger.HIGH, "Entering NeverNote.closeEvent");
1177                 waitCursor(true);
1178                 
1179                 if (currentNote != null & browserWindow != null) {
1180                         if (currentNote.getTitle() != null && browserWindow != null
1181                                         && !currentNote.getTitle().equals(browserWindow.getTitle()))
1182                                 conn.getNoteTable().updateNoteTitle(currentNote.getGuid(),
1183                                                 browserWindow.getTitle());
1184                 }
1185                 
1186                 saveNote();
1187                 setMessage(tr("Beginning shutdown."));
1188                 
1189                 // Close down external windows
1190                 Collection<ExternalBrowse> windows = externalWindows.values();
1191                 Iterator<ExternalBrowse> iterator = windows.iterator();
1192                 while (iterator.hasNext()) {
1193                         ExternalBrowse browser = iterator.next();
1194                         browser.windowClosing.disconnect();
1195                         browser.close();
1196                 }
1197                 
1198                 // タブブラウザに対してクローズ処理を行う
1199                 Collection<TabBrowse> win = tabWindows.values();
1200                 Iterator<TabBrowse> it = win.iterator();
1201                 tabBrowser.currentChanged.disconnect();
1202                 tabBrowser.tabCloseRequested.disconnect();
1203                 while (it.hasNext()) {
1204                         TabBrowse browser = it.next();
1205                         browser.close();
1206                 }
1207                 
1208                 externalFileEditedSaver();
1209                 if (Global.isConnected && Global.synchronizeOnClose()) {
1210                         setMessage(tr("Performing synchronization before closing."));
1211                         syncRunner.syncNeeded = true;
1212                         syncRunner.addWork("SYNC");
1213                 } else {
1214                         syncRunner.keepRunning = false;
1215                 }
1216                 syncRunner.addWork("STOP");
1217                 setMessage("Closing Program.");
1218                 threadMonitorTimer.stop();
1219
1220                 thumbnailRunner.addWork("STOP");
1221                 indexRunner.addWork("STOP");
1222                 saveNote();
1223                 listManager.stop();
1224                 saveWindowState();
1225                 
1226                 // 連想ノートリストのEvernote関連ノート取得スレッドを終了
1227                 rensoNoteListDock.getRensoNoteList().stopThread();
1228
1229                 if (tempFiles != null)
1230                         tempFiles.clear();
1231
1232                 browserWindow.noteSignal.tagsChanged.disconnect();
1233                 browserWindow.noteSignal.titleChanged.disconnect();
1234                 browserWindow.noteSignal.noteChanged.disconnect();
1235                 browserWindow.noteSignal.notebookChanged.disconnect();
1236                 browserWindow.noteSignal.createdDateChanged.disconnect();
1237                 browserWindow.noteSignal.alteredDateChanged.disconnect();
1238                 syncRunner.searchSignal.listChanged.disconnect();
1239                 syncRunner.tagSignal.listChanged.disconnect();
1240         syncRunner.notebookSignal.listChanged.disconnect();
1241         syncRunner.noteIndexSignal.listChanged.disconnect();
1242
1243                 if (isVisible())
1244                         Global.saveWindowVisible("toolBar", toolBar.isVisible());
1245                 saveNoteColumnPositions();
1246                 saveNoteIndexWidth();
1247                 
1248                 int width = notebookTree.columnWidth(0);
1249                 Global.setColumnWidth("notebookTreeName", width);
1250                 width = tagTree.columnWidth(0);
1251                 Global.setColumnWidth("tagTreeName", width);
1252                 
1253                 Global.saveWindowMaximized(isMaximized());
1254                 Global.saveCurrentNoteGuid(currentNoteGuid);
1255                         
1256                 int sortCol = noteTableView.proxyModel.sortColumn();
1257                 int sortOrder = noteTableView.proxyModel.sortOrder().value();
1258                 Global.setSortColumn(sortCol);
1259                 Global.setSortOrder(sortOrder);
1260                 
1261                 hide();
1262                 trayIcon.hide();
1263                 Global.keepRunning = false;
1264                 try {
1265                         logger.log(logger.MEDIUM, "Waiting for indexThread to stop");
1266                         if (indexRunner.thread().isAlive())
1267                                 indexRunner.thread().join(50);
1268                         if (!indexRunner.thread().isAlive())
1269                                 logger.log(logger.MEDIUM, "Index thread has stopped");
1270                         else {
1271                                 logger.log(logger.MEDIUM, "Index thread still running - interrupting");
1272                                 indexRunner.thread().interrupt();
1273                         }
1274                 } catch (InterruptedException e1) {
1275                         e1.printStackTrace();
1276                 }
1277                 
1278                 if (!syncRunner.thread().isAlive()) {
1279                         logger.log(logger.MEDIUM, "Waiting for syncThread to stop");
1280                         if (syncRunner.thread().isAlive()) {
1281                                 System.out.println(tr("Synchronizing.  Please be patient."));
1282                                 for(;syncRunner.thread().isAlive();) {
1283                                         try {
1284                                                 wait(10);
1285                                         } catch (InterruptedException e) {
1286                                                 e.printStackTrace();
1287                                         }
1288                                 }
1289                         }
1290                         logger.log(logger.MEDIUM, "Sync thread has stopped");
1291                 }
1292
1293                 if (encryptOnShutdown) {
1294                         encryptOnShutdown();
1295                 }
1296                 if (decryptOnShutdown) {
1297                         decryptOnShutdown();
1298                 }
1299                 try {
1300                         Global.getFileManager().purgeResDirectory(false);
1301                 } catch (InitializationException e) {
1302                         System.out.println(tr("Empty res directory purge failed"));
1303                         e.printStackTrace();
1304                 }
1305                 logger.log(logger.HIGH, "Leaving NeverNote.closeEvent");
1306         }
1307
1308
1309         private void closeNeverNote() {
1310                 closeAction = true;
1311                 close();
1312         }
1313         public void setMessage(String s) {
1314                 if (logger != null) 
1315                         logger.log(logger.HIGH, "Entering NeverNote.setMessage");
1316                 else
1317                         System.out.println("*** ERROR *** " +s);
1318                 
1319                 if (statusBar != null) {
1320                         statusBar.show();
1321                         if (logger != null) 
1322                                 logger.log(logger.HIGH, "Message: " +s);
1323                         statusBar.showMessage(s);
1324                         if (emitLog != null)
1325                                 emitLog.add(s);
1326                 
1327                         if (messageTimer != null) {
1328                                 messageTimer.stop();
1329                                 messageTimer.setSingleShot(true);
1330                                 messageTimer.start();
1331                         }
1332                 }
1333                         
1334                 if (logger != null) 
1335                         logger.log(logger.HIGH, "Leaving NeverNote.setMessage");
1336         }
1337         
1338         private void clearMessage() {
1339                 statusBar.clearMessage();
1340                 statusBar.hide();
1341         }
1342                 
1343         private void waitCursor(boolean wait) {
1344                 if (wait) {
1345                         if (QApplication.overrideCursor() == null)
1346                                 QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.WaitCursor));
1347                 }
1348                 else {
1349                         if (QApplication.overrideCursor() != null)
1350                                 QApplication.restoreOverrideCursor();
1351                         else
1352                                 QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.ArrowCursor));
1353                 }
1354                 listManager.refreshCounters();
1355         }
1356         
1357         private void setupIndexListeners() {
1358 //              indexRunner.noteSignal.noteIndexed.connect(this, "indexThreadComplete(String)");
1359 //              indexRunner.resourceSignal.resourceIndexed.connect(this, "indexThreadComplete(String)");
1360                 indexRunner.signal.indexStarted.connect(this, "indexStarted()");
1361                 indexRunner.signal.indexFinished.connect(this, "indexComplete()");
1362         }
1363         private void setupSyncSignalListeners() {
1364                 syncRunner.tagSignal.listChanged.connect(this, "tagIndexUpdated()");
1365         syncRunner.searchSignal.listChanged.connect(this, "savedSearchIndexUpdated()");
1366         syncRunner.notebookSignal.listChanged.connect(this, "notebookIndexUpdated()");
1367         syncRunner.noteIndexSignal.listChanged.connect(this, "noteIndexUpdated(boolean)");
1368         syncRunner.noteSignal.quotaChanged.connect(this, "updateQuotaBar()");
1369         
1370                 syncRunner.syncSignal.saveUploadAmount.connect(this,"saveUploadAmount(long)");
1371                 syncRunner.syncSignal.saveUserInformation.connect(this,"saveUserInformation(User)");
1372                 syncRunner.syncSignal.saveEvernoteUpdateCount.connect(this,"saveEvernoteUpdateCount(int)");
1373                 
1374                 syncRunner.noteSignal.guidChanged.connect(this, "noteGuidChanged(String, String)");
1375                 syncRunner.noteSignal.noteChanged.connect(this, "invalidateNoteCache(String, String)");
1376                 syncRunner.resourceSignal.resourceGuidChanged.connect(this, "noteResourceGuidChanged(String,String,String)");
1377                 syncRunner.noteSignal.noteDownloaded.connect(listManager, "noteDownloaded(Note)");
1378                 syncRunner.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
1379                 
1380                 syncRunner.syncSignal.refreshLists.connect(this, "refreshLists()");
1381         }
1382         
1383         private void setupBrowserSignalListeners() {
1384                 setupBrowserWindowListeners(browserWindow, true);
1385         }
1386
1387         private void setupBrowserWindowListeners(BrowserWindow browser, boolean master) {
1388                 browser.fileWatcher.fileChanged.connect(this, "externalFileEdited(String)");
1389                 browser.noteSignal.tagsChanged.connect(this, "updateNoteTags(String, List)");
1390             browser.noteSignal.tagsChanged.connect(this, "updateListTags(String, List)");
1391             if (master) browser.noteSignal.noteChanged.connect(this, "setNoteDirty()");
1392             browser.noteSignal.titleChanged.connect(listManager, "updateNoteTitle(String, String)");
1393             browser.noteSignal.titleChanged.connect(this, "updateNoteTitle(String, String)");
1394             browser.noteSignal.notebookChanged.connect(this, "updateNoteNotebook(String, String)");
1395             browser.noteSignal.createdDateChanged.connect(listManager, "updateNoteCreatedDate(String, QDateTime)");
1396             browser.noteSignal.alteredDateChanged.connect(listManager, "updateNoteAlteredDate(String, QDateTime)");
1397             browser.noteSignal.subjectDateChanged.connect(listManager, "updateNoteSubjectDate(String, QDateTime)");
1398             browser.noteSignal.authorChanged.connect(listManager, "updateNoteAuthor(String, String)");
1399             browser.noteSignal.geoChanged.connect(listManager, "updateNoteGeoTag(String, Double,Double,Double)");
1400             browser.noteSignal.geoChanged.connect(this, "setNoteDirty()");
1401             browser.noteSignal.sourceUrlChanged.connect(listManager, "updateNoteSourceUrl(String, String)");
1402         browser.blockApplication.connect(this, "blockApplication(BrowserWindow)");
1403         browser.unblockApplication.connect(this, "unblockApplication()");
1404             if (master) browser.focusLost.connect(this, "saveNote()");
1405             browser.resourceSignal.contentChanged.connect(this, "externalFileEdited(String)");
1406             browser.evernoteLinkClicked.connect(this, "evernoteLinkClick(String, String)");
1407         }
1408
1409         //**************************************************
1410         //* Setup shortcuts
1411         //**************************************************
1412         private void setupShortcut(QShortcut action, String text) {
1413                 if (!Global.shortcutKeys.containsAction(text))
1414                         return;
1415                 action.setKey(new QKeySequence(Global.shortcutKeys.getShortcut(text)));
1416         }
1417         
1418         //***************************************************************
1419         //***************************************************************
1420         //* Settings and look & feel
1421         //***************************************************************
1422         //***************************************************************
1423         @SuppressWarnings("unused")
1424         private void settings() {
1425                 logger.log(logger.HIGH, "Entering NeverNote.settings");
1426
1427                 saveNoteColumnPositions();
1428                 saveNoteIndexWidth();
1429                 showColumns();
1430         ConfigDialog settings = new ConfigDialog(this, conn);
1431         String dateFormat = Global.getDateFormat();
1432         String timeFormat = Global.getTimeFormat();
1433         
1434                 indexTime = 1000*Global.getIndexThreadSleepInterval();  
1435                 indexTimer.start(indexTime);  // reset indexing timer
1436         
1437         settings.exec();
1438         indexRunner.indexAttachmentsLocally = Global.indexAttachmentsLocally();
1439 //        indexRunner.indexNoteBody = Global.indexNoteBody();
1440 //        indexRunner.indexNoteTitle = Global.indexNoteTitle();
1441 //        indexRunner.specialIndexCharacters = Global.getSpecialIndexCharacters();
1442         indexRunner.indexImageRecognition = Global.indexImageRecognition();
1443         if (Global.showTrayIcon() || Global.minimizeOnClose())
1444                 trayIcon.show();
1445         else
1446                 trayIcon.hide();
1447         showColumns();
1448         if (menuBar.showEditorBar.isChecked()){
1449                 for(int i = 0; i < tabBrowser.count(); i++){
1450                         BrowserWindow browser = ((TabBrowse) tabBrowser.widget(i)).getBrowserWindow();
1451                         showEditorButtons(browser);
1452                 }
1453                 
1454         }
1455         
1456         // Reset the save timer
1457         if (Global.getAutoSaveInterval() > 0)
1458                         saveTimer.setInterval(1000*60*Global.getAutoSaveInterval());
1459         else
1460                 saveTimer.stop();
1461         
1462         
1463         // Set special reloads
1464         if (settings.getDebugPage().reloadSharedNotebooksClicked()) {
1465                 conn.executeSql("Delete from LinkedNotebook");
1466                 conn.executeSql("delete from SharedNotebook");
1467                 conn.executeSql("Delete from Notebook where linked=true");
1468                 conn.executeSql("Insert into Sync (key, value) values ('FullLinkedNotebookSync', 'true')");
1469                 conn.executeSql("Insert into Sync (key, value) values ('FullSharedNotebookSync', 'true')");
1470         }
1471
1472         // Reload user data
1473         noteCache.clear();
1474         readOnlyCache.clear();
1475         inkNoteCache.clear();
1476         noteIndexUpdated(true);
1477                 
1478         logger.log(logger.HIGH, "Leaving NeverNote.settings");
1479         }
1480         // Restore things to the way they were
1481         private void restoreWindowState(boolean mainWindow) {
1482                 // We need to name things or this doesn't work.
1483                 setObjectName("NeverNote");
1484         restoreState(Global.restoreState(objectName()));
1485                 mainLeftRightSplitter.setObjectName("mainLeftRightSplitter");
1486                 browserIndexSplitter.setObjectName("browserIndexSplitter");
1487                 leftSplitter1.setObjectName("leftSplitter1");
1488                 rensoNoteListDock.setObjectName("rensoNoteListDock");
1489                 
1490                 // Restore the actual positions.
1491                 if (mainWindow)
1492                         restoreGeometry(Global.restoreGeometry(objectName()));
1493         mainLeftRightSplitter.restoreState(Global.restoreState(mainLeftRightSplitter.objectName()));
1494         browserIndexSplitter.restoreState(Global.restoreState(browserIndexSplitter.objectName()));
1495         leftSplitter1.restoreState(Global.restoreState(leftSplitter1.objectName()));
1496         rensoNoteListDock.restoreGeometry(Global.restoreGeometry(rensoNoteListDock.objectName()));
1497        
1498         }
1499         // Save window positions for the next start
1500         private void saveWindowState() {
1501                 Global.saveGeometry(objectName(), saveGeometry());
1502                 Global.saveState(mainLeftRightSplitter.objectName(), mainLeftRightSplitter.saveState());
1503                 Global.saveState(browserIndexSplitter.objectName(), browserIndexSplitter.saveState());
1504                 Global.saveState(leftSplitter1.objectName(), leftSplitter1.saveState());
1505                 Global.saveState(objectName(), saveState());
1506                 Global.saveGeometry(rensoNoteListDock.objectName(), rensoNoteListDock.saveGeometry());
1507         }    
1508         // Load the style sheet
1509         private void loadStyleSheet() {
1510                 String styleSheetName = "default.qss";
1511                 if (Global.getStyle().equalsIgnoreCase("cleanlooks"))
1512                                 styleSheetName = "default-cleanlooks.qss";
1513                 String fileName = Global.getFileManager().getQssDirPathUser("default.qss");
1514                 QFile file = new QFile(fileName);
1515                 
1516                 // If a user default.qss doesn't exist, we use the one shipped with NeverNote
1517                 if (!file.exists()) {
1518                         fileName = Global.getFileManager().getQssDirPath(styleSheetName);
1519                         file = new QFile(fileName);
1520                 }
1521                 file.open(OpenModeFlag.ReadOnly);
1522                 String styleSheet = file.readAll().toString();
1523                 file.close();
1524                 setStyleSheet(styleSheet);
1525         }
1526         // Save column positions for the next time
1527         private void saveNoteColumnPositions() {
1528                 int position = noteTableView.header.visualIndex(Global.noteTableCreationPosition);
1529                 Global.setColumnPosition("noteTableCreationPosition", position);
1530                 position = noteTableView.header.visualIndex(Global.noteTableTagPosition);
1531                 Global.setColumnPosition("noteTableTagPosition", position);
1532                 position = noteTableView.header.visualIndex(Global.noteTableNotebookPosition);
1533                 Global.setColumnPosition("noteTableNotebookPosition", position);
1534                 position = noteTableView.header.visualIndex(Global.noteTableChangedPosition);
1535                 Global.setColumnPosition("noteTableChangedPosition", position);
1536                 position = noteTableView.header.visualIndex(Global.noteTableAuthorPosition);
1537                 Global.setColumnPosition("noteTableAuthorPosition", position);
1538                 position = noteTableView.header.visualIndex(Global.noteTableSourceUrlPosition);
1539                 Global.setColumnPosition("noteTableSourceUrlPosition", position);
1540                 position = noteTableView.header.visualIndex(Global.noteTableSubjectDatePosition);
1541                 Global.setColumnPosition("noteTableSubjectDatePosition", position);
1542                 position = noteTableView.header.visualIndex(Global.noteTableTitlePosition);
1543                 Global.setColumnPosition("noteTableTitlePosition", position);
1544                 position = noteTableView.header.visualIndex(Global.noteTableSynchronizedPosition);
1545                 Global.setColumnPosition("noteTableSynchronizedPosition", position);
1546                 position = noteTableView.header.visualIndex(Global.noteTableGuidPosition);
1547                 Global.setColumnPosition("noteTableGuidPosition", position);
1548                 position = noteTableView.header.visualIndex(Global.noteTableThumbnailPosition);
1549                 Global.setColumnPosition("noteTableThumbnailPosition", position);
1550                 position = noteTableView.header.visualIndex(Global.noteTablePinnedPosition);
1551                 Global.setColumnPosition("noteTablePinnedPosition", position);
1552
1553         }
1554         // Save column widths for the next time
1555         private void saveNoteIndexWidth() {
1556                 int width;
1557         width = noteTableView.getColumnWidth(Global.noteTableCreationPosition);
1558         Global.setColumnWidth("noteTableCreationPosition", width);
1559                 width = noteTableView.getColumnWidth(Global.noteTableChangedPosition);
1560                 Global.setColumnWidth("noteTableChangedPosition", width);
1561                 width = noteTableView.getColumnWidth(Global.noteTableGuidPosition);
1562                 Global.setColumnWidth("noteTableGuidPosition", width);
1563                 width = noteTableView.getColumnWidth(Global.noteTableNotebookPosition);
1564                 Global.setColumnWidth("noteTableNotebookPosition", width);
1565                 width = noteTableView.getColumnWidth(Global.noteTableTagPosition);
1566                 Global.setColumnWidth("noteTableTagPosition", width);
1567                 width = noteTableView.getColumnWidth(Global.noteTableTitlePosition);
1568                 Global.setColumnWidth("noteTableTitlePosition", width);
1569                 width = noteTableView.getColumnWidth(Global.noteTableSourceUrlPosition);
1570                 Global.setColumnWidth("noteTableSourceUrlPosition", width);
1571                 width = noteTableView.getColumnWidth(Global.noteTableAuthorPosition);
1572                 Global.setColumnWidth("noteTableAuthorPosition", width);
1573                 width = noteTableView.getColumnWidth(Global.noteTableSubjectDatePosition);
1574                 Global.setColumnWidth("noteTableSubjectDatePosition", width);
1575                 width = noteTableView.getColumnWidth(Global.noteTableSynchronizedPosition);
1576                 Global.setColumnWidth("noteTableSynchronizedPosition", width);
1577                 width = noteTableView.getColumnWidth(Global.noteTableThumbnailPosition);
1578                 Global.setColumnWidth("noteTableThumbnailPosition", width);
1579                 width = noteTableView.getColumnWidth(Global.noteTableGuidPosition);
1580                 Global.setColumnWidth("noteTableGuidPosition", width);
1581                 width = noteTableView.getColumnWidth(Global.noteTablePinnedPosition);
1582                 Global.setColumnWidth("noteTablePinnedPosition", width);
1583         }
1584         
1585         @SuppressWarnings("unused")
1586         private void toggleSearchWindow() {
1587                 logger.log(logger.HIGH, "Entering NeverNote.toggleSearchWindow");
1588         searchLayout.toggleSearchField();
1589         menuBar.hideSearch.setChecked(searchField.isVisible());
1590         Global.saveWindowVisible("searchField", searchField.isVisible());
1591         logger.log(logger.HIGH, "Leaving NeverNote.toggleSearchWindow");
1592     }   
1593         @SuppressWarnings("unused")
1594         private void toggleQuotaWindow() {
1595                 logger.log(logger.HIGH, "Entering NeverNote.toggleQuotaWindow");
1596         searchLayout.toggleQuotaBar();
1597         menuBar.hideQuota.setChecked(quotaBar.isVisible());
1598         Global.saveWindowVisible("quota", quotaBar.isVisible());
1599         logger.log(logger.HIGH, "Leaving NeverNote.toggleQuotaWindow");
1600     }   
1601         @SuppressWarnings("unused")
1602         private void toggleZoomWindow() {
1603                 logger.log(logger.HIGH, "Entering NeverNote.toggleZoomWindow");
1604         searchLayout.toggleZoom();
1605         menuBar.hideZoom.setChecked(zoomSpinner.isVisible());
1606         Global.saveWindowVisible("zoom", zoomSpinner.isVisible());
1607         logger.log(logger.HIGH, "Leaving NeverNote.toggleZoomWindow");
1608     }   
1609         
1610         
1611         
1612     //***************************************************************
1613     //***************************************************************
1614     //** These functions deal with Notebook menu items
1615     //***************************************************************
1616     //***************************************************************
1617     // Setup the tree containing the user's notebooks.
1618     private void initializeNotebookTree() {       
1619         logger.log(logger.HIGH, "Entering NeverNote.initializeNotebookTree");
1620 //      notebookTree.itemClicked.connect(this, "notebookTreeSelection()");
1621         notebookTree.selectionSignal.connect(this, "notebookTreeSelection()");
1622         listManager.notebookSignal.refreshNotebookTreeCounts.connect(notebookTree, "updateCounts(List, List)");
1623         logger.log(logger.HIGH, "Leaving NeverNote.initializeNotebookTree");
1624     }   
1625     // Listener when a notebook is selected
1626         private void notebookTreeSelection() {
1627                 logger.log(logger.HIGH, "Entering NeverNote.notebookTreeSelection");
1628                 noteTableView.proxyModel.blocked = true;
1629                 
1630                 clearTrashFilter();
1631                 clearAttributeFilter();
1632                 clearSavedSearchFilter();
1633                 if (Global.mimicEvernoteInterface) {
1634                         clearTagFilter();
1635                         //searchField.clear();
1636                         searchField.clearEditText();
1637                 }
1638                 menuBar.noteRestoreAction.setVisible(false);            
1639         menuBar.notebookEditAction.setEnabled(true);
1640         menuBar.notebookDeleteAction.setEnabled(true);
1641         menuBar.notebookPublishAction.setEnabled(true);
1642         menuBar.notebookShareAction.setEnabled(true);
1643         menuBar.notebookIconAction.setEnabled(true);
1644         menuBar.notebookStackAction.setEnabled(true);
1645         
1646                 // ゴミ箱から元の画面に戻す。連想ノートリストをONに。
1647                 if (!rensoNoteListDock.isEnabled()) {
1648                         rensoNoteListDock.setEnabled(true);
1649                 }
1650                 
1651         List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1652         selectedNotebookGUIDs.clear();
1653                 String guid = "";
1654                 String stackName = "";
1655                 if (selections.size() > 0) {
1656                 guid = (selections.get(0).text(2));
1657                 stackName = selections.get(0).text(0);
1658         }
1659                 if (!Global.mimicEvernoteInterface) {
1660                         // If no notebooks are selected, we make it look like the "all notebooks" one was selected
1661                         if (selections.size()==0) {
1662                                 selectedNotebookGUIDs.clear();
1663                                 for (int i=0; i < listManager.getNotebookIndex().size(); i++) {
1664                                         selectedNotebookGUIDs.add(listManager.getNotebookIndex().get(i).getGuid());
1665                                 }
1666                                 menuBar.notebookEditAction.setEnabled(false);
1667                                 menuBar.notebookDeleteAction.setEnabled(false);
1668                                 menuBar.notebookStackAction.setEnabled(false);
1669                                 menuBar.notebookIconAction.setEnabled(false);
1670                         }
1671                 }
1672         if (!guid.equals("") && !guid.equals("STACK")) {
1673                 selectedNotebookGUIDs.add(guid);
1674                 menuBar.notebookIconAction.setEnabled(true);
1675         } else {
1676                 menuBar.notebookIconAction.setEnabled(true);
1677                         for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1678                                 Notebook book = listManager.getNotebookIndex().get(j);
1679                                 if (book.getStack() != null && book.getStack().equalsIgnoreCase(stackName))
1680                                         selectedNotebookGUIDs.add(book.getGuid());
1681                         }
1682         }
1683         listManager.setSelectedNotebooks(selectedNotebookGUIDs);
1684         listManager.loadNotesIndex();
1685         noteIndexUpdated(false);
1686         refreshEvernoteNote(true);
1687         listManager.refreshCounters = true;
1688         listManager.refreshCounters();
1689         if (selectedNotebookGUIDs.size() == 1) {
1690                 int col = conn.getNotebookTable().getSortColumn(selectedNotebookGUIDs.get(0));
1691                 int order = conn.getNotebookTable().getSortOrder(selectedNotebookGUIDs.get(0));
1692                 if (col != -1) {
1693                         noteTableView.proxyModel.blocked = true;
1694                         if (order == 1)
1695                                 noteTableView.sortByColumn(col, Qt.SortOrder.DescendingOrder);
1696                         else
1697                                 noteTableView.sortByColumn(col, Qt.SortOrder.AscendingOrder);
1698                 }
1699         }
1700         noteTableView.proxyModel.blocked = false;
1701                 logger.log(logger.HIGH, "Leaving NeverNote.notebookTreeSelection");
1702
1703     }
1704     private void clearNotebookFilter() {
1705         notebookTree.blockSignals(true);
1706         notebookTree.clearSelection();
1707                 menuBar.noteRestoreAction.setVisible(false);
1708         menuBar.notebookEditAction.setEnabled(false);
1709         menuBar.notebookDeleteAction.setEnabled(false);
1710         selectedNotebookGUIDs.clear();
1711         listManager.setSelectedNotebooks(selectedNotebookGUIDs);
1712         notebookTree.blockSignals(false);
1713     }
1714         // Triggered when the notebook DB has been updated
1715         private void notebookIndexUpdated() {
1716                 logger.log(logger.HIGH, "Entering NeverNote.notebookIndexUpdated");
1717         
1718                 // Get the possible icons
1719                 HashMap<String, QIcon> icons = conn.getNotebookTable().getAllIcons();
1720         notebookTree.setIcons(icons);
1721         
1722         if (selectedNotebookGUIDs == null)
1723                         selectedNotebookGUIDs = new ArrayList<String>();
1724                 List<Notebook> books = conn.getNotebookTable().getAll();
1725                 for (int i=books.size()-1; i>=0; i--) {
1726                         for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1727                                 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(books.get(i).getGuid())) {
1728                                         books.remove(i);
1729                                         j=listManager.getArchiveNotebookIndex().size();
1730                                 }
1731                         }
1732                 }
1733                 
1734                 
1735                 listManager.countNotebookResults(listManager.getNoteIndex());
1736                 notebookTree.blockSignals(true);
1737         notebookTree.load(books, listManager.getLocalNotebooks());
1738         for (int i=selectedNotebookGUIDs.size()-1; i>=0; i--) {
1739                 boolean found = notebookTree.selectGuid(selectedNotebookGUIDs.get(i));
1740                 if (!found)
1741                         selectedNotebookGUIDs.remove(i);
1742         }
1743         listManager.refreshCounters = true;
1744         listManager.refreshCounters();
1745         notebookTree.blockSignals(false);
1746         
1747                 logger.log(logger.HIGH, "Leaving NeverNote.notebookIndexUpdated");
1748     }
1749     // Show/Hide note information
1750         @SuppressWarnings("unused")
1751         private void toggleNotebookWindow() {
1752                 logger.log(logger.HIGH, "Entering NeverNote.toggleNotebookWindow");
1753                 searchLayout.toggleNotebook();
1754         menuBar.hideNotebooks.setChecked(notebookTree.isVisible());
1755         Global.saveWindowVisible("notebookTree", notebookTree.isVisible());
1756         logger.log(logger.HIGH, "Leaving NeverNote.toggleNotebookWindow");
1757     }   
1758         // Add a new notebook
1759         @SuppressWarnings("unused")
1760         private void addNotebook() {
1761                 logger.log(logger.HIGH, "Inside NeverNote.addNotebook");
1762                 NotebookEdit edit = new NotebookEdit();
1763                 edit.setNotebooks(listManager.getNotebookIndex());
1764                 edit.exec();
1765         
1766                 if (!edit.okPressed())
1767                         return;
1768         
1769                 Calendar currentTime = new GregorianCalendar();
1770                 Long l = new Long(currentTime.getTimeInMillis());
1771                 String randint = new String(Long.toString(l));
1772         
1773                 Notebook newBook = new Notebook();
1774                 newBook.setUpdateSequenceNum(0);
1775                 newBook.setGuid(randint);
1776                 newBook.setName(edit.getNotebook());
1777                 newBook.setServiceCreated(new Date().getTime());
1778                 newBook.setServiceUpdated(new Date().getTime());
1779                 newBook.setDefaultNotebook(false);
1780                 newBook.setPublished(false);
1781                 
1782                 listManager.getNotebookIndex().add(newBook);
1783                 if (edit.isLocal())
1784                         listManager.getLocalNotebooks().add(newBook.getGuid());
1785                 conn.getNotebookTable().addNotebook(newBook, true, edit.isLocal());
1786                 notebookIndexUpdated();
1787                 listManager.countNotebookResults(listManager.getNoteIndex());
1788 //              notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());
1789                 logger.log(logger.HIGH, "Leaving NeverNote.addNotebook");
1790         }
1791         // Edit an existing notebook
1792         @SuppressWarnings("unused")
1793         private void stackNotebook() {
1794                 logger.log(logger.HIGH, "Entering NeverNote.stackNotebook");
1795                 StackNotebook edit = new StackNotebook();
1796                 
1797                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1798                 QTreeWidgetItem currentSelection;
1799                 for (int i=0; i<selections.size(); i++) {
1800                         currentSelection = selections.get(0);
1801                         String guid = currentSelection.text(2);
1802                         if (guid.equalsIgnoreCase("")) {
1803                                  QMessageBox.critical(this, tr("Unable To Stack") ,tr("You can't stack the \"All Notebooks\" item."));
1804                                  return;
1805                         }
1806                         if (guid.equalsIgnoreCase("STACK")) {
1807                                  QMessageBox.critical(this, tr("Unable To Stack") ,tr("You can't stack a stack."));
1808                                  return;
1809                         }
1810                 }
1811
1812                 edit.setStackNames(conn.getNotebookTable().getAllStackNames());
1813
1814                 
1815                 edit.exec();
1816         
1817                 if (!edit.okPressed())
1818                         return;
1819         
1820                 String stack = edit.getStackName();
1821                 
1822                 for (int i=0; i<selections.size(); i++) {
1823                         currentSelection = selections.get(i);
1824                         String guid = currentSelection.text(2);
1825                         listManager.updateNotebookStack(guid, stack);
1826                 }
1827                 notebookIndexUpdated();
1828                 logger.log(logger.HIGH, "Leaving NeverNote.stackNotebook");
1829         }
1830         // Edit an existing notebook
1831         @SuppressWarnings("unused")
1832         private void editNotebook() {
1833                 logger.log(logger.HIGH, "Entering NeverNote.editNotebook");
1834                 NotebookEdit edit = new NotebookEdit();
1835                 
1836                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1837                 QTreeWidgetItem currentSelection;
1838                 currentSelection = selections.get(0);
1839                 edit.setNotebook(currentSelection.text(0));
1840                 
1841                 String guid = currentSelection.text(2);
1842                 if (!guid.equalsIgnoreCase("STACK")) {
1843                         edit.setTitle(tr("Edit Notebook"));
1844                         edit.setNotebooks(listManager.getNotebookIndex());
1845                         edit.setLocalCheckboxEnabled(false);
1846                         for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1847                                 if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
1848                                         edit.setDefaultNotebook(listManager.getNotebookIndex().get(i).isDefaultNotebook());
1849                                         i=listManager.getNotebookIndex().size();
1850                                 }
1851                         }
1852                 } else {
1853                         edit.setTitle(tr("Edit Stack"));
1854                         edit.setStacks(conn.getNotebookTable().getAllStackNames());
1855                         edit.hideLocalCheckbox();
1856                         edit.hideDefaultCheckbox();
1857                 }
1858                 
1859                 edit.exec();
1860         
1861                 if (!edit.okPressed())
1862                         return;
1863         
1864                 
1865                 if (guid.equalsIgnoreCase("STACK")) {
1866                         conn.getNotebookTable().renameStacks(currentSelection.text(0), edit.getNotebook());
1867                         for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
1868                                 if (listManager.getNotebookIndex().get(j).getStack() != null && 
1869                                         listManager.getNotebookIndex().get(j).getStack().equalsIgnoreCase(currentSelection.text(0)))
1870                                                 listManager.getNotebookIndex().get(j).setStack(edit.getNotebook());
1871                         }
1872                         conn.getNotebookTable().renameStacks(currentSelection.text(0), edit.getNotebook());
1873                         currentSelection.setText(0, edit.getNotebook());
1874                         return;
1875                 }
1876                 
1877                 updateListNotebookName(currentSelection.text(0), edit.getNotebook());
1878                 currentSelection.setText(0, edit.getNotebook());
1879                 
1880                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1881                         if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
1882                                 listManager.getNotebookIndex().get(i).setName(edit.getNotebook());
1883                                 if (!listManager.getNotebookIndex().get(i).isDefaultNotebook() && edit.isDefaultNotebook()) {
1884                                         for (int j=0; j<listManager.getNotebookIndex().size(); j++)
1885                                                 listManager.getNotebookIndex().get(j).setDefaultNotebook(false);
1886                                         listManager.getNotebookIndex().get(i).setDefaultNotebook(true);
1887                                         conn.getNotebookTable().setDefaultNotebook(listManager.getNotebookIndex().get(i).getGuid());
1888                                 }
1889                                 conn.getNotebookTable().updateNotebook(listManager.getNotebookIndex().get(i), true);
1890                                 if (conn.getNotebookTable().isLinked(listManager.getNotebookIndex().get(i).getGuid())) {
1891                                         LinkedNotebook linkedNotebook = conn.getLinkedNotebookTable().getByNotebookGuid(listManager.getNotebookIndex().get(i).getGuid());
1892                                         linkedNotebook.setShareName(edit.getNotebook());
1893                                         conn.getLinkedNotebookTable().updateNotebook(linkedNotebook, true);
1894                                 }
1895                                 i=listManager.getNotebookIndex().size();
1896                         }
1897                 }
1898                 
1899                 // Build a list of non-closed notebooks
1900                 List<Notebook> nbooks = new ArrayList<Notebook>();
1901                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1902                         boolean found=false;
1903                         for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
1904                                 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
1905                                         found = true;
1906                         }
1907                         if (!found)
1908                                 nbooks.add(listManager.getNotebookIndex().get(i));
1909                 }
1910                 
1911                 
1912                 FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger);
1913                 List<Notebook> filteredBooks = notebookFilter.getValidNotebooks(currentNote, listManager.getNotebookIndex());
1914                 browserWindow.setNotebookList(filteredBooks);
1915                 Iterator<String> set = externalWindows.keySet().iterator();
1916                 while(set.hasNext())
1917                         externalWindows.get(set.next()).getBrowserWindow().setNotebookList(filteredBooks);
1918                 
1919                 Iterator<Integer>it = tabWindows.keySet().iterator();
1920                 while (it.hasNext()) {
1921                         tabWindows.get(it.next()).getBrowserWindow()
1922                                         .setNotebookList(filteredBooks);
1923                 }
1924                 
1925                 logger.log(logger.HIGH, "Leaving NeverNote.editNotebook");
1926         }
1927         // Publish a notebook
1928         @SuppressWarnings("unused")
1929         private void publishNotebook() {
1930                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1931                 QTreeWidgetItem currentSelection;
1932                 currentSelection = selections.get(0);
1933                 String guid = currentSelection.text(2);
1934
1935                 if (guid.equalsIgnoreCase("STACK") || guid.equalsIgnoreCase(""))
1936                         return;
1937                 
1938                 Notebook n = null;
1939                 int position = 0;
1940                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1941                         if (guid.equals(listManager.getNotebookIndex().get(i).getGuid())) {
1942                                 n = listManager.getNotebookIndex().get(i);
1943                                 position = i;
1944                                 i = listManager.getNotebookIndex().size();
1945                         }
1946                 }
1947                 if (n == null)
1948                         return;
1949                 
1950                 PublishNotebook publish = new PublishNotebook(Global.username, Global.getServer(), n);
1951                 publish.exec();
1952                 
1953                 if (!publish.okClicked()) 
1954                         return;
1955                 
1956                 Publishing p = publish.getPublishing();
1957                 boolean isPublished = !publish.isStopPressed();
1958                 conn.getNotebookTable().setPublishing(n.getGuid(), isPublished, p);
1959                 n.setPublished(isPublished);
1960                 n.setPublishing(p);
1961                 listManager.getNotebookIndex().set(position, n);
1962                 notebookIndexUpdated();
1963         }
1964         // Publish a notebook
1965         @SuppressWarnings("unused")
1966         private void shareNotebook() {
1967                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
1968                 QTreeWidgetItem currentSelection;
1969                 currentSelection = selections.get(0);
1970                 String guid = currentSelection.text(2);
1971
1972                 if (guid.equalsIgnoreCase("STACK") || guid.equalsIgnoreCase(""))
1973                         return;
1974                 
1975                 Notebook n = null;;
1976                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
1977                         if (guid.equals(listManager.getNotebookIndex().get(i).getGuid())) {
1978                                 n = listManager.getNotebookIndex().get(i);
1979                                 i = listManager.getNotebookIndex().size();
1980                         }
1981                 }
1982                                 
1983                 String authToken = null;
1984                 if (syncRunner.isConnected)
1985                         authToken = syncRunner.authToken;
1986                 ShareNotebook share = new ShareNotebook(n.getName(), conn, n, syncRunner);
1987                 share.exec();
1988                 
1989         }
1990
1991         // Delete an existing notebook
1992         @SuppressWarnings("unused")
1993         private void deleteNotebook() {
1994                 logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
1995                 boolean stacksFound = false;
1996                 boolean notebooksFound = false;
1997                 boolean assigned = false;
1998                 // Check if any notes have this notebook
1999                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
2000         for (int i=0; i<selections.size(); i++) {
2001                 QTreeWidgetItem currentSelection;
2002                 currentSelection = selections.get(i);
2003                 String guid = currentSelection.text(2);
2004                 if (!guid.equalsIgnoreCase("STACK")) {
2005                         notebooksFound = true;
2006                         for (int j=0; j<listManager.getNoteIndex().size(); j++) {
2007                                 String noteGuid = listManager.getNoteIndex().get(j).getNotebookGuid();
2008                                 if (noteGuid.equals(guid)) {
2009                                         assigned = true;
2010                                         j=listManager.getNoteIndex().size();
2011                                         i=selections.size();
2012                                 }
2013                         }
2014                 } else {
2015                         stacksFound = true;
2016                 }
2017         }
2018                 if (assigned) {
2019                         QMessageBox.information(this, tr("Unable to Delete"), tr("Some of the selected notebook(s) contain notes.\n"+
2020                                         "Please delete the notes or move them to another notebook before deleting any notebooks."));
2021                         return;
2022                 }
2023                 
2024                 if (conn.getNotebookTable().getAll().size() == 1) {
2025                         QMessageBox.information(this, tr("Unable to Delete"), tr("You must have at least one notebook."));
2026                         return;
2027                 }
2028         
2029         // If all notebooks are clear, verify the delete
2030                 String msg1 = new String(tr("Delete selected notebooks?"));
2031                 String msg2 = new String(tr("Remove selected stacks (notebooks will not be deleted)?"));
2032                 String msg3 = new String(tr("Delete selected notebooks & remove stacks? Notebooks under the stacks are" +
2033                                 " not deleted unless selected?"));
2034                 String msg = "";
2035                 if (stacksFound && notebooksFound)
2036                         msg = msg3;
2037                 if (!stacksFound && notebooksFound)
2038                         msg = msg1;
2039                 if (stacksFound && !notebooksFound)
2040                         msg = msg2;
2041                 if (QMessageBox.question(this, tr("Confirmation"), msg,
2042                         QMessageBox.StandardButton.Yes, 
2043                         QMessageBox.StandardButton.No)==StandardButton.No.value()) {
2044                         return;
2045                 }
2046                 
2047                 // If confirmed, delete the notebook
2048         for (int i=selections.size()-1; i>=0; i--) {
2049                 QTreeWidgetItem currentSelection;
2050                 currentSelection = selections.get(i);
2051                 String guid = currentSelection.text(2);
2052                 if (currentSelection.text(2).equalsIgnoreCase("STACK")) {
2053                         conn.getNotebookTable().renameStacks(currentSelection.text(0), "");
2054                         listManager.renameStack(currentSelection.text(0), "");
2055                 } else {
2056                         conn.getNotebookTable().expungeNotebook(guid, true);
2057                         listManager.deleteNotebook(guid);
2058                 }
2059         }
2060
2061                 notebookIndexUpdated();
2062 //        notebookTreeSelection();
2063 //        notebookTree.load(listManager.getNotebookIndex(), listManager.getLocalNotebooks());
2064 //        listManager.countNotebookResults(listManager.getNoteIndex());
2065         logger.log(logger.HIGH, "Entering NeverNote.deleteNotebook");
2066         }
2067         // A note's notebook has been updated
2068         @SuppressWarnings("unused")
2069         private void updateNoteNotebook(String guid, String notebookGuid) {
2070                 // 同じノートブックに入れられたノート間の履歴を登録
2071                 conn.getHistoryTable().addSameNotebookHistory(guid, notebookGuid);
2072                 
2073                 // Update the list manager
2074                 listManager.updateNoteNotebook(guid, notebookGuid);
2075                 listManager.countNotebookResults(listManager.getNoteIndex());
2076 //              notebookTree.updateCounts(listManager.getNotebookIndex(), listManager.getNotebookCounter());    
2077                 
2078                 // Find the name of the notebook
2079                 String notebookName = null;
2080                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
2081                         if (listManager.getNotebookIndex().get(i).getGuid().equals(notebookGuid)) {
2082                                 notebookName = listManager.getNotebookIndex().get(i).getName();
2083                                 break;
2084                         }
2085                 }
2086                 
2087                 // If we found the name, update the browser window
2088                 if (notebookName != null) {
2089                         updateListNoteNotebook(guid, notebookName);
2090                         if (guid.equals(currentNoteGuid)) {
2091                                 int pos =  browserWindow.notebookBox.findText(notebookName);
2092                                 if (pos >=0)
2093                                         browserWindow.notebookBox.setCurrentIndex(pos);
2094                         }
2095                 }
2096                 
2097                 // If we're dealing with the current note, then we need to be sure and update the notebook there
2098                 if (guid.equals(currentNoteGuid)) {
2099                         if (currentNote != null) {
2100                                 currentNote.setNotebookGuid(notebookGuid);
2101                         }
2102                 }
2103         }
2104         // Open/close notebooks
2105         @SuppressWarnings("unused")
2106         private void closeNotebooks() {
2107                 NotebookArchive na = new NotebookArchive(listManager.getNotebookIndex(), listManager.getArchiveNotebookIndex());
2108                 na.exec();
2109                 if (!na.okClicked())
2110                         return;
2111                 
2112                 waitCursor(true);
2113                 listManager.getArchiveNotebookIndex().clear();
2114                 
2115                 for (int i=na.getClosedBookList().count()-1; i>=0; i--) {
2116                         String text = na.getClosedBookList().takeItem(i).text();
2117                         for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
2118                                 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
2119                                         Notebook n = listManager.getNotebookIndex().get(j);
2120                                         conn.getNotebookTable().setArchived(n.getGuid(),true);
2121                                         listManager.getArchiveNotebookIndex().add(n);
2122                                         j=listManager.getNotebookIndex().size();
2123                                 }
2124                         }
2125                 }
2126                 
2127                 for (int i=na.getOpenBookList().count()-1; i>=0; i--) {
2128                         String text = na.getOpenBookList().takeItem(i).text();
2129                         for (int j=0; j<listManager.getNotebookIndex().size(); j++) {
2130                                 if (listManager.getNotebookIndex().get(j).getName().equalsIgnoreCase(text)) {
2131                                         Notebook n = listManager.getNotebookIndex().get(j);
2132                                         conn.getNotebookTable().setArchived(n.getGuid(),false);
2133                                         j=listManager.getNotebookIndex().size();
2134                                 }
2135                         }
2136                 }
2137                 notebookTreeSelection();
2138                 listManager.loadNotesIndex();
2139                 notebookIndexUpdated();
2140                 noteIndexUpdated(false);
2141                 reloadTagTree(true);
2142 //              noteIndexUpdated(false);
2143                 
2144                 // Build a list of non-closed notebooks
2145                 List<Notebook> nbooks = new ArrayList<Notebook>();
2146                 for (int i=0; i<listManager.getNotebookIndex().size(); i++) {
2147                         boolean found=false;
2148                         for (int j=0; j<listManager.getArchiveNotebookIndex().size(); j++) {
2149                                 if (listManager.getArchiveNotebookIndex().get(j).getGuid().equals(listManager.getNotebookIndex().get(i).getGuid()))
2150                                         found = true;
2151                         }
2152                         if (!found)
2153                                 nbooks.add(listManager.getNotebookIndex().get(i));
2154                 }
2155                 
2156                 FilterEditorNotebooks notebookFilter = new FilterEditorNotebooks(conn, logger);
2157                 List<Notebook> filteredBooks = notebookFilter.getValidNotebooks(currentNote, listManager.getNotebookIndex());
2158                 browserWindow.setNotebookList(filteredBooks);
2159                 
2160                 // Update any external windows
2161                 Iterator<String> set = externalWindows.keySet().iterator();
2162                 while(set.hasNext())
2163                         externalWindows.get(set.next()).getBrowserWindow().setNotebookList(filteredBooks);
2164                 
2165                 // 全てのタブウィンドウを更新
2166                 Iterator<Integer> it = tabWindows.keySet().iterator();
2167                 while (it.hasNext()) {
2168                         tabWindows.get(it.next()).getBrowserWindow()
2169                                         .setNotebookList(filteredBooks);
2170                 }
2171                 
2172                 waitCursor(false);
2173         }
2174         // Change the notebook's icon
2175         @SuppressWarnings("unused")
2176         private void setNotebookIcon() {
2177                 boolean stackSelected = false;
2178                 boolean allNotebookSelected = false;
2179                 
2180                 QTreeWidgetItem currentSelection;
2181                 List<QTreeWidgetItem> selections = notebookTree.selectedItems();
2182                 if (selections.size() == 0)
2183                         return;
2184                 
2185                 currentSelection = selections.get(0);   
2186                 String guid = currentSelection.text(2);
2187                 if (guid.equalsIgnoreCase(""))
2188                         allNotebookSelected = true;
2189                 if (guid.equalsIgnoreCase("STACK"))
2190                         stackSelected = true;
2191
2192                 QIcon currentIcon = currentSelection.icon(0);
2193                 QIcon icon;
2194                 SetIcon dialog;
2195                 
2196                 if (!stackSelected && !allNotebookSelected) {
2197                         icon = conn.getNotebookTable().getIcon(guid);
2198                         if (icon == null) {
2199                                 dialog = new SetIcon(currentIcon, saveLastPath);
2200                                 dialog.setUseDefaultIcon(true);
2201                         } else {
2202                                 dialog = new SetIcon(icon, saveLastPath);
2203                                 dialog.setUseDefaultIcon(false);
2204                         }
2205                 } else {
2206                         if (stackSelected) {
2207                                 icon = conn.getSystemIconTable().getIcon(currentSelection.text(0), "STACK");
2208                         } else {
2209                                 icon = conn.getSystemIconTable().getIcon(currentSelection.text(0), "ALLNOTEBOOK");                              
2210                         }
2211                         if (icon == null) {
2212                                 dialog = new SetIcon(currentIcon, saveLastPath);
2213                                 dialog.setUseDefaultIcon(true);
2214                         } else {
2215                                 dialog = new SetIcon(icon, saveLastPath);
2216                                 dialog.setUseDefaultIcon(false);
2217                         }
2218                 }
2219                 dialog.exec();
2220                 if (dialog.okPressed()) {
2221                 saveLastPath = dialog.getPath();
2222
2223                         QIcon newIcon = dialog.getIcon();
2224                         if (stackSelected) {
2225                                 conn.getSystemIconTable().setIcon(currentSelection.text(0), "STACK", newIcon, dialog.getFileType());
2226                                 if (newIcon == null) {
2227                                         newIcon = new QIcon(iconPath+"books2.png");
2228                                 }
2229                                 currentSelection.setIcon(0,newIcon);
2230                                 return;
2231                         }
2232                         if (allNotebookSelected) {
2233                                 conn.getSystemIconTable().setIcon(currentSelection.text(0), "ALLNOTEBOOK", newIcon, dialog.getFileType());
2234                                 if (newIcon == null) {
2235                                         newIcon = new QIcon(iconPath+"notebook-green.png");
2236                                 }
2237                                 currentSelection.setIcon(0,newIcon);
2238                                 return;
2239                         }
2240                         conn.getNotebookTable().setIcon(guid, newIcon, dialog.getFileType());
2241                         if (newIcon == null) {
2242                                 boolean isPublished = false;;
2243                                 boolean found = false;
2244                                 for (int i=0; i<listManager.getNotebookIndex().size() && !found; i++) {
2245                                         if (listManager.getNotebookIndex().get(i).getGuid().equals(guid)) {
2246                                                 isPublished = listManager.getNotebookIndex().get(i).isPublished();
2247                                                 found = true;
2248                                         }
2249                                 }
2250                                 newIcon = notebookTree.findDefaultIcon(guid, currentSelection.text(1), listManager.getLocalNotebooks(), isPublished);
2251                         }
2252                         currentSelection.setIcon(0, newIcon);
2253                 }
2254         
2255         }
2256         
2257         
2258     //***************************************************************
2259     //***************************************************************
2260     //** These functions deal with Tag menu items
2261     //***************************************************************
2262     //***************************************************************
2263         // Add a new notebook
2264         @SuppressWarnings("unused")
2265         private void addTag() {
2266                 logger.log(logger.HIGH, "Inside NeverNote.addTag");
2267                 TagEdit edit = new TagEdit();
2268                 edit.setTagList(listManager.getTagIndex());
2269
2270                 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2271                 QTreeWidgetItem currentSelection = null;
2272                 if (selections.size() > 0) {
2273                         currentSelection = selections.get(0);
2274                         edit.setParentTag(currentSelection.text(0));
2275                 }
2276
2277                 edit.exec();
2278         
2279                 if (!edit.okPressed())
2280                         return;
2281         
2282                 Calendar currentTime = new GregorianCalendar();
2283                 Long l = new Long(currentTime.getTimeInMillis());
2284                 String randint = new String(Long.toString(l));
2285         
2286                 Tag newTag = new Tag();
2287                 newTag.setUpdateSequenceNum(0);
2288                 newTag.setGuid(randint);
2289                 newTag.setName(edit.getTag());
2290                 if (edit.getParentTag().isChecked()) {
2291                         newTag.setParentGuid(currentSelection.text(2));
2292                         newTag.setParentGuidIsSet(true);
2293                         currentSelection.setExpanded(true);
2294                 }
2295                 conn.getTagTable().addTag(newTag, true);
2296                 listManager.getTagIndex().add(newTag);
2297                 reloadTagTree(true);
2298                 
2299                 logger.log(logger.HIGH, "Leaving NeverNote.addTag");
2300         }
2301         @SuppressWarnings("unused")
2302         private void reloadTagTree() {
2303                 reloadTagTree(false);
2304         }
2305         private void reloadTagTree(boolean reload) {
2306                 logger.log(logger.HIGH, "Entering NeverNote.reloadTagTree");
2307                 tagIndexUpdated(reload);
2308                 boolean filter = false;
2309                 if (reload)
2310                         listManager.countTagResults(listManager.getNoteIndex());
2311                 if (notebookTree.selectedItems().size() > 0 
2312                                                   && !notebookTree.selectedItems().get(0).text(0).equalsIgnoreCase("All Notebooks"))
2313                                                   filter = true;
2314                 if (tagTree.selectedItems().size() > 0)
2315                         filter = true;
2316                 tagTree.showAllTags(!filter);
2317                 tagIndexUpdated(false);
2318                 logger.log(logger.HIGH, "Leaving NeverNote.reloadTagTree");
2319         }
2320         // Edit an existing tag
2321         @SuppressWarnings("unused")
2322         private void editTag() {
2323                 logger.log(logger.HIGH, "Entering NeverNote.editTag");
2324                 TagEdit edit = new TagEdit();
2325                 edit.setTitle("Edit Tag");
2326                 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2327                 QTreeWidgetItem currentSelection;
2328                 currentSelection = selections.get(0);
2329                 edit.setTag(currentSelection.text(0));
2330                 edit.setTagList(listManager.getTagIndex());
2331                 edit.exec();
2332         
2333                 if (!edit.okPressed())
2334                         return;
2335         
2336                 String guid = currentSelection.text(2);
2337                 currentSelection.setText(0,edit.getTag());
2338                 
2339                 for (int i=0; i<listManager.getTagIndex().size(); i++) {
2340                         if (listManager.getTagIndex().get(i).getGuid().equals(guid)) {
2341                                 listManager.getTagIndex().get(i).setName(edit.getTag());
2342                                 conn.getTagTable().updateTag(listManager.getTagIndex().get(i), true);
2343                                 updateListTagName(guid);
2344                                 if (currentNote != null && currentNote.getTagGuids().contains(guid))
2345                                         browserWindow.setTag(getTagNamesForNote(currentNote));
2346                                 logger.log(logger.HIGH, "Leaving NeverNote.editTag");
2347                                 //return;
2348                         }
2349                 }
2350                 listManager.reloadNoteTagNames(guid, edit.getTag());
2351                 noteIndexUpdated(true);
2352                 refreshEvernoteNote(true);
2353                 browserWindow.setTag(getTagNamesForNote(currentNote));
2354                 logger.log(logger.HIGH, "Leaving NeverNote.editTag...");
2355         }
2356         // Delete an existing tag
2357         @SuppressWarnings("unused")
2358         private void deleteTag() {
2359                 logger.log(logger.HIGH, "Entering NeverNote.deleteTag");
2360                 
2361                 if (QMessageBox.question(this, tr("Confirmation"), tr("Delete the selected tags?"),
2362                         QMessageBox.StandardButton.Yes, 
2363                         QMessageBox.StandardButton.No)==StandardButton.No.value()) {
2364                                                         return;
2365                 }
2366                 
2367                 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2368         for (int i=selections.size()-1; i>=0; i--) {
2369                 QTreeWidgetItem currentSelection;
2370                 currentSelection = selections.get(i);                   
2371                 removeTagItem(currentSelection.text(2));
2372         }
2373         tagIndexUpdated(true);
2374         tagTreeSelection();
2375         listManager.countTagResults(listManager.getNoteIndex());
2376 //              tagTree.updateCounts(listManager.getTagCounter());
2377         logger.log(logger.HIGH, "Leaving NeverNote.deleteTag");
2378         }
2379         // Remove a tag tree item.  Go recursively down & remove the children too
2380         private void removeTagItem(String guid) {
2381         for (int j=listManager.getTagIndex().size()-1; j>=0; j--) {             
2382                 String parent = listManager.getTagIndex().get(j).getParentGuid();
2383                 if (parent != null && parent.equals(guid)) {            
2384                         //Remove this tag's children
2385                         removeTagItem(listManager.getTagIndex().get(j).getGuid());
2386                 }
2387         }
2388         //Now, remove this tag
2389         removeListTagName(guid);
2390         conn.getTagTable().expungeTag(guid, true);                      
2391         for (int a=0; a<listManager.getTagIndex().size(); a++) {
2392                 if (listManager.getTagIndex().get(a).getGuid().equals(guid)) {
2393                         listManager.getTagIndex().remove(a);
2394                         return;
2395                 }
2396         }
2397         }
2398         // Setup the tree containing the user's tags
2399     private void initializeTagTree() {
2400         logger.log(logger.HIGH, "Entering NeverNote.initializeTagTree");
2401 //      tagTree.itemSelectionChanged.connect(this, "tagTreeSelection()");
2402 //      tagTree.itemClicked.connect(this, "tagTreeSelection()");
2403         tagTree.selectionSignal.connect(this, "tagTreeSelection()");
2404         listManager.tagSignal.refreshTagTreeCounts.connect(tagTree, "updateCounts(List)");
2405         logger.log(logger.HIGH, "Leaving NeverNote.initializeTagTree");
2406     }
2407     // Listener when a tag is selected
2408         private void tagTreeSelection() {
2409         logger.log(logger.HIGH, "Entering NeverNote.tagTreeSelection");
2410                 
2411         clearTrashFilter();
2412         clearAttributeFilter();
2413         clearSavedSearchFilter();
2414         
2415                 menuBar.noteRestoreAction.setVisible(false);
2416                 
2417                 // ゴミ箱から元の画面に戻す。連想ノートリストをONに。
2418                 if (!rensoNoteListDock.isEnabled()) {
2419                         rensoNoteListDock.setEnabled(true);
2420                 }
2421                 
2422         List<QTreeWidgetItem> selections = tagTree.selectedItems();
2423         QTreeWidgetItem currentSelection;
2424         selectedTagGUIDs.clear();
2425         for (int i=0; i<selections.size(); i++) {
2426                 currentSelection = selections.get(i);
2427                 selectedTagGUIDs.add(currentSelection.text(2));
2428         }
2429         if (selections.size() > 0) {
2430                 menuBar.tagEditAction.setEnabled(true);
2431                 menuBar.tagDeleteAction.setEnabled(true);
2432                 menuBar.tagIconAction.setEnabled(true);
2433         }
2434         else {
2435                 menuBar.tagEditAction.setEnabled(false);
2436                 menuBar.tagDeleteAction.setEnabled(false);
2437                 menuBar.tagIconAction.setEnabled(true);
2438         }
2439         if (selections.size() > 1)
2440                 menuBar.tagMergeAction.setEnabled(true);
2441         else
2442                 menuBar.tagMergeAction.setEnabled(false);
2443         listManager.setSelectedTags(selectedTagGUIDs);
2444         listManager.loadNotesIndex();
2445         noteIndexUpdated(false);
2446         refreshEvernoteNote(true);
2447         listManager.refreshCounters = true;
2448         listManager.refreshCounters();
2449         logger.log(logger.HIGH, "Leaving NeverNote.tagTreeSelection");
2450     }
2451     // trigger the tag index to be refreshed
2452     @SuppressWarnings("unused")
2453         private void tagIndexUpdated() {
2454         tagIndexUpdated(true);
2455     }
2456     private void tagIndexUpdated(boolean reload) {
2457         logger.log(logger.HIGH, "Entering NeverNote.tagIndexUpdated");
2458                 if (selectedTagGUIDs == null)
2459                         selectedTagGUIDs = new ArrayList<String>();
2460                 if (reload)
2461                         listManager.reloadTagIndex();
2462
2463                 tagTree.blockSignals(true);
2464                 if (reload) {
2465                         tagTree.setIcons(conn.getTagTable().getAllIcons());
2466                         tagTree.load(listManager.getTagIndex());
2467                 }
2468
2469         for (int i=selectedTagGUIDs.size()-1; i>=0; i--) {
2470                 boolean found = tagTree.selectGuid(selectedTagGUIDs.get(i));
2471                 if (!found)
2472                         selectedTagGUIDs.remove(i);
2473         }
2474         tagTree.blockSignals(false);
2475         
2476                 browserWindow.setTag(getTagNamesForNote(currentNote));
2477         logger.log(logger.HIGH, "Leaving NeverNote.tagIndexUpdated");
2478     }   
2479     // Show/Hide note information
2480         @SuppressWarnings("unused")
2481         private void toggleTagWindow() {
2482                 logger.log(logger.HIGH, "Entering NeverNote.toggleTagWindow");
2483         if (tagTree.isVisible())
2484                 tagTree.hide();
2485         else
2486                 tagTree.show();
2487         menuBar.hideTags.setChecked(tagTree.isVisible());
2488         Global.saveWindowVisible("tagTree", tagTree.isVisible());
2489         logger.log(logger.HIGH, "Leaving NeverNote.toggleTagWindow");
2490     }   
2491         // A note's tags have been updated
2492         @SuppressWarnings("unused")
2493         private void updateNoteTags(String guid, List<String> tags) {
2494                 // Save any new tags.  We'll need them later.
2495                 List<String> newTags = new ArrayList<String>();
2496                 for (int i=0; i<tags.size(); i++) {
2497                         if (conn.getTagTable().findTagByName(tags.get(i))==null) 
2498                                 newTags.add(tags.get(i));
2499                 }
2500                 
2501                 listManager.saveNoteTags(guid, tags, true);
2502                 listManager.countTagResults(listManager.getNoteIndex());
2503                 StringBuffer names = new StringBuffer("");
2504                 for (int i=0; i<tags.size(); i++) {
2505                         names = names.append(tags.get(i));
2506                         if (i<tags.size()-1) {
2507                                 names.append(Global.tagDelimeter + " ");
2508                         }
2509                 }
2510                 browserWindow.setTag(names.toString());
2511                 
2512                 for (TabBrowse tab: tabWindows.values()) {
2513                         if (tab.getBrowserWindow().getNote().getGuid().equals(guid)) {
2514                                 int index = tabBrowser.indexOf(tab);
2515                                 noteDirty.put(index, true);
2516                                 break;
2517                         }
2518                 }
2519                 
2520                 // Now, we need to add any new tags to the tag tree
2521                 for (int i=0; i<newTags.size(); i++) 
2522                         tagTree.insertTag(newTags.get(i), conn.getTagTable().findTagByName(newTags.get(i)));
2523         }
2524         // Get a string containing all tag names for a note
2525         private String getTagNamesForNote(Note n) {
2526                 logger.log(logger.HIGH, "Entering NeverNote.getTagNamesForNote");
2527                 if (n==null || n.getGuid() == null || n.getGuid().equals(""))
2528                         return "";
2529                 StringBuffer buffer = new StringBuffer(100);
2530                 Vector<String> v = new Vector<String>();
2531                 List<String> guids = n.getTagGuids();
2532                 
2533                 if (guids == null) 
2534                         return "";
2535                 
2536                 for (int i=0; i<guids.size(); i++) {
2537                         v.add(listManager.getTagNameByGuid(guids.get(i)));
2538                 }
2539                 Comparator<String> comparator = Collections.reverseOrder();
2540                 Collections.sort(v,comparator);
2541                 Collections.reverse(v);
2542                 
2543                 for (int i = 0; i<v.size(); i++) {
2544                         if (i>0) 
2545                                 buffer.append(", ");
2546                         buffer.append(v.get(i));
2547                 }
2548                 
2549                 logger.log(logger.HIGH, "Leaving NeverNote.getTagNamesForNote");
2550                 return buffer.toString();
2551         }       
2552         // Tags were added via dropping notes from the note list
2553         @SuppressWarnings("unused")
2554         private void tagsAdded(String noteGuid, String tagGuid) {
2555                 String tagName = null;
2556                 for (int i=0; i<listManager.getTagIndex().size(); i++) {
2557                         if (listManager.getTagIndex().get(i).getGuid().equals(tagGuid)) {
2558                                 tagName = listManager.getTagIndex().get(i).getName();
2559                                 i=listManager.getTagIndex().size();
2560                         }
2561                 }
2562                 if (tagName == null)
2563                         return;
2564                 
2565                 for (int i=0; i<listManager.getMasterNoteIndex().size(); i++) {
2566                         if (listManager.getMasterNoteIndex().get(i).getGuid().equals(noteGuid)) {
2567                                 List<String> tagNames = new ArrayList<String>();
2568                                 tagNames.add(new String(tagName));
2569                                 Note n = listManager.getMasterNoteIndex().get(i);
2570                                 for (int j=0; j<n.getTagNames().size(); j++) {
2571                                         tagNames.add(new String(n.getTagNames().get(j)));
2572                                 }
2573                                 listManager.getNoteTableModel().updateNoteTags(noteGuid, n.getTagGuids(), tagNames);
2574                                 if (n.getGuid().equals(currentNoteGuid)) {
2575                                         Collections.sort(tagNames);
2576                                         String display = "";
2577                                         for (int j=0; j<tagNames.size(); j++) {
2578                                                 display = display+tagNames.get(j);
2579                                                 if (j+2<tagNames.size()) 
2580                                                         display = display+Global.tagDelimeter+" ";
2581                                         }
2582                                         browserWindow.setTag(display);
2583                                 }
2584                                 i=listManager.getMasterNoteIndex().size();
2585                         }
2586                 }
2587                 
2588                 
2589                 listManager.getNoteTableModel().updateNoteSyncStatus(noteGuid, false);
2590         }
2591         private void clearTagFilter() {
2592                 tagTree.blockSignals(true);
2593                 tagTree.clearSelection();
2594                 menuBar.noteRestoreAction.setVisible(false);
2595                 menuBar.tagEditAction.setEnabled(false);
2596                 menuBar.tagMergeAction.setEnabled(false);
2597                 menuBar.tagDeleteAction.setEnabled(false);
2598                 menuBar.tagIconAction.setEnabled(false);
2599                 selectedTagGUIDs.clear();
2600         listManager.setSelectedTags(selectedTagGUIDs);
2601         tagTree.blockSignals(false);
2602         }
2603         // Change the icon for a tag
2604         @SuppressWarnings("unused")
2605         private void setTagIcon() {
2606                 QTreeWidgetItem currentSelection;
2607                 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2608                 if (selections.size() == 0)
2609                         return;
2610                 
2611                 currentSelection = selections.get(0);   
2612                 String guid = currentSelection.text(2);
2613
2614                 QIcon currentIcon = currentSelection.icon(0);
2615                 QIcon icon = conn.getTagTable().getIcon(guid);
2616                 SetIcon dialog;
2617                 if (icon == null) {
2618                         dialog = new SetIcon(currentIcon, saveLastPath);
2619                         dialog.setUseDefaultIcon(true);
2620                 } else {
2621                         dialog = new SetIcon(icon, saveLastPath);
2622                         dialog.setUseDefaultIcon(false);
2623                 }
2624                 dialog.exec();
2625                 if (dialog.okPressed()) {
2626                 saveLastPath = dialog.getPath();
2627                         QIcon newIcon = dialog.getIcon();
2628                         conn.getTagTable().setIcon(guid, newIcon, dialog.getFileType());
2629                         if (newIcon == null) 
2630                                 newIcon = new QIcon(iconPath+"tag.png");
2631                         currentSelection.setIcon(0, newIcon);
2632                 }
2633         
2634         }
2635         // Merge tags
2636         @SuppressWarnings("unused")
2637         private void mergeTags() {
2638                 List<Tag> tags = new ArrayList<Tag>();
2639                 List<QTreeWidgetItem> selections = tagTree.selectedItems();
2640                 for (int i=0; i<selections.size(); i++) {
2641                         Tag record = new Tag();
2642                         record.setGuid(selections.get(i).text(2));
2643                         record.setName(selections.get(i).text(0));
2644                         tags.add(record);
2645                 }
2646
2647                 TagMerge mergeDialog = new TagMerge(tags);
2648                 mergeDialog.exec();
2649                 if (!mergeDialog.okClicked())
2650                         return;
2651                 String newGuid = mergeDialog.getNewTagGuid();
2652                 
2653                 for (int i=0; i<tags.size(); i++) {
2654                         if (!tags.get(i).getGuid().equals(newGuid)) {
2655                                 List<String> noteGuids = conn.getNoteTable().noteTagsTable.getTagNotes(tags.get(i).getGuid());
2656                                 for (int j=0; j<noteGuids.size(); j++) {
2657                                         String noteGuid = noteGuids.get(j);
2658                                         conn.getNoteTable().noteTagsTable.deleteNoteTag(noteGuid);
2659                                         if (!conn.getNoteTable().noteTagsTable.checkNoteNoteTags(noteGuid, newGuid))
2660                                                 conn.getNoteTable().noteTagsTable.saveNoteTag(noteGuid, newGuid, true);
2661                                 }
2662                         }
2663                 }
2664                 listManager.reloadIndexes();
2665         }
2666         
2667     //***************************************************************
2668     //***************************************************************
2669     //** These functions deal with Saved Search menu items
2670     //***************************************************************
2671     //***************************************************************
2672         // Add a new notebook
2673         @SuppressWarnings("unused")
2674         private void addSavedSearch() {
2675                 logger.log(logger.HIGH, "Inside NeverNote.addSavedSearch");
2676                 SavedSearchEdit edit = new SavedSearchEdit();
2677