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