2 * This file is part of NeighborNote
3 * Copyright 2013 Yuki Takahashi
5 * This file may be licensed under the terms of of the
6 * GNU General Public License Version 2 (the ``GPL'').
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.
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.
21 package cx.fbn.nevernote.gui;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
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;
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;
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;
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;
59 public RensoNoteList(DatabaseConnection c, NeverNote p) {
60 logger = new ApplicationLogger("rensoNoteList.log");
61 logger.log(logger.HIGH, "Setting up rensoNoteList");
66 rensoNoteListItems = new HashMap<QListWidgetItem, String>();
67 rensoNoteListTrueItems = new ArrayList<RensoNoteListItem>();
69 this.itemPressed.connect(this, "rensoNoteItemPressed(QListWidgetItem)");
72 menu = new QMenu(this);
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()");
78 starAction = new QAction(tr("Add Star"), this);
79 starAction.setToolTip(tr("Add Star to this item"));
80 starAction.triggered.connect(parent, "starNote()");
82 unstarAction = new QAction(tr("Remove Star"), this);
83 unstarAction.setToolTip(tr("Remove Star from this item"));
84 unstarAction.triggered.connect(parent, "unstarNote()");
86 excludeNoteAction = new QAction(tr("Exclude"), this);
87 excludeNoteAction.setToolTip(tr("Exclude this note from RensoNoteList"));
88 excludeNoteAction.triggered.connect(parent, "excludeNote()");
90 menu.addAction(openNewTabAction);
91 menu.addAction(excludeNoteAction);
92 menu.aboutToHide.connect(this, "contextMenuHidden()");
94 logger.log(logger.HIGH, "rensoNoteList setup complete");
97 public void refreshRensoNoteList(String guid) {
98 logger.log(logger.HIGH, "Entering RensoNoteList.refreshRensoNoteList");
101 rensoNoteListItems.clear();
102 rensoNoteListTrueItems.clear();
104 if (!this.isEnabled()) {
107 if (guid == null || guid.equals("")) {
111 HashMap<String, Integer> mergedHistory = new HashMap<String, Integer>();
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>());
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);
123 // addNewNoteHistory<guid, 回数(ポイント)>
124 HashMap<String, Integer> addNewNoteHistory = conn.getHistoryTable().getBehaviorHistory("addNewNote", guid);
125 addWeight(addNewNoteHistory, Global.getAddNewNoteWeight());
126 mergedHistory = mergeHistory(addNewNoteHistory, mergedHistory);
128 // rensoItemClickHistory<guid, 回数(ポイント)>
129 HashMap<String, Integer> rensoItemClickHistory = conn.getHistoryTable().getBehaviorHistory("rensoItemClick", guid);
130 addWeight(rensoItemClickHistory, Global.getRensoItemClickWeight());
131 mergedHistory = mergeHistory(rensoItemClickHistory, mergedHistory);
133 // sameTagHistory<guid, 回数(ポイント)>
134 HashMap<String, Integer> sameTagHistory = conn.getHistoryTable().getBehaviorHistory("sameTag", guid);
135 addWeight(sameTagHistory, Global.getSameTagWeight());
136 mergedHistory = mergeHistory(sameTagHistory, mergedHistory);
138 // sameNotebookNoteHistory<guid, 回数(ポイント)>
139 HashMap<String, Integer> sameNotebookHistory = conn.getHistoryTable().getBehaviorHistory("sameNotebook", guid);
140 addWeight(sameNotebookHistory, Global.getSameNotebookWeight());
141 mergedHistory = mergeHistory(sameNotebookHistory, mergedHistory);
143 // すべての関連ポイントの合計を取得(関連度のパーセント算出に利用)
145 for (int p : mergedHistory.values()) {
149 addRensoNoteList(mergedHistory);
151 logger.log(logger.HIGH, "Leaving RensoNoteList.refreshRensoNoteList");
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);
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>();
168 mergedHistory.putAll(History1);
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));
177 mergedHistory.put(key, History2.get(key));
181 return mergedHistory;
184 private void addRensoNoteList(HashMap<String, Integer> History){
185 String currentNoteGuid = new String(parent.getCurrentNoteGuid());
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);
194 staredNotes.put(nextGuid, relationPoint);
196 normalNotes.put(nextGuid, relationPoint);
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;
210 // 操作回数が多い順に取り出して連想ノートリストに追加する
211 if (!tmpMap.isEmpty()) {
213 String maxGuid = new String();
215 for (String nextGuid: tmpMap.keySet()) {
216 int relationPoint = tmpMap.get(nextGuid);
219 if (relationPoint > maxNum) {
220 maxNum = relationPoint;
225 // 次の最大値探索で邪魔なので最大値をHashMapから削除
226 tmpMap.remove(maxGuid);
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();
235 // 存在していて、かつ関連度0でなければノート情報を取得して連想ノートリストに追加
236 if (isNoteActive && maxNum > 0) {
239 isStared = conn.getStaredTable().existNote(currentNoteGuid, maxGuid);
241 QListWidgetItem item = new QListWidgetItem();
242 RensoNoteListItem myItem = new RensoNoteListItem(maxNote, maxNum, isStared, allPointSum, conn, this);
243 item.setSizeHint(new QSize(0, 90));
245 this.setItemWidget(item, myItem);
246 rensoNoteListItems.put(item, maxGuid);
247 rensoNoteListTrueItems.add(myItem);
255 // リストのアイテムから対象ノートのguidを取得
256 public String getNoteGuid(QListWidgetItem item) {
257 return rensoNoteListItems.get(item);
260 // 関連ノートリストの右クリックメニュー
262 public void contextMenuEvent(QContextMenuEvent event){
263 if (rensoNotePressedItemGuid == null || rensoNotePressedItemGuid.equals("")) {
267 // STAR, UNSTARがあれば、一度消す
268 List<QAction> menuActions = new ArrayList<QAction>(menu.actions());
269 if (menuActions.contains(starAction)) {
270 menu.removeAction(starAction);
272 if (menuActions.contains(unstarAction)) {
273 menu.removeAction(unstarAction);
276 // 対象アイテムがスター付きなら「UNSTAR」、スター無しなら「STAR」を追加
277 String currentNoteGuid = parent.getCurrentNoteGuid();
278 boolean isExist = conn.getStaredTable().existNote(currentNoteGuid, rensoNotePressedItemGuid);
280 menu.insertAction(excludeNoteAction, unstarAction);
282 menu.insertAction(excludeNoteAction, starAction);
286 menu.exec(event.globalPos());
288 rensoNotePressedItemGuid = null;
291 // コンテキストメニューが表示されているかどうか
292 public boolean isContextMenuVisible() {
293 return menu.isVisible();
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();
305 // ユーザが連想ノートリストのアイテムを選択した時の処理
306 @SuppressWarnings("unused")
307 private void rensoNoteItemPressed(QListWidgetItem current) {
308 rensoNotePressedItemGuid = null;
310 if (QApplication.mouseButtons().isSet(MouseButton.RightButton)) {
311 rensoNotePressedItemGuid = getNoteGuid(current);