xref: /haiku/src/preferences/bluetooth/BluetoothSettingsView.cpp (revision c085f3863924bb32c6b250e1b9697a39688effef)
1 /*
2  * Copyright 2008-2009, Oliver Ruiz Dorantes <oliver.ruiz.dorantes@gmail.com>
3  * Copyright 2012-2013, Tri-Edge AI, <triedgeai@gmail.com>
4  *
5  * All rights reserved. Distributed under the terms of the MIT License.
6  */
7 
8 #include "BluetoothSettingsView.h"
9 
10 #include "defs.h"
11 #include "BluetoothSettings.h"
12 #include "BluetoothWindow.h"
13 #include "ExtendedLocalDeviceView.h"
14 
15 #include <bluetooth/LocalDevice.h>
16 
17 #include <Box.h>
18 #include <Catalog.h>
19 #include <LayoutBuilder.h>
20 #include <MenuField.h>
21 #include <MenuItem.h>
22 #include <PopUpMenu.h>
23 #include <Slider.h>
24 #include <SpaceLayoutItem.h>
25 #include <String.h>
26 #include <TextView.h>
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 
31 #undef B_TRANSLATION_CONTEXT
32 #define B_TRANSLATION_CONTEXT "Settings view"
33 
34 static const int32 kMsgSetConnectionPolicy = 'sCpo';
35 static const int32 kMsgSetDeviceClass = 'sDC0';
36 static const int32 kMsgSetInquiryTime = 'afEa';
37 static const int32 kMsgLocalSwitched = 'lDsW';
38 
39 static const char* kAllLabel = B_TRANSLATE_MARK("From all devices");
40 static const char* kTrustedLabel =
41 	B_TRANSLATE_MARK("Only from trusted devices");
42 static const char* kAlwaysLabel = B_TRANSLATE_MARK("Always ask");
43 
44 static const char* kDesktopLabel = B_TRANSLATE_MARK("Desktop");
45 static const char* kServerLabel = B_TRANSLATE_MARK("Server");
46 static const char* kLaptopLabel = B_TRANSLATE_MARK("Laptop");
47 static const char* kHandheldLabel = B_TRANSLATE_MARK("Handheld");
48 static const char* kPhoneLabel = B_TRANSLATE_MARK("Smart phone");
49 
50 //	#pragma mark -
51 
52 BluetoothSettingsView::BluetoothSettingsView(const char* name)
53 	:
54 	BView(name, 0),
55 	fLocalDevicesMenu(NULL)
56 {
57 	fSettings.Load();
58 
59 	_BuildConnectionPolicy();
60 	fPolicyMenuField = new BMenuField("policy",
61 		B_TRANSLATE("Incoming connections policy:"), fPolicyMenu);
62 
63 	fInquiryTimeControl = new BSlider("time",
64 		B_TRANSLATE("Default inquiry time:"), new BMessage(kMsgSetInquiryTime),
65 		0, 255, B_HORIZONTAL);
66 	fInquiryTimeControl->SetLimitLabels(B_TRANSLATE("15 secs"),
67 		B_TRANSLATE("61 secs"));
68 	fInquiryTimeControl->SetHashMarks(B_HASH_MARKS_BOTTOM);
69 	fInquiryTimeControl->SetHashMarkCount(255 / 15);
70 	fInquiryTimeControl->SetEnabled(true);
71 
72 	fExtDeviceView = new ExtendedLocalDeviceView(NULL);
73 
74 	// localdevices menu
75 	_BuildLocalDevicesMenu();
76 	fLocalDevicesMenuField = new BMenuField("devices",
77 		B_TRANSLATE("Local devices found on system:"),
78 		fLocalDevicesMenu);
79 
80 	if (ActiveLocalDevice != NULL) {
81 		fExtDeviceView->SetLocalDevice(ActiveLocalDevice);
82 		fExtDeviceView->SetEnabled(true);
83 
84 		DeviceClass rememberedClass = ActiveLocalDevice->GetDeviceClass();
85 
86 		if (!rememberedClass.IsUnknownDeviceClass())
87 			fSettings.Data.LocalDeviceClass = rememberedClass;
88 	}
89 
90 	// hinting menu
91 	_BuildClassMenu();
92 	fClassMenuField = new BMenuField("class", B_TRANSLATE("Identify host as:"),
93 		fClassMenu);
94 
95 	BLayoutBuilder::Grid<>(this, 0)
96 		.SetInsets(10)
97 		.Add(fClassMenuField->CreateLabelLayoutItem(), 0, 0)
98 		.Add(fClassMenuField->CreateMenuBarLayoutItem(), 1, 0)
99 
100 		.Add(fPolicyMenuField->CreateLabelLayoutItem(), 0, 1)
101 		.Add(fPolicyMenuField->CreateMenuBarLayoutItem(), 1, 1)
102 
103 		.Add(fInquiryTimeControl, 0, 2, 2)
104 
105 		.Add(fLocalDevicesMenuField->CreateLabelLayoutItem(), 0, 5)
106 		.Add(fLocalDevicesMenuField->CreateMenuBarLayoutItem(), 1, 5)
107 
108 		.Add(fExtDeviceView, 0, 6, 2)
109 	.End();
110 }
111 
112 
113 BluetoothSettingsView::~BluetoothSettingsView()
114 {
115 	fSettings.Save();
116 }
117 
118 
119 void
120 BluetoothSettingsView::AttachedToWindow()
121 {
122 	if (Parent() != NULL)
123 		SetViewColor(Parent()->ViewColor());
124 	else
125 		SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
126 
127 	fPolicyMenu->SetTargetForItems(this);
128 	fClassMenu->SetTargetForItems(this);
129 	fLocalDevicesMenu->SetTargetForItems(this);
130 	fInquiryTimeControl->SetTarget(this);
131 }
132 
133 
134 void
135 BluetoothSettingsView::MessageReceived(BMessage* message)
136 {
137 	switch (message->what) {
138 		case kMsgLocalSwitched:
139 		{
140 			LocalDevice* lDevice;
141 
142 			if (message->FindPointer("LocalDevice",
143 				(void**)&lDevice) == B_OK) {
144 
145 				_MarkLocalDevice(lDevice);
146 			}
147 
148 			break;
149 		}
150 		// TODO: To be fixed. :)
151 
152 		/*
153 		case kMsgSetConnectionPolicy:
154 		{
155 			//uint8 Policy;
156 			//if (message->FindInt8("Policy", (int8*)&Policy) == B_OK)
157 			break;
158 		}
159 
160 		case kMsgSetInquiryTime:
161 		{
162 			break;
163 		}
164 		*/
165 		case kMsgSetDeviceClass:
166 		{
167 			uint8 deviceClass;
168 
169 			if (message->FindInt8("DeviceClass",
170 				(int8*)&deviceClass) == B_OK) {
171 
172 				if (deviceClass == 5)
173 					_SetDeviceClass(2, 3, 0x72);
174 				else
175 					_SetDeviceClass(1, deviceClass, 0x72);
176 			}
177 
178 			break;
179 		}
180 		case kMsgRefresh:
181 		{
182 			_BuildLocalDevicesMenu();
183 			fLocalDevicesMenu->SetTargetForItems(this);
184 
185 			break;
186 		}
187 		default:
188 			BView::MessageReceived(message);
189 			break;
190 	}
191 }
192 
193 
194 bool
195 BluetoothSettingsView::_SetDeviceClass(uint8 major, uint8 minor,
196 	uint16 service)
197 {
198 	bool haveRun = true;
199 
200 	fSettings.Data.LocalDeviceClass.SetRecord(major, minor, service);
201 
202 	if (ActiveLocalDevice != NULL)
203 		ActiveLocalDevice->SetDeviceClass(fSettings.Data.LocalDeviceClass);
204 	else
205 		haveRun = false;
206 
207 	return haveRun;
208 }
209 
210 
211 void
212 BluetoothSettingsView::_BuildConnectionPolicy()
213 {
214 	BMessage* message = NULL;
215 	BMenuItem* item = NULL;
216 
217 	fPolicyMenu = new BPopUpMenu(B_TRANSLATE("Policy" B_UTF8_ELLIPSIS));
218 
219 	message = new BMessage(kMsgSetConnectionPolicy);
220 	message->AddInt8("Policy", 1);
221 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kAllLabel), message);
222 	fPolicyMenu->AddItem(item);
223 
224 	message = new BMessage(kMsgSetConnectionPolicy);
225 	message->AddInt8("Policy", 2);
226 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kTrustedLabel), message);
227 	fPolicyMenu->AddItem(item);
228 
229 	message = new BMessage(kMsgSetConnectionPolicy);
230 	message->AddInt8("Policy", 3);
231 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kAlwaysLabel), NULL);
232 	fPolicyMenu->AddItem(item);
233 }
234 
235 void
236 BluetoothSettingsView::_BuildClassMenu()
237 {
238 	BMessage* message = NULL;
239 	BMenuItem* item = NULL;
240 
241 	fClassMenu = new BPopUpMenu(B_TRANSLATE("Identify us as" B_UTF8_ELLIPSIS));
242 
243 	message = new BMessage(kMsgSetDeviceClass);
244 	message->AddInt8("DeviceClass", 1);
245 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kDesktopLabel), message);
246 	fClassMenu->AddItem(item);
247 
248 	if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 &&
249 		fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 1)
250 			item->SetMarked(true);
251 
252 	message = new BMessage(kMsgSetDeviceClass);
253 	message->AddInt8("DeviceClass", 2);
254 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kServerLabel), message);
255 	fClassMenu->AddItem(item);
256 
257 	if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 &&
258 		fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 2)
259 			item->SetMarked(true);
260 
261 	message = new BMessage(kMsgSetDeviceClass);
262 	message->AddInt8("DeviceClass", 3);
263 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kLaptopLabel), message);
264 	fClassMenu->AddItem(item);
265 
266 	if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 &&
267 		fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 3)
268 			item->SetMarked(true);
269 
270 	message = new BMessage(kMsgSetDeviceClass);
271 	message->AddInt8("DeviceClass", 4);
272 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kHandheldLabel), message);
273 	fClassMenu->AddItem(item);
274 
275 	if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 &&
276 		fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 4)
277 			item->SetMarked(true);
278 
279 	message = new BMessage(kMsgSetDeviceClass);
280 	message->AddInt8("DeviceClass", 5);
281 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kPhoneLabel), message);
282 	fClassMenu->AddItem(item);
283 
284 	if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 2 &&
285 		fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 3)
286 			item->SetMarked(true);
287 }
288 
289 
290 void
291 BluetoothSettingsView::_BuildLocalDevicesMenu()
292 {
293 	LocalDevice* lDevice;
294 
295 	if (!fLocalDevicesMenu)
296 		fLocalDevicesMenu = new BPopUpMenu(B_TRANSLATE("Pick device"
297 			B_UTF8_ELLIPSIS));
298 
299 	while (fLocalDevicesMenu->CountItems() > 0) {
300 		BMenuItem* item = fLocalDevicesMenu->RemoveItem((int32)0);
301 
302 		if (item != NULL) {
303 			delete item;
304 		}
305 	}
306 
307 	ActiveLocalDevice = NULL;
308 
309 	for (uint32 i = 0; i < LocalDevice::GetLocalDeviceCount(); i++) {
310 		lDevice = LocalDevice::GetLocalDevice();
311 
312 		if (lDevice != NULL) {
313 			BMessage* message = new BMessage(kMsgLocalSwitched);
314 			message->AddPointer("LocalDevice", lDevice);
315 
316 			BMenuItem* item = new BMenuItem(
317 				(lDevice->GetFriendlyName().String()), message);
318 
319 			if (bdaddrUtils::Compare(lDevice->GetBluetoothAddress(),
320 				fSettings.Data.PickedDevice)) {
321 
322 				item->SetMarked(true);
323 				ActiveLocalDevice = lDevice;
324 			}
325 
326 			fLocalDevicesMenu->AddItem(item);
327 		}
328 	}
329 }
330 
331 void
332 BluetoothSettingsView::_MarkLocalDevice(LocalDevice* lDevice)
333 {
334 	// TODO: Device integrity should be rechecked.
335 
336 	fExtDeviceView->SetLocalDevice(lDevice);
337 	fExtDeviceView->SetEnabled(true);
338 	ActiveLocalDevice = lDevice;
339 	fSettings.Data.PickedDevice = lDevice->GetBluetoothAddress();
340 }
341