OSDN Git Service

loggerを修正した
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / gui / RensoNoteList.java
1 /*
2  * This file is part of NeighborNote
3  * Copyright 2013 Yuki Takahashi
4  * 
5  * This file may be licensed under the terms of of the
6  * GNU General Public License Version 2 (the ``GPL'').
7  *
8  * Software distributed under the License is distributed
9  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
10  * express or implied. See the GPL for the specific language
11  * governing rights and limitations.
12  *
13  * You should have received a copy of the GPL along with this
14  * program. If not, go to http://www.gnu.org/licenses/gpl.html
15  * or write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18 */
19
20 package cx.fbn.nevernote.gui;
21
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28
29 import com.evernote.edam.type.Note;
30 import com.trolltech.qt.QThread;
31 import com.trolltech.qt.core.QByteArray;
32 import com.trolltech.qt.core.QFile;
33 import com.trolltech.qt.core.QSize;
34 import com.trolltech.qt.core.Qt.MouseButton;
35 import com.trolltech.qt.gui.QAction;
36 import com.trolltech.qt.gui.QApplication;
37 import com.trolltech.qt.gui.QContextMenuEvent;
38 import com.trolltech.qt.gui.QListWidget;
39 import com.trolltech.qt.gui.QListWidgetItem;
40 import com.trolltech.qt.gui.QMenu;
41
42 import cx.fbn.nevernote.Global;
43 import cx.fbn.nevernote.NeverNote;
44 import cx.fbn.nevernote.sql.DatabaseConnection;
45 import cx.fbn.nevernote.threads.CounterRunner;
46 import cx.fbn.nevernote.threads.ENRelatedNotesRunner;
47 import cx.fbn.nevernote.threads.ENThumbnailRunner;
48 import cx.fbn.nevernote.threads.SyncRunner;
49 import cx.fbn.nevernote.utilities.ApplicationLogger;
50 import cx.fbn.nevernote.utilities.Pair;
51
52 public class RensoNoteList extends QListWidget {
53         private final DatabaseConnection conn;
54         private final ApplicationLogger logger;
55         private final HashMap<QListWidgetItem, String> rensoNoteListItems;
56         private final HashMap<String, RensoNoteListItem> rensoNoteListTrueItems;
57         private String rensoNotePressedItemGuid;
58         private final QAction openNewTabAction;
59         private final QAction starAction;
60         private final QAction unstarAction;
61         private final QAction excludeNoteAction;
62         private final NeverNote parent;
63         private final QMenu menu;
64         private HashMap<String, Integer> mergedHistory;                         // マージされた操作履歴
65         private final SyncRunner syncRunner;
66         private final ENRelatedNotesRunner enRelatedNotesRunner;
67         private final QThread enRelatedNotesThread;
68         private final HashMap<String, List<String>> enRelatedNotesCache;        // Evernote関連ノートのキャッシュ<guid, 関連ノートリスト>
69         private final ENThumbnailRunner enThumbnailRunner;
70         private final QThread enThumbnailThread;
71         private String guid;
72         private int allPointSum;
73
74         public RensoNoteList(DatabaseConnection c, NeverNote p, SyncRunner syncRunner, ApplicationLogger logger) {
75                 this.logger = logger;
76                 this.logger.log(this.logger.HIGH, "Setting up rensoNoteList");
77                 allPointSum = 0;
78
79                 this.conn = c;
80                 this.parent = p;
81                 this.syncRunner = syncRunner;
82                 
83                 this.guid = new String();
84                 mergedHistory = new HashMap<String, Integer>();
85                 enRelatedNotesCache = new HashMap<String, List<String>>();
86                 this.enRelatedNotesRunner = new ENRelatedNotesRunner(this.syncRunner, "enRelatedNotesRunner.log");
87                 this.enRelatedNotesRunner.enRelatedNotesSignal.getENRelatedNotesFinished.connect(this, "enRelatedNotesComplete()");
88                 this.enRelatedNotesRunner.limitSignal.rateLimitReached.connect(parent, "informRateLimit(Integer)");
89                 this.enRelatedNotesThread = new QThread(enRelatedNotesRunner, "ENRelatedNotes Thread");
90                 this.getEnRelatedNotesThread().start();
91                 
92                 this.enThumbnailRunner = new ENThumbnailRunner("enThumbnailRunner.log", CounterRunner.NOTEBOOK, 
93                                         Global.getDatabaseUrl(), Global.getIndexDatabaseUrl(), Global.getResourceDatabaseUrl(), Global.getBehaviorDatabaseUrl(),
94                                         Global.getDatabaseUserid(), Global.getDatabaseUserPassword(), Global.cipherPassword);
95                 this.enThumbnailRunner.enThumbnailSignal.getENThumbnailFinished.connect(this, "enThumbnailComplete(String)");
96                 this.enThumbnailRunner.limitSignal.rateLimitReached.connect(parent, "informRateLimit(Integer)");
97                 this.enThumbnailThread = new QThread(enThumbnailRunner, "ENThumbnail Thread");
98                 this.enThumbnailThread.start();
99                 
100                 rensoNoteListItems = new HashMap<QListWidgetItem, String>();
101                 rensoNoteListTrueItems = new HashMap<String, RensoNoteListItem>();
102                 
103                 this.itemPressed.connect(this, "rensoNoteItemPressed(QListWidgetItem)");
104                 
105                 // コンテキストメニュー作成
106                 menu = new QMenu(this);
107                 // 新しいタブで開くアクション生成
108                 openNewTabAction = new QAction(tr("Open in New Tab"), this);
109                 openNewTabAction.setToolTip(tr("Open this note in new tab"));
110                 openNewTabAction.triggered.connect(parent, "openNewTabFromRNL()");
111                 // スターをつけるアクション生成
112                 starAction = new QAction(tr("Add Star"), this);
113                 starAction.setToolTip(tr("Add Star to this item"));
114                 starAction.triggered.connect(parent, "starNote()");
115                 // スターを外すアクション生成
116                 unstarAction = new QAction(tr("Remove Star"), this);
117                 unstarAction.setToolTip(tr("Remove Star from this item"));
118                 unstarAction.triggered.connect(parent, "unstarNote()");
119                 // このノートを除外するアクション生成
120                 excludeNoteAction = new QAction(tr("Exclude"), this);
121                 excludeNoteAction.setToolTip(tr("Exclude this note from RensoNoteList"));
122                 excludeNoteAction.triggered.connect(parent, "excludeNote()");
123                 // コンテキストメニューに登録
124                 menu.addAction(openNewTabAction);
125                 menu.addAction(excludeNoteAction);
126                 menu.aboutToHide.connect(this, "contextMenuHidden()");
127                 
128                 this.logger.log(this.logger.HIGH, "rensoNoteList setup complete");
129         }
130         
131         // オーバーロード
132         // 現在開いているノートの連想ノートリストをリフレッシュ
133         public void refreshRensoNoteList() {
134                 refreshRensoNoteList(guid);
135         }
136
137         // 連想ノートリストをリフレッシュ
138         public void refreshRensoNoteList(String guid) {
139                 logger.log(logger.HIGH, "Entering RensoNoteList.refreshRensoNoteList guid = " + guid);
140
141                 this.clear();
142                 rensoNoteListItems.clear();
143                 rensoNoteListTrueItems.clear();
144                 mergedHistory = new HashMap<String, Integer>();
145
146                 if (!this.isEnabled()) {
147                         return;
148                 }
149                 if (guid == null || guid.equals("")) {
150                         return;
151                 }
152                 
153                 this.guid = guid;
154                 // すでにEvernote関連ノートがキャッシュされているか確認
155                 boolean isCached;
156                 isCached = enRelatedNotesCache.containsKey(guid);
157                 if (!isCached) {        // キャッシュ無し
158                         // Evernoteの関連ノートを別スレッドで取得させる
159                         enRelatedNotesRunner.addGuid(guid);
160                 } else {                        // キャッシュ有り
161                         List<String> relatedNoteGuids = enRelatedNotesCache.get(guid);
162                         addENRelatedNotes(relatedNoteGuids);
163                 }
164                 
165                 calculateHistory(guid);
166                 repaintRensoNoteList(false);
167
168                 logger.log(logger.HIGH, "Leaving RensoNoteList.refreshRensoNoteList");
169         }
170         
171         // 操作履歴をデータベースから取得してノートごとの関連度を算出、その後mergedHistoryに追加
172         private void calculateHistory(String guid) {
173                 logger.log(logger.EXTREME, "Entering RensoNoteList.calculateHistory guid = " + guid);
174                 
175                 // browseHistory<guid, 回数(ポイント)>
176                 HashMap<String, Integer> browseHistory = conn.getHistoryTable().getBehaviorHistory("browse", guid);
177                 addWeight(browseHistory, Global.getBrowseWeight());
178                 mergedHistory = mergeHistory(filterHistory(browseHistory), mergedHistory);
179                 
180                 // copy&pasteHistory<guid, 回数(ポイント)>
181                 HashMap<String, Integer> copyAndPasteHistory = conn.getHistoryTable().getBehaviorHistory("copy & paste", guid);
182                 addWeight(copyAndPasteHistory, Global.getCopyPasteWeight());
183                 mergedHistory = mergeHistory(filterHistory(copyAndPasteHistory), mergedHistory);
184                 
185                 // addNewNoteHistory<guid, 回数(ポイント)>
186                 HashMap<String, Integer> addNewNoteHistory = conn.getHistoryTable().getBehaviorHistory("addNewNote", guid);
187                 addWeight(addNewNoteHistory, Global.getAddNewNoteWeight());
188                 mergedHistory = mergeHistory(filterHistory(addNewNoteHistory), mergedHistory);
189                 
190                 // rensoItemClickHistory<guid, 回数(ポイント)>
191                 HashMap<String, Integer> rensoItemClickHistory = conn.getHistoryTable().getBehaviorHistory("rensoItemClick", guid);
192                 addWeight(rensoItemClickHistory, Global.getRensoItemClickWeight());
193                 mergedHistory = mergeHistory(filterHistory(rensoItemClickHistory), mergedHistory);
194                 
195                 // sameTagHistory<guid, 回数(ポイント)>
196                 HashMap<String, Integer> sameTagHistory = conn.getHistoryTable().getBehaviorHistory("sameTag", guid);
197                 addWeight(sameTagHistory, Global.getSameTagWeight());
198                 mergedHistory = mergeHistory(filterHistory(sameTagHistory), mergedHistory);
199                 
200                 // sameNotebookNoteHistory<guid, 回数(ポイント)>
201                 HashMap<String, Integer> sameNotebookHistory = conn.getHistoryTable().getBehaviorHistory("sameNotebook", guid);
202                 addWeight(sameNotebookHistory, Global.getSameNotebookWeight());
203                 mergedHistory = mergeHistory(filterHistory(sameNotebookHistory), mergedHistory);
204                 logger.log(logger.EXTREME, "Leaving RensoNoteList.calculateHistory");
205         }
206         
207         // 操作回数に重み付けする
208         private void addWeight(HashMap<String, Integer> history, int weight){
209                 logger.log(logger.EXTREME, "Entering RensoNoteList.addWeight");
210                 
211                 Set<String> keySet = history.keySet();
212                 Iterator<String> hist_iterator = keySet.iterator();
213                 while(hist_iterator.hasNext()){
214                         String key = hist_iterator.next();
215                         history.put(key, history.get(key) * weight);
216                 }
217                 
218                 logger.log(logger.EXTREME, "Leaving RensoNoteList.addWeight");
219         }
220         
221         // 連想ノートリストを再描画
222         private void repaintRensoNoteList(boolean needClear) {
223                 logger.log(logger.EXTREME, "Entering RensoNoteList.repaintRensoNoteList");
224                 
225                 if (needClear) {
226                         this.clear();
227                         rensoNoteListItems.clear();
228                         rensoNoteListTrueItems.clear();
229                 }
230                 
231                 if (!this.isEnabled()) {
232                         return;
233                 }
234                 
235                 // すべての関連ポイントの合計を取得(関連度のパーセント算出に利用)
236                 allPointSum = 0;
237                 for (int p : mergedHistory.values()) {
238                         allPointSum += p;
239                 }
240                 
241                 addRensoNoteList(mergedHistory);
242                 
243                 logger.log(logger.EXTREME, "Leaving RensoNoteList.repaintRensoNoteList");
244         }
245         
246         // 引数1と引数2をマージしたハッシュマップを返す
247         private HashMap<String, Integer> mergeHistory(HashMap<String, Integer> History1, HashMap<String, Integer> History2){
248                 logger.log(logger.EXTREME, "Entering RensoNoteList.mergeHistory");
249                 
250                 HashMap<String, Integer> mergedHistory = new HashMap<String, Integer>();
251                 
252                 mergedHistory.putAll(History1);
253                 
254                 Set<String> keySet = History2.keySet();
255                 Iterator<String> hist2_iterator = keySet.iterator();
256                 while(hist2_iterator.hasNext()){
257                         String key = hist2_iterator.next();
258                         if(mergedHistory.containsKey(key)){
259                                 mergedHistory.put(key, mergedHistory.get(key) + History2.get(key));
260                         }else {
261                                 mergedHistory.put(key, History2.get(key));
262                         }
263                 }
264                 
265                 logger.log(logger.EXTREME, "Leaving RensoNoteList.mergeHistory");
266                 return mergedHistory;
267         }
268         
269         // 連想ノートリストにハッシュマップのデータを追加
270         private void addRensoNoteList(HashMap<String, Integer> History){
271                 logger.log(logger.EXTREME, "Entering RensoNoteList.addRensoNoteList");
272                 
273                 enThumbnailRunner.setUser(Global.getUserInformation());
274                 enThumbnailRunner.setServerUrl(Global.getServer());
275                 
276                 String currentNoteGuid = new String(parent.getCurrentNoteGuid());
277                 
278                 // スター付きノートとスター無しノートを分ける
279                 HashMap<String, Integer> staredNotes = new HashMap<String, Integer>();  // スター付きノートのマップ
280                 HashMap<String, Integer> normalNotes = new HashMap<String, Integer>();  // スター無しノートのマップ
281                 for (String nextGuid: History.keySet()) {
282                         int relationPoint = History.get(nextGuid);
283                         boolean isStared = conn.getStaredTable().existNote(currentNoteGuid, nextGuid);
284                         if (isStared) {
285                                 staredNotes.put(nextGuid, relationPoint);
286                         } else {
287                                 normalNotes.put(nextGuid, relationPoint);
288                         }
289                 }
290                 
291                 // 連想ノートリストアイテムの最大表示数まで繰り返す
292                 for (int i = 0; i < Global.getRensoListItemMaximum(); i++) {
293                         // スター付きノートがあれば先に処理する
294                         HashMap<String, Integer> tmpMap = new HashMap<String, Integer>();
295                         if (!staredNotes.isEmpty()) {
296                                 tmpMap = staredNotes;
297                         }else if (!normalNotes.isEmpty()) {
298                                 tmpMap = normalNotes;
299                         }
300                         
301                         // 操作回数が多い順に取り出して連想ノートリストに追加する
302                         if (!tmpMap.isEmpty()) {
303                                 int maxNum = -1;
304                                 String maxGuid = new String();
305                                 
306                                 for (String nextGuid: tmpMap.keySet()) {
307                                         int relationPoint = tmpMap.get(nextGuid);
308                                         
309                                         // 最大ノート探索する
310                                         if (relationPoint > maxNum) {
311                                                 maxNum = relationPoint;
312                                                 maxGuid = nextGuid;
313                                         }
314                                 }
315                                 
316                                 // 次の最大値探索で邪魔なので最大値をHashMapから削除
317                                 tmpMap.remove(maxGuid);
318         
319                                 // 関連度最大のノートがアクティブか確認
320                                 Note maxNote = conn.getNoteTable().getNote(maxGuid, true, false, false, false, true);
321                                 boolean isNoteActive = false;
322                                 if(maxNote != null) {
323                                         isNoteActive = maxNote.isActive();
324                                 }
325                                 
326                                 // 存在していて、かつ関連度0でなければノート情報を取得して連想ノートリストに追加
327                                 if (isNoteActive && maxNum > 0) {
328                                         // Evernoteサムネイルが取得済みか確認。未取得ならサムネイル取得スレッドにキュー
329                                         if (Global.isConnected) {
330                                                 String thumbnailName = Global.getFileManager().getResDirPath("enThumbnail-" + maxGuid + ".png");
331                                                 QFile thumbnail = new QFile(thumbnailName);
332                                                 if (!thumbnail.exists()) {      // Evernoteサムネイルがファイルとして存在しない
333                                                         QByteArray data = conn.getNoteTable().getENThumbnail(maxGuid);
334                                                         if (data == null) {     // Evernoteサムネイル未取得
335                                                                 enThumbnailRunner.addGuid(maxGuid);
336                                                         }
337                                                 }
338                                         }
339                                         
340                                         // スター付きか確認
341                                         boolean isStared;
342                                         isStared = conn.getStaredTable().existNote(currentNoteGuid, maxGuid);
343                                         
344                                         QListWidgetItem item = new QListWidgetItem();
345                                         RensoNoteListItem myItem = new RensoNoteListItem(maxNote, maxNum, isStared, allPointSum, conn, this);
346                                         item.setSizeHint(new QSize(0, 90));
347                                         this.addItem(item);
348                                         this.setItemWidget(item, myItem);
349                                         rensoNoteListItems.put(item, maxGuid);
350                                         rensoNoteListTrueItems.put(maxGuid, myItem);
351                                 } else {
352                                         break;
353                                 }
354                         }
355                 }
356                 logger.log(logger.EXTREME, "Leaving RensoNoteList.addRensoNoteList");
357         }
358
359         // リストのアイテムから対象ノートのguidを取得
360         public String getNoteGuid(QListWidgetItem item) {
361                 return rensoNoteListItems.get(item);
362         }
363         
364         // 関連ノートリストの右クリックメニュー
365         @Override
366         public void contextMenuEvent(QContextMenuEvent event){
367                 logger.log(logger.EXTREME, "Entering RensoNoteList.contextMenuEvent");
368                 
369                 if (rensoNotePressedItemGuid == null || rensoNotePressedItemGuid.equals("")) {
370                         return;
371                 }
372                 
373                 // STAR, UNSTARがあれば、一度消す
374                 List<QAction> menuActions = new ArrayList<QAction>(menu.actions());
375                 if (menuActions.contains(starAction)) {
376                         menu.removeAction(starAction);
377                 }
378                 if (menuActions.contains(unstarAction)) {
379                         menu.removeAction(unstarAction);
380                 }
381                 
382                 // 対象アイテムがスター付きなら「UNSTAR」、スター無しなら「STAR」を追加
383                 String currentNoteGuid = parent.getCurrentNoteGuid();
384                 boolean isExist = conn.getStaredTable().existNote(currentNoteGuid, rensoNotePressedItemGuid);
385                 if (isExist) {
386                         menu.insertAction(excludeNoteAction, unstarAction);
387                 } else {
388                         menu.insertAction(excludeNoteAction, starAction);
389                 }
390                 
391                 // コンテキストメニューを表示
392                 menu.exec(event.globalPos());
393                 
394                 rensoNotePressedItemGuid = null;
395                 
396                 logger.log(logger.EXTREME, "Leaving RensoNoteList.contextMenuEvent");
397         }
398         
399         // コンテキストメニューが表示されているかどうか
400         public boolean isContextMenuVisible() {
401                 return menu.isVisible();
402         }
403         
404         // コンテキストメニューが閉じられた時
405         @SuppressWarnings("unused")
406         private void contextMenuHidden() {
407                 for (RensoNoteListItem item : rensoNoteListTrueItems.values()) {
408                         item.setDefaultBackground();
409                 }
410         }
411         
412         // ユーザが連想ノートリストのアイテムを選択した時の処理
413         @SuppressWarnings("unused")
414         private void rensoNoteItemPressed(QListWidgetItem current) {
415                 logger.log(logger.HIGH, "Entering RensoNoteList.rensoNoteItemPressed");
416                 
417                 rensoNotePressedItemGuid = null;
418                 // 右クリックだったときの処理
419                 if (QApplication.mouseButtons().isSet(MouseButton.RightButton)) {
420                         rensoNotePressedItemGuid = getNoteGuid(current);
421                 }
422                 
423                 logger.log(logger.HIGH, "Leaving RensoNoteList.rensoNoteItemPressed");
424         }
425         
426         // Evernoteの関連ノートの取得が完了
427         @SuppressWarnings("unused")
428         private void enRelatedNotesComplete() {
429                 logger.log(logger.HIGH, "Entering RensoNoteList.enRelatedNotesComplete");
430                 
431                 Pair<String, List<String>> enRelatedNoteGuidPair = enRelatedNotesRunner.getENRelatedNoteGuids();        // <元ノートguid, 関連ノートguidリスト>
432                 
433                 if (enRelatedNoteGuidPair == null) {
434                         return;
435                 }
436                 
437                 String sourceGuid = enRelatedNoteGuidPair.getFirst();
438                 List<String> enRelatedNoteGuids = enRelatedNoteGuidPair.getSecond();
439                 
440                 
441                 if (sourceGuid != null && !sourceGuid.equals("") && enRelatedNoteGuids != null) {       // Evernote関連ノートがnullでなければ
442                         // まずキャッシュに追加
443                         enRelatedNotesCache.put(sourceGuid, enRelatedNoteGuids);
444                         
445                         if (!enRelatedNoteGuids.isEmpty()) {    // Evernote関連ノートが存在していて
446                                 if (sourceGuid.equals(this.guid)) {     // 取得したデータが今開いているノートの関連ノートなら
447                                         // mergedHistoryにEvernote関連ノートを追加してから再描画
448                                         addENRelatedNotes(enRelatedNoteGuids);
449                                         repaintRensoNoteList(true);
450                                 }
451                         }
452                 }
453                 
454                 logger.log(logger.HIGH, "Leaving RensoNoteList.enRelatedNotesComplete");
455         }
456         
457         // Evernote関連ノートの関連度情報をmergedHistoryに追加
458         private void addENRelatedNotes(List<String> relatedNoteGuids) {
459                 logger.log(logger.EXTREME, "Entering RensoNoteList.addENRelatedNotes");
460                 
461                 // Evernote関連ノート<guid, 関連ポイント>
462                 HashMap<String, Integer> enRelatedNotes = new HashMap<String, Integer>();
463                 
464                 for (String relatedGuid : relatedNoteGuids) {
465                         enRelatedNotes.put(relatedGuid, Global.getENRelatedNotesWeight());
466                 }
467                 
468                 mergedHistory = mergeHistory(filterHistory(enRelatedNotes), mergedHistory);
469                 
470                 logger.log(logger.EXTREME, "Leaving RensoNoteList.addENRelatedNotes");
471         }
472         
473         // Evernoteの関連ノート取得スレッドを終了させる
474         public boolean stopThread() {
475                 logger.log(logger.HIGH, "Entering RensoNoteList.stopThread");
476                 
477                 if (!enRelatedNotesRunner.addStop()) {
478                         logger.log(logger.HIGH, "RensoNoteList.stopThread failed(enRelatedNotesRunner)");
479                         return false;
480                 }
481                 if (!enThumbnailRunner.addStop()) {
482                         logger.log(logger.HIGH, "RensoNoteList.stopThread failed(enThumbnailRunner)");
483                         return false;
484                 }
485                 
486                 logger.log(logger.HIGH, "RensoNoteList.stopThread succeeded");
487                 return true;
488         }
489
490         public QThread getEnRelatedNotesThread() {
491                 return enRelatedNotesThread;
492         }
493         
494         public String getGuid() {
495                 return guid;
496         }
497         
498         // ローカルに存在していて、かつアクティブなノートだけを返す
499         private HashMap<String, Integer> filterHistory(HashMap<String, Integer> sourceHistory) {
500                 HashMap<String, Integer> dstHistory = new HashMap<String, Integer>();
501                 
502                 for (String guid : sourceHistory.keySet()) {
503                         if (conn.getNoteTable().exists(guid)) {
504                                 if (conn.getNoteTable().getNote(guid, false, false, false, false, false).isActive()) {
505                                         dstHistory.put(guid, sourceHistory.get(guid));
506                                 }
507                         }
508                 }
509                 
510                 return dstHistory;
511         }
512         
513         /**
514          * Evernoteサムネイルの取得が完了
515          * 
516          * @param guid 現在開いているノートのguid
517          */
518         @SuppressWarnings("unused")
519         private void enThumbnailComplete(String guid) {
520                 logger.log(logger.HIGH, "Entering RensoNoteList.enThumbnailComplete");
521                 
522                 for (Map.Entry<String, RensoNoteListItem> e : rensoNoteListTrueItems.entrySet()) {
523                         // サムネイル取得が完了したノートが現在の連想ノートリストに表示されていたら再描画
524                         if (guid.equals(e.getKey())) {
525                                 e.getValue().repaint();
526                         }
527                 }
528                 
529                 logger.log(logger.HIGH, "Leaving RensoNoteList.enThumbnailComplete");
530         }
531 }