1 /*
2   KeePass Password Safe - The Open-Source Password Manager
3   Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de>
4 
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9 
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14 
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19 
20 using System;
21 using System.Collections.Generic;
22 using System.Text;
23 using System.Windows.Forms;
24 using System.Diagnostics;
25 
26 using KeePass.App.Configuration;
27 using KeePass.Forms;
28 using KeePass.Resources;
29 using KeePass.Util;
30 
31 using KeePassLib;
32 using KeePassLib.Collections;
33 
34 namespace KeePass.UI
35 {
36 	public sealed class ListViewGroupingMenu
37 	{
38 		private ToolStripMenuItem m_tsmiMenu;
39 		private MainForm m_mf;
40 
41 		private Dictionary<AceListGrouping, ToolStripMenuItem> m_dItems =
42 			new Dictionary<AceListGrouping, ToolStripMenuItem>();
43 
ListViewGroupingMenu(ToolStripMenuItem tsmiContainer, MainForm mf)44 		public ListViewGroupingMenu(ToolStripMenuItem tsmiContainer, MainForm mf)
45 		{
46 			if(tsmiContainer == null) throw new ArgumentNullException("tsmiContainer");
47 			if(mf == null) throw new ArgumentNullException("mf");
48 
49 			m_tsmiMenu = tsmiContainer;
50 			m_mf = mf;
51 
52 			ToolStripMenuItem tsmi = new ToolStripMenuItem(KPRes.On);
53 			tsmi.Click += this.OnGroupOn;
54 			m_dItems[AceListGrouping.On] = tsmi;
55 			m_tsmiMenu.DropDownItems.Add(tsmi);
56 
57 			tsmi = new ToolStripMenuItem(KPRes.Auto + " (" + KPRes.RecommendedCmd + ")");
58 			tsmi.Click += this.OnGroupAuto;
59 			m_dItems[AceListGrouping.Auto] = tsmi;
60 			m_tsmiMenu.DropDownItems.Add(tsmi);
61 
62 			tsmi = new ToolStripMenuItem(KPRes.Off);
63 			tsmi.Click += this.OnGroupOff;
64 			m_dItems[AceListGrouping.Off] = tsmi;
65 			m_tsmiMenu.DropDownItems.Add(tsmi);
66 
67 			UpdateUI();
68 		}
69 
70 #if DEBUG
~ListViewGroupingMenu()71 		~ListViewGroupingMenu()
72 		{
73 			Debug.Assert(m_tsmiMenu == null); // Release should have been called
74 		}
75 #endif
76 
Release()77 		public void Release()
78 		{
79 			if(m_tsmiMenu != null)
80 			{
81 				m_dItems[AceListGrouping.On].Click -= this.OnGroupOn;
82 				m_dItems[AceListGrouping.Auto].Click -= this.OnGroupAuto;
83 				m_dItems[AceListGrouping.Off].Click -= this.OnGroupOff;
84 
85 				m_dItems.Clear();
86 				m_tsmiMenu.DropDownItems.Clear();
87 
88 				m_tsmiMenu = null;
89 				m_mf = null;
90 			}
91 		}
92 
UpdateUI()93 		private void UpdateUI()
94 		{
95 			int lgp = (Program.Config.MainWindow.ListGrouping & (int)AceListGrouping.Primary);
96 			foreach(KeyValuePair<AceListGrouping, ToolStripMenuItem> kvp in m_dItems)
97 			{
98 				Debug.Assert(((int)kvp.Key & ~(int)AceListGrouping.Primary) == 0);
99 				UIUtil.SetRadioChecked(kvp.Value, ((int)kvp.Key == lgp));
100 			}
101 		}
102 
SetGrouping(AceListGrouping lgPrimary)103 		private void SetGrouping(AceListGrouping lgPrimary)
104 		{
105 			Debug.Assert(((int)lgPrimary & ~(int)AceListGrouping.Primary) == 0);
106 			if((int)lgPrimary == (Program.Config.MainWindow.ListGrouping &
107 				(int)AceListGrouping.Primary))
108 				return;
109 
110 			Program.Config.MainWindow.ListGrouping &= ~(int)AceListGrouping.Primary;
111 			Program.Config.MainWindow.ListGrouping |= (int)lgPrimary;
112 			Debug.Assert((Program.Config.MainWindow.ListGrouping &
113 				(int)AceListGrouping.Primary) == (int)lgPrimary);
114 			UpdateUI();
115 
116 			if(m_mf == null) { Debug.Assert(false); return; }
117 
118 			PwDatabase pd = m_mf.ActiveDatabase;
119 			PwGroup pg = m_mf.GetCurrentEntries();
120 			if((pd == null) || !pd.IsOpen || (pg == null)) return; // No assert
121 
122 			PwObjectList<PwEntry> pwl = pg.GetEntries(true);
123 			if((pwl.UCount > 0) && EntryUtil.EntriesHaveSameParent(pwl))
124 				m_mf.UpdateUI(false, null, true, pwl.GetAt(0).ParentGroup,
125 					true, null, false);
126 			else
127 			{
128 				EntryUtil.ReorderEntriesAsInDatabase(pwl, pd); // Requires open DB
129 
130 				pg = new PwGroup(true, true);
131 				pg.IsVirtual = true;
132 				foreach(PwEntry pe in pwl) pg.AddEntry(pe, false);
133 
134 				m_mf.UpdateUI(false, null, false, null, true, pg, false);
135 			}
136 		}
137 
OnGroupOn(object sender, EventArgs e)138 		private void OnGroupOn(object sender, EventArgs e)
139 		{
140 			SetGrouping(AceListGrouping.On);
141 		}
142 
OnGroupAuto(object sender, EventArgs e)143 		private void OnGroupAuto(object sender, EventArgs e)
144 		{
145 			SetGrouping(AceListGrouping.Auto);
146 		}
147 
OnGroupOff(object sender, EventArgs e)148 		private void OnGroupOff(object sender, EventArgs e)
149 		{
150 			SetGrouping(AceListGrouping.Off);
151 		}
152 	}
153 }
154