xref: /haiku/src/preferences/notifications/NotificationsView.cpp (revision 5e7964b0a929555415798dea3373db9ac4611caa)
1 /*
2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
3  * Copyright 2009, Pier Luigi Fiorini.
4  * Distributed under the terms of the MIT License.
5  *
6  * Authors:
7  *		Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
8  */
9 
10 #include <Alert.h>
11 #include <Catalog.h>
12 #include <CheckBox.h>
13 #include <ColumnListView.h>
14 #include <ColumnTypes.h>
15 #include <Directory.h>
16 #include <FindDirectory.h>
17 #include <LayoutBuilder.h>
18 #include <Notification.h>
19 #include <Path.h>
20 #include <TextControl.h>
21 #include <Window.h>
22 
23 #include <notification/Notifications.h>
24 #include <notification/NotificationReceived.h>
25 
26 #include "NotificationsView.h"
27 
28 #undef B_TRANSLATION_CONTEXT
29 #define B_TRANSLATION_CONTEXT "NotificationView"
30 
31 const float kEdgePadding = 5.0;
32 const float kCLVTitlePadding = 8.0;
33 
34 const int32 kApplicationSelected = '_ASL';
35 const int32 kNotificationSelected = '_NSL';
36 
37 const int32 kCLVDeleteRow = 'av02';
38 
39 // Applications column indexes
40 const int32 kAppIndex = 0;
41 const int32 kAppEnabledIndex = 1;
42 
43 // Notifications column indexes
44 const int32 kTitleIndex = 0;
45 const int32 kDateIndex = 1;
46 const int32 kTypeIndex = 2;
47 const int32 kAllowIndex = 3;
48 
49 
50 NotificationsView::NotificationsView(SettingsHost* host)
51 	:
52 	SettingsPane("apps", host)
53 {
54 	BRect rect(0, 0, 100, 100);
55 
56 	// Search application field
57 	fSearch = new BTextControl(B_TRANSLATE("Search:"), NULL,
58 		new BMessage(kSettingChanged));
59 
60 	// Applications list
61 	fApplications = new BColumnListView(B_TRANSLATE("Applications"),
62 		0, B_FANCY_BORDER, true);
63 	fApplications->SetSelectionMode(B_SINGLE_SELECTION_LIST);
64 
65 	fAppCol = new BStringColumn(B_TRANSLATE("Application"), 200,
66 		be_plain_font->StringWidth(B_TRANSLATE("Application")) +
67 		(kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT);
68 	fApplications->AddColumn(fAppCol, kAppIndex);
69 
70 	fAppEnabledCol = new BStringColumn(B_TRANSLATE("Enabled"), 10,
71 		be_plain_font->StringWidth(B_TRANSLATE("Enabled")) +
72 		(kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT);
73 	fApplications->AddColumn(fAppEnabledCol, kAppEnabledIndex);
74 
75 	// Notifications list
76 	fNotifications = new BColumnListView(B_TRANSLATE("Notifications"),
77 		0, B_FANCY_BORDER, true);
78 	fNotifications->SetSelectionMode(B_SINGLE_SELECTION_LIST);
79 
80 	fTitleCol = new BStringColumn(B_TRANSLATE("Title"), 100,
81 		be_plain_font->StringWidth(B_TRANSLATE("Title")) +
82 		(kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT);
83 	fNotifications->AddColumn(fTitleCol, kTitleIndex);
84 
85 	fDateCol = new BDateColumn(B_TRANSLATE("Last received"), 100,
86 		be_plain_font->StringWidth(B_TRANSLATE("Last received")) +
87 		(kCLVTitlePadding * 2), rect.Width(), B_ALIGN_LEFT);
88 	fNotifications->AddColumn(fDateCol, kDateIndex);
89 
90 	fTypeCol = new BStringColumn(B_TRANSLATE("Type"), 100,
91 		be_plain_font->StringWidth(B_TRANSLATE("Type")) +
92 		(kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT);
93 	fNotifications->AddColumn(fTypeCol, kTypeIndex);
94 
95 	fAllowCol = new BStringColumn(B_TRANSLATE("Allowed"), 100,
96 		be_plain_font->StringWidth(B_TRANSLATE("Allowed")) +
97 		(kCLVTitlePadding * 2), rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT);
98 	fNotifications->AddColumn(fAllowCol, kAllowIndex);
99 
100 	// Add views
101 	BLayoutBuilder::Group<>(this, B_VERTICAL)
102 		.AddGroup(B_HORIZONTAL)
103 			.AddGlue()
104 			.Add(fSearch)
105 		.End()
106 		.Add(fApplications)
107 		.Add(fNotifications)
108 		.SetInsets(B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING,
109 			B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING);
110 }
111 
112 
113 void
114 NotificationsView::AttachedToWindow()
115 {
116 	fApplications->SetTarget(this);
117 	fApplications->SetInvocationMessage(new BMessage(kApplicationSelected));
118 
119 	fNotifications->SetTarget(this);
120 	fNotifications->SetInvocationMessage(new BMessage(kNotificationSelected));
121 
122 #if 0
123 	fNotifications->AddFilter(new BMessageFilter(B_ANY_DELIVERY,
124 		B_ANY_SOURCE, B_KEY_DOWN, CatchDelete));
125 #endif
126 }
127 
128 
129 void
130 NotificationsView::MessageReceived(BMessage* msg)
131 {
132 	switch (msg->what) {
133 		case kApplicationSelected:
134 		{
135 			BRow* row = fApplications->CurrentSelection();
136 			if (row == NULL)
137 				return;
138 			BStringField* appName
139 				= dynamic_cast<BStringField*>(row->GetField(kAppIndex));
140 			if (appName == NULL)
141 				break;
142 
143 			appusage_t::iterator it = fAppFilters.find(appName->String());
144 			if (it != fAppFilters.end())
145 				_Populate(it->second);
146 
147 			break;
148 		}
149 		case kNotificationSelected:
150 			break;
151 		default:
152 			BView::MessageReceived(msg);
153 			break;
154 	}
155 }
156 
157 
158 status_t
159 NotificationsView::Load(BMessage& settings)
160 {
161 	type_code type;
162 	int32 count = 0;
163 
164 	if (settings.GetInfo("app_usage", &type, &count) != B_OK)
165 		return B_ERROR;
166 
167 	// Clean filters
168 	appusage_t::iterator auIt;
169 	for (auIt = fAppFilters.begin(); auIt != fAppFilters.end(); auIt++)
170 		delete auIt->second;
171 	fAppFilters.clear();
172 
173 	// Add new filters
174 	for (int32 i = 0; i < count; i++) {
175 		AppUsage* app = new AppUsage();
176 		settings.FindFlat("app_usage", i, app);
177 		fAppFilters[app->Name()] = app;
178 	}
179 
180 	// Load the applications list
181 	_PopulateApplications();
182 
183 	return B_OK;
184 }
185 
186 
187 status_t
188 NotificationsView::Save(BMessage& storage)
189 {
190 	appusage_t::iterator fIt;
191 	for (fIt = fAppFilters.begin(); fIt != fAppFilters.end(); fIt++)
192 		storage.AddFlat("app_usage", fIt->second);
193 
194 	return B_OK;
195 }
196 
197 
198 void
199 NotificationsView::_PopulateApplications()
200 {
201 	appusage_t::iterator it;
202 
203 	fApplications->Clear();
204 
205 	for (it = fAppFilters.begin(); it != fAppFilters.end(); ++it) {
206 		BRow* row = new BRow();
207 		row->SetField(new BStringField(it->first.String()), kAppIndex);
208 		fApplications->AddRow(row);
209 	}
210 }
211 
212 
213 void
214 NotificationsView::_Populate(AppUsage* usage)
215 {
216 	// Sanity check
217 	if (!usage)
218 		return;
219 
220 	int32 size = usage->Notifications();
221 
222 	if (usage->Allowed() == false)
223 		fBlockAll->SetValue(B_CONTROL_ON);
224 
225 	fNotifications->Clear();
226 
227 	for (int32 i = 0; i < size; i++) {
228 		NotificationReceived* notification = usage->NotificationAt(i);
229 		time_t updated = notification->LastReceived();
230 		const char* allow = notification->Allowed() ? B_TRANSLATE("Yes")
231 			: B_TRANSLATE("No");
232 		const char* type = "";
233 
234 		switch (notification->Type()) {
235 			case B_INFORMATION_NOTIFICATION:
236 				type = B_TRANSLATE("Information");
237 				break;
238 			case B_IMPORTANT_NOTIFICATION:
239 				type = B_TRANSLATE("Important");
240 				break;
241 			case B_ERROR_NOTIFICATION:
242 				type = B_TRANSLATE("Error");
243 				break;
244 			case B_PROGRESS_NOTIFICATION:
245 				type = B_TRANSLATE("Progress");
246 				break;
247 			default:
248 				type = B_TRANSLATE("Unknown");
249 		}
250 
251 		BRow* row = new BRow();
252 		row->SetField(new BStringField(notification->Title()), kTitleIndex);
253 		row->SetField(new BDateField(&updated), kDateIndex);
254 		row->SetField(new BStringField(type), kTypeIndex);
255 		row->SetField(new BStringField(allow), kAllowIndex);
256 
257 		fNotifications->AddRow(row);
258 	}
259 }
260