OSDN Git Service

STAR→Add Star, UNSTAR→Remove Star
[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 // ICHANGED
21 package cx.fbn.nevernote.gui;
22
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Set;
28
29 import com.evernote.edam.type.Note;
30 import com.trolltech.qt.core.QSize;
31 import com.trolltech.qt.core.Qt.MouseButton;
32 import com.trolltech.qt.gui.QAction;
33 import com.trolltech.qt.gui.QApplication;
34 import com.trolltech.qt.gui.QContextMenuEvent;
35 import com.trolltech.qt.gui.QListWidget;
36 import com.trolltech.qt.gui.QListWidgetItem;
37 import com.trolltech.qt.gui.QMenu;
38
39 import cx.fbn.nevernote.Global;
40 import cx.fbn.nevernote.NeverNote;
41 import cx.fbn.nevernote.sql.DatabaseConnection;
42 import cx.fbn.nevernote.utilities.ApplicationLogger;
43
44 public class RensoNoteList extends QListWidget {
45         private final DatabaseConnection conn;
46         private final ApplicationLogger logger;
47         private final HashMap<QListWidgetItem, String> rensoNoteListItems;
48         private final List<RensoNoteListItem> rensoNoteListTrueItems;
49         private String rensoNotePressedItemGuid;
50         
51         private final QAction openNewTabAction;
52         private final QAction starAction;
53         private final QAction unstarAction;
54         private final QAction excludeNoteAction;
55         private final NeverNote parent;
56         private final QMenu menu;
57         private int allPointSum;
58
59         public RensoNoteList(DatabaseConnection c, NeverNote p) {
60                 logger = new ApplicationLogger("rensoNoteList.log");
61                 logger.log(logger.HIGH, "Setting up rensoNoteList");
62                 allPointSum = 0;
63
64                 conn = c;
65                 this.parent = p;
66                 rensoNoteListItems = new HashMap<QListWidgetItem, String>();
67                 rensoNoteListTrueItems = new ArrayList<RensoNoteListItem>();
68                 
69                 this.itemPressed.connect(this, "rensoNoteItemPressed(QListWidgetItem)");
70                 
71                 // コンテキストメニュー作成
72                 menu = new QMenu(this);
73                 // 新しいタブで開くアクション生成
74                 openNewTabAction = new QAction(tr("Open in New Tab"), this);
75                 openNewTabAction.setToolTip(tr("Open this note in new tab"));
76                 openNewTabAction.triggered.connect(parent, "openNewTabFromRNL()");
77                 // スターをつけるアクション生成
78                 starAction = new QAction(tr("Add Star"), this);
79                 starAction.setToolTip(tr("Add Star to this item"));
80                 starAction.triggered.connect(parent, "starNote()");
81                 // スターを外すアクション生成
82                 unstarAction = new QAction(tr("Remove Star"), this);
83                 unstarAction.setToolTip(tr("Remove Star from this item"));
84                 unstarAction.triggered.connect(parent, "unstarNote()");
85                 // このノートを除外するアクション生成
86                 excludeNoteAction = new QAction(tr("Exclude"), this);
87                 excludeNoteAction.setToolTip(tr("Exclude this note from RensoNoteList"));
88                 excludeNoteAction.triggered.connect(parent, "excludeNote()");
89                 // コンテキストメニューに登録
90                 menu.addAction(openNewTabAction);
91                 menu.addAction(excludeNoteAction);
92                 menu.aboutToHide.connect(this, "contextMenuHidden()");
93                 
94                 logger.log(logger.HIGH, "rensoNoteList setup complete");
95         }
96
97         public void refreshRensoNoteList(String guid) {
98                 logger.log(logger.HIGH, "Entering RensoNoteList.refreshRensoNoteList");
99
100                 this.clear();
101                 rensoNoteListItems.clear();
102                 rensoNoteListTrueItems.clear();
103
104                 if (!this.isEnabled()) {
105                         return;
106                 }
107                 if (guid == null || guid.equals("")) {
108                         return;
109                 }
110
111                 HashMap<String, Integer> mergedHistory = new HashMap<String, Integer>();
112                 
113                 // browseHistory<guid, 回数(ポイント)>
114                 HashMap<String, Integer> browseHistory = conn.getHistoryTable().getBehaviorHistory("browse", guid);
115                 addWeight(browseHistory, Global.getBrowseWeight());
116                 mergedHistory = mergeHistory(browseHistory, new HashMap<String, Integer>());
117                 
118                 // copy&pasteHistory<guid, 回数(ポイント)>
119                 HashMap<String, Integer> copyAndPasteHistory = conn.getHistoryTable().getBehaviorHistory("copy & paste", guid);
120                 addWeight(copyAndPasteHistory, Global.getCopyPasteWeight());
121                 mergedHistory = mergeHistory(copyAndPasteHistory, mergedHistory);
122                 
123                 // addNewNoteHistory<guid, 回数(ポイント)>
124                 HashMap<String, Integer> addNewNoteHistory = conn.getHistoryTable().getBehaviorHistory("addNewNote", guid);
125                 addWeight(addNewNoteHistory, Global.getAddNewNoteWeight());
126                 mergedHistory = mergeHistory(addNewNoteHistory, mergedHistory);
127                 
128                 // rensoItemClickHistory<guid, 回数(ポイント)>
129                 HashMap<String, Integer> rensoItemClickHistory = conn.getHistoryTable().getBehaviorHistory("rensoItemClick", guid);
130                 addWeight(rensoItemClickHistory, Global.getRensoItemClickWeight());
131                 mergedHistory = mergeHistory(rensoItemClickHistory, mergedHistory);
132                 
133                 // sameTagHistory<guid, 回数(ポイント)>
134                 HashMap<String, Integer> sameTagHistory = conn.getHistoryTable().getBehaviorHistory("sameTag", guid);
135                 addWeight(sameTagHistory, Global.getSameTagWeight());
136                 mergedHistory = mergeHistory(sameTagHistory, mergedHistory);
137                 
138                 // sameNotebookNoteHistory<guid, 回数(ポイント)>
139                 HashMap<String, Integer> sameNotebookHistory = conn.getHistoryTable().getBehaviorHistory("sameNotebook", guid);
140                 addWeight(sameNotebookHistory, Global.getSameNotebookWeight());
141                 mergedHistory = mergeHistory(sameNotebookHistory, mergedHistory);
142                 
143                 // すべての関連ポイントの合計を取得(関連度のパーセント算出に利用)
144                 allPointSum = 0;
145                 for (int p : mergedHistory.values()) {
146                         allPointSum += p;
147                 }
148                 
149                 addRensoNoteList(mergedHistory);
150
151                 logger.log(logger.HIGH, "Leaving RensoNoteList.refreshRensoNoteList");
152         }
153         
154         // 操作回数に重み付けする
155         private void addWeight(HashMap<String, Integer> history, int weight){
156                 Set<String> keySet = history.keySet();
157                 Iterator<String> hist_iterator = keySet.iterator();
158                 while(hist_iterator.hasNext()){
159                         String key = hist_iterator.next();
160                         history.put(key, history.get(key) * weight);
161                 }
162         }
163         
164         // 引数1と引数2をマージしたハッシュマップを返す
165         private HashMap<String, Integer> mergeHistory(HashMap<String, Integer> History1, HashMap<String, Integer> History2){
166                 HashMap<String, Integer> mergedHistory = new HashMap<String, Integer>();
167                 
168                 mergedHistory.putAll(History1);
169                 
170                 Set<String> keySet = History2.keySet();
171                 Iterator<String> hist2_iterator = keySet.iterator();
172                 while(hist2_iterator.hasNext()){
173                         String key = hist2_iterator.next();
174                         if(mergedHistory.containsKey(key)){
175                                 mergedHistory.put(key, mergedHistory.get(key) + History2.get(key));
176                         }else {
177                                 mergedHistory.put(key, History2.get(key));
178                         }
179                 }
180
181                 return mergedHistory;
182         }
183         
184         private void addRensoNoteList(HashMap<String, Integer> History){
185                 String currentNoteGuid = new String(parent.getCurrentNoteGuid());
186                 
187                 // スター付きノートとスター無しノートを分ける
188                 HashMap<String, Integer> staredNotes = new HashMap<String, Integer>();  // スター付きノートのマップ
189                 HashMap<String, Integer> normalNotes = new HashMap<String, Integer>();  // スター無しノートのマップ
190                 for (String nextGuid: History.keySet()) {
191                         int relationPoint = History.get(nextGuid);
192                         boolean isStared = conn.getStaredTable().existNote(currentNoteGuid, nextGuid);
193                         if (isStared) {
194                                 staredNotes.put(nextGuid, relationPoint);
195                         } else {
196                                 normalNotes.put(nextGuid, relationPoint);
197                         }
198                 }
199                 
200                 // 連想ノートリストアイテムの最大表示数まで繰り返す
201                 for (int i = 0; i < Global.getRensoListItemMaximum(); i++) {
202                         // スター付きノートがあれば先に処理する
203                         HashMap<String, Integer> tmpMap = new HashMap<String, Integer>();
204                         if (!staredNotes.isEmpty()) {
205                                 tmpMap = staredNotes;
206                         }else if (!normalNotes.isEmpty()) {
207                                 tmpMap = normalNotes;
208                         }
209                         
210                         // 操作回数が多い順に取り出して連想ノートリストに追加する
211                         if (!tmpMap.isEmpty()) {
212                                 int maxNum = -1;
213                                 String maxGuid = new String();
214                                 
215                                 for (String nextGuid: tmpMap.keySet()) {
216                                         int relationPoint = tmpMap.get(nextGuid);
217                                         
218                                         // 最大ノート探索する
219                                         if (relationPoint > maxNum) {
220                                                 maxNum = relationPoint;
221                                                 maxGuid = nextGuid;
222                                         }
223                                 }
224                                 
225                                 // 次の最大値探索で邪魔なので最大値をHashMapから削除
226                                 tmpMap.remove(maxGuid);
227         
228                                 // 関連度最大のノートがアクティブか確認
229                                 Note maxNote = conn.getNoteTable().getNote(maxGuid, true, false, false, false, true);
230                                 boolean isNoteActive = false;
231                                 if(maxNote != null) {
232                                         isNoteActive = maxNote.isActive();
233                                 }
234                                 
235                                 // 存在していて、かつ関連度0でなければノート情報を取得して連想ノートリストに追加
236                                 if (isNoteActive && maxNum > 0) {
237                                         // スター付きか確認
238                                         boolean isStared;
239                                         isStared = conn.getStaredTable().existNote(currentNoteGuid, maxGuid);
240                                         
241                                         QListWidgetItem item = new QListWidgetItem();
242                                         RensoNoteListItem myItem = new RensoNoteListItem(maxNote, maxNum, isStared, allPointSum, conn, this);
243                                         item.setSizeHint(new QSize(0, 90));
244                                         this.addItem(item);
245                                         this.setItemWidget(item, myItem);
246                                         rensoNoteListItems.put(item, maxGuid);
247                                         rensoNoteListTrueItems.add(myItem);
248                                 } else {
249                                         break;
250                                 }
251                         }
252                 }
253         }
254
255         // リストのアイテムから対象ノートのguidを取得
256         public String getNoteGuid(QListWidgetItem item) {
257                 return rensoNoteListItems.get(item);
258         }
259         
260         // 関連ノートリストの右クリックメニュー
261         @Override
262         public void contextMenuEvent(QContextMenuEvent event){
263                 if (rensoNotePressedItemGuid == null || rensoNotePressedItemGuid.equals("")) {
264                         return;
265                 }
266                 
267                 // STAR, UNSTARがあれば、一度消す
268                 List<QAction> menuActions = new ArrayList<QAction>(menu.actions());
269                 if (menuActions.contains(starAction)) {
270                         menu.removeAction(starAction);
271                 }
272                 if (menuActions.contains(unstarAction)) {
273                         menu.removeAction(unstarAction);
274                 }
275                 
276                 // 対象アイテムがスター付きなら「UNSTAR」、スター無しなら「STAR」を追加
277                 String currentNoteGuid = parent.getCurrentNoteGuid();
278                 boolean isExist = conn.getStaredTable().existNote(currentNoteGuid, rensoNotePressedItemGuid);
279                 if (isExist) {
280                         menu.insertAction(excludeNoteAction, unstarAction);
281                 } else {
282                         menu.insertAction(excludeNoteAction, starAction);
283                 }
284                 
285                 // コンテキストメニューを表示
286                 menu.exec(event.globalPos());
287                 
288                 rensoNotePressedItemGuid = null;
289         }
290         
291         // コンテキストメニューが表示されているかどうか
292         public boolean isContextMenuVisible() {
293                 return menu.isVisible();
294         }
295         
296         // コンテキストメニューが閉じられた時
297         @SuppressWarnings("unused")
298         private void contextMenuHidden() {
299                 for (int i = 0; i < rensoNoteListTrueItems.size(); i++) {
300                         RensoNoteListItem item = rensoNoteListTrueItems.get(i);
301                         item.setDefaultBackground();
302                 }
303         }
304         
305         // ユーザが連想ノートリストのアイテムを選択した時の処理
306         @SuppressWarnings("unused")
307         private void rensoNoteItemPressed(QListWidgetItem current) {
308                 rensoNotePressedItemGuid = null;
309                 // 右クリックだったときの処理
310                 if (QApplication.mouseButtons().isSet(MouseButton.RightButton)) {
311                         rensoNotePressedItemGuid = getNoteGuid(current);
312                 }
313         }
314 }