xref: /haiku/src/preferences/bluetooth/BluetoothSettingsView.cpp (revision 945566ff43583e4f8102b4440c88f53dae775cb4)
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 	}
190 }
191 
192 
193 bool
194 BluetoothSettingsView::_SetDeviceClass(uint8 major, uint8 minor,
195 	uint16 service)
196 {
197 	bool haveRun = true;
198 
199 	fSettings.Data.LocalDeviceClass.SetRecord(major, minor, service);
200 
201 	if (ActiveLocalDevice != NULL)
202 		ActiveLocalDevice->SetDeviceClass(fSettings.Data.LocalDeviceClass);
203 	else
204 		haveRun = false;
205 
206 	return haveRun;
207 }
208 
209 
210 void
211 BluetoothSettingsView::_BuildConnectionPolicy()
212 {
213 	BMessage* message = NULL;
214 	BMenuItem* item = NULL;
215 
216 	fPolicyMenu = new BPopUpMenu(B_TRANSLATE("Policy..."));
217 
218 	message = new BMessage(kMsgSetConnectionPolicy);
219 	message->AddInt8("Policy", 1);
220 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kAllLabel), message);
221 	fPolicyMenu->AddItem(item);
222 
223 	message = new BMessage(kMsgSetConnectionPolicy);
224 	message->AddInt8("Policy", 2);
225 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kTrustedLabel), message);
226 	fPolicyMenu->AddItem(item);
227 
228 	message = new BMessage(kMsgSetConnectionPolicy);
229 	message->AddInt8("Policy", 3);
230 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kAlwaysLabel), NULL);
231 	fPolicyMenu->AddItem(item);
232 }
233 
234 void
235 BluetoothSettingsView::_BuildClassMenu()
236 {
237 	BMessage* message = NULL;
238 	BMenuItem* item = NULL;
239 
240 	fClassMenu = new BPopUpMenu(B_TRANSLATE("Identify us as..."));
241 
242 	message = new BMessage(kMsgSetDeviceClass);
243 	message->AddInt8("DeviceClass", 1);
244 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kDesktopLabel), message);
245 	fClassMenu->AddItem(item);
246 
247 	if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 &&
248 		fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 1)
249 			item->SetMarked(true);
250 
251 	message = new BMessage(kMsgSetDeviceClass);
252 	message->AddInt8("DeviceClass", 2);
253 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kServerLabel), message);
254 	fClassMenu->AddItem(item);
255 
256 	if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 &&
257 		fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 2)
258 			item->SetMarked(true);
259 
260 	message = new BMessage(kMsgSetDeviceClass);
261 	message->AddInt8("DeviceClass", 3);
262 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kLaptopLabel), message);
263 	fClassMenu->AddItem(item);
264 
265 	if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 &&
266 		fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 3)
267 			item->SetMarked(true);
268 
269 	message = new BMessage(kMsgSetDeviceClass);
270 	message->AddInt8("DeviceClass", 4);
271 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kHandheldLabel), message);
272 	fClassMenu->AddItem(item);
273 
274 	if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 1 &&
275 		fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 4)
276 			item->SetMarked(true);
277 
278 	message = new BMessage(kMsgSetDeviceClass);
279 	message->AddInt8("DeviceClass", 5);
280 	item = new BMenuItem(B_TRANSLATE_NOCOLLECT(kPhoneLabel), message);
281 	fClassMenu->AddItem(item);
282 
283 	if (fSettings.Data.LocalDeviceClass.MajorDeviceClass() == 2 &&
284 		fSettings.Data.LocalDeviceClass.MinorDeviceClass() == 3)
285 			item->SetMarked(true);
286 }
287 
288 
289 void
290 BluetoothSettingsView::_BuildLocalDevicesMenu()
291 {
292 	LocalDevice* lDevice;
293 
294 	if (!fLocalDevicesMenu)
295 		fLocalDevicesMenu = new BPopUpMenu(B_TRANSLATE("Pick device..."));
296 
297 	while (fLocalDevicesMenu->CountItems() > 0) {
298 		BMenuItem* item = fLocalDevicesMenu->RemoveItem((int32)0);
299 
300 		if (item != NULL) {
301 			delete item;
302 		}
303 	}
304 
305 	ActiveLocalDevice = NULL;
306 
307 	for (uint32 i = 0; i < LocalDevice::GetLocalDeviceCount(); i++) {
308 		lDevice = LocalDevice::GetLocalDevice();
309 
310 		if (lDevice != NULL) {
311 			BMessage* message = new BMessage(kMsgLocalSwitched);
312 			message->AddPointer("LocalDevice", lDevice);
313 
314 			BMenuItem* item = new BMenuItem(
315 				(lDevice->GetFriendlyName().String()), message);
316 
317 			if (bdaddrUtils::Compare(lDevice->GetBluetoothAddress(),
318 				fSettings.Data.PickedDevice)) {
319 
320 				item->SetMarked(true);
321 				ActiveLocalDevice = lDevice;
322 			}
323 
324 			fLocalDevicesMenu->AddItem(item);
325 		}
326 	}
327 }
328 
329 void
330 BluetoothSettingsView::_MarkLocalDevice(LocalDevice* lDevice)
331 {
332 	// TODO: Device integrity should be rechecked.
333 
334 	fExtDeviceView->SetLocalDevice(lDevice);
335 	fExtDeviceView->SetEnabled(true);
336 	ActiveLocalDevice = lDevice;
337 	fSettings.Data.PickedDevice = lDevice->GetBluetoothAddress();
338 }
339