xref: /haiku/src/apps/networkstatus/NetworkStatusView.cpp (revision 3aeed6607cd07762c0e709633c012b3a632dbad9)
1f01106c3SAxel Dörfler /*
26c7caf44SAxel Dörfler  * Copyright 2006-2013, Haiku, Inc. All rights reserved.
3f01106c3SAxel Dörfler  * Distributed under the terms of the MIT License.
4f01106c3SAxel Dörfler  *
5f01106c3SAxel Dörfler  * Authors:
63b41ad86SStephan Aßmus  *		Dario Casalinuovo
7937ca113SRene Gollent  *		Axel Dörfler, axeld@pinc-software.de
85c46b171SRene Gollent  *		Rene Gollent, rene@gollent.com
9937ca113SRene Gollent  *		Hugo Santos, hugosantos@gmail.com
10f01106c3SAxel Dörfler  */
11f01106c3SAxel Dörfler 
12f01106c3SAxel Dörfler 
13f01106c3SAxel Dörfler #include "NetworkStatusView.h"
14f01106c3SAxel Dörfler 
15440d0e61SAxel Dörfler #include <set>
16440d0e61SAxel Dörfler 
17195981bbSAxel Dörfler #include <arpa/inet.h>
18195981bbSAxel Dörfler #include <net/if.h>
19195981bbSAxel Dörfler #include <stdio.h>
20195981bbSAxel Dörfler #include <stdlib.h>
21*3aeed660SJérôme Duval #include <strings.h>
22195981bbSAxel Dörfler #include <sys/socket.h>
23195981bbSAxel Dörfler #include <sys/sockio.h>
24195981bbSAxel Dörfler #include <unistd.h>
25f01106c3SAxel Dörfler 
26730a45eeSJohn Scipione #include <AboutWindow.h>
27f01106c3SAxel Dörfler #include <Alert.h>
28f01106c3SAxel Dörfler #include <Application.h>
29757e7059SAdrien Destugues #include <Catalog.h>
30f01106c3SAxel Dörfler #include <Bitmap.h>
31f01106c3SAxel Dörfler #include <Deskbar.h>
32f01106c3SAxel Dörfler #include <Dragger.h>
33f01106c3SAxel Dörfler #include <Drivers.h>
34f01106c3SAxel Dörfler #include <IconUtils.h>
35757e7059SAdrien Destugues #include <Locale.h>
36f01106c3SAxel Dörfler #include <MenuItem.h>
37f01106c3SAxel Dörfler #include <MessageRunner.h>
385fe97f21SAxel Dörfler #include <NetworkDevice.h>
395fe97f21SAxel Dörfler #include <NetworkInterface.h>
405fe97f21SAxel Dörfler #include <NetworkRoster.h>
41f01106c3SAxel Dörfler #include <PopUpMenu.h>
42f01106c3SAxel Dörfler #include <Resources.h>
43d5ba07a3SAxel Dörfler #include <Roster.h>
44f01106c3SAxel Dörfler #include <String.h>
45f01106c3SAxel Dörfler #include <TextView.h>
46f01106c3SAxel Dörfler 
47195981bbSAxel Dörfler #include "NetworkStatus.h"
48195981bbSAxel Dörfler #include "NetworkStatusIcons.h"
495fe97f21SAxel Dörfler #include "RadioView.h"
503ca00ffdSAxel Dörfler #include "WirelessNetworkMenuItem.h"
51195981bbSAxel Dörfler 
52f01106c3SAxel Dörfler 
53546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
54546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "NetworkStatusView"
55757e7059SAdrien Destugues 
56757e7059SAdrien Destugues 
57f01106c3SAxel Dörfler static const char *kStatusDescriptions[] = {
582ee8f3f6SSiarzhuk Zharski 	B_TRANSLATE("Unknown"),
592ee8f3f6SSiarzhuk Zharski 	B_TRANSLATE("No link"),
602ee8f3f6SSiarzhuk Zharski 	B_TRANSLATE("No stateful configuration"),
612ee8f3f6SSiarzhuk Zharski 	B_TRANSLATE("Configuring"),
622ee8f3f6SSiarzhuk Zharski 	B_TRANSLATE("Ready")
63f01106c3SAxel Dörfler };
64f01106c3SAxel Dörfler 
65f01106c3SAxel Dörfler extern "C" _EXPORT BView *instantiate_deskbar_item(void);
66f01106c3SAxel Dörfler 
67f01106c3SAxel Dörfler 
68f01106c3SAxel Dörfler const uint32 kMsgShowConfiguration = 'shcf';
69c1502c9aSStephan Aßmus const uint32 kMsgOpenNetworkPreferences = 'onwp';
702e1a6286SAxel Dörfler const uint32 kMsgJoinNetwork = 'join';
71f01106c3SAxel Dörfler 
72f01106c3SAxel Dörfler const uint32 kMinIconWidth = 16;
73f01106c3SAxel Dörfler const uint32 kMinIconHeight = 16;
74f01106c3SAxel Dörfler 
75195981bbSAxel Dörfler 
76195981bbSAxel Dörfler //	#pragma mark -
77f01106c3SAxel Dörfler 
78f01106c3SAxel Dörfler 
79f01106c3SAxel Dörfler NetworkStatusView::NetworkStatusView(BRect frame, int32 resizingMode,
80f01106c3SAxel Dörfler 		bool inDeskbar)
81f01106c3SAxel Dörfler 	: BView(frame, kDeskbarItemName, resizingMode,
82d5ba07a3SAxel Dörfler 		B_WILL_DRAW | B_FRAME_EVENTS),
835c46b171SRene Gollent 	fInDeskbar(inDeskbar)
84f01106c3SAxel Dörfler {
85f01106c3SAxel Dörfler 	_Init();
86f01106c3SAxel Dörfler 
87f01106c3SAxel Dörfler 	if (!inDeskbar) {
88f01106c3SAxel Dörfler 		// we were obviously added to a standard window - let's add a dragger
89f01106c3SAxel Dörfler 		frame.OffsetTo(B_ORIGIN);
90f01106c3SAxel Dörfler 		frame.top = frame.bottom - 7;
91f01106c3SAxel Dörfler 		frame.left = frame.right - 7;
92f01106c3SAxel Dörfler 		BDragger* dragger = new BDragger(frame, this,
93f01106c3SAxel Dörfler 			B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
94f01106c3SAxel Dörfler 		AddChild(dragger);
95f01106c3SAxel Dörfler 	} else
96f01106c3SAxel Dörfler 		_Update();
97f01106c3SAxel Dörfler }
98f01106c3SAxel Dörfler 
99f01106c3SAxel Dörfler 
100f01106c3SAxel Dörfler NetworkStatusView::NetworkStatusView(BMessage* archive)
101d5ba07a3SAxel Dörfler 	: BView(archive),
102d5ba07a3SAxel Dörfler 	fInDeskbar(false)
103f01106c3SAxel Dörfler {
104d5ba07a3SAxel Dörfler 	app_info info;
105d5ba07a3SAxel Dörfler 	if (be_app->GetAppInfo(&info) == B_OK
106d5ba07a3SAxel Dörfler 		&& !strcasecmp(info.signature, "application/x-vnd.Be-TSKB"))
107d5ba07a3SAxel Dörfler 		fInDeskbar = true;
108d5ba07a3SAxel Dörfler 
109f01106c3SAxel Dörfler 	_Init();
110f01106c3SAxel Dörfler }
111f01106c3SAxel Dörfler 
112f01106c3SAxel Dörfler 
113f01106c3SAxel Dörfler NetworkStatusView::~NetworkStatusView()
114f01106c3SAxel Dörfler {
115f01106c3SAxel Dörfler }
116f01106c3SAxel Dörfler 
117f01106c3SAxel Dörfler 
118f01106c3SAxel Dörfler void
119f01106c3SAxel Dörfler NetworkStatusView::_Init()
120f01106c3SAxel Dörfler {
121f01106c3SAxel Dörfler 	for (int i = 0; i < kStatusCount; i++) {
122e58807edSAlexander von Gluck IV 		fTrayIcons[i] = NULL;
123e58807edSAlexander von Gluck IV 		fNotifyIcons[i] = NULL;
124f01106c3SAxel Dörfler 	}
125f01106c3SAxel Dörfler 
126f01106c3SAxel Dörfler 	_UpdateBitmaps();
127f01106c3SAxel Dörfler }
128f01106c3SAxel Dörfler 
129f01106c3SAxel Dörfler 
130f01106c3SAxel Dörfler void
131f01106c3SAxel Dörfler NetworkStatusView::_UpdateBitmaps()
132f01106c3SAxel Dörfler {
133f01106c3SAxel Dörfler 	for (int i = 0; i < kStatusCount; i++) {
134e58807edSAlexander von Gluck IV 		delete fTrayIcons[i];
135e58807edSAlexander von Gluck IV 		delete fNotifyIcons[i];
136e58807edSAlexander von Gluck IV 		fTrayIcons[i] = NULL;
137e58807edSAlexander von Gluck IV 		fNotifyIcons[i] = NULL;
138f01106c3SAxel Dörfler 	}
139f01106c3SAxel Dörfler 
140f01106c3SAxel Dörfler 	image_info info;
141f01106c3SAxel Dörfler 	if (our_image(info) != B_OK)
142f01106c3SAxel Dörfler 		return;
143f01106c3SAxel Dörfler 
144f01106c3SAxel Dörfler 	BFile file(info.name, B_READ_ONLY);
145f01106c3SAxel Dörfler 	if (file.InitCheck() < B_OK)
146f01106c3SAxel Dörfler 		return;
147f01106c3SAxel Dörfler 
148f01106c3SAxel Dörfler 	BResources resources(&file);
149f01106c3SAxel Dörfler #ifdef HAIKU_TARGET_PLATFORM_HAIKU
150f01106c3SAxel Dörfler 	if (resources.InitCheck() < B_OK)
151f01106c3SAxel Dörfler 		return;
152f01106c3SAxel Dörfler #endif
153f01106c3SAxel Dörfler 
154f01106c3SAxel Dörfler 	for (int i = 0; i < kStatusCount; i++) {
155f01106c3SAxel Dörfler 		const void* data = NULL;
156f01106c3SAxel Dörfler 		size_t size;
157f01106c3SAxel Dörfler 		data = resources.LoadResource(B_VECTOR_ICON_TYPE,
158f01106c3SAxel Dörfler 			kNetworkStatusNoDevice + i, &size);
159f01106c3SAxel Dörfler 		if (data != NULL) {
160e58807edSAlexander von Gluck IV 			// Scale main tray icon
161e58807edSAlexander von Gluck IV 			BBitmap* trayIcon = new BBitmap(Bounds(), B_RGBA32);
162e58807edSAlexander von Gluck IV 			if (trayIcon->InitCheck() == B_OK
163f01106c3SAxel Dörfler 				&& BIconUtils::GetVectorIcon((const uint8 *)data,
164e58807edSAlexander von Gluck IV 					size, trayIcon) == B_OK) {
165e58807edSAlexander von Gluck IV 				fTrayIcons[i] = trayIcon;
166f01106c3SAxel Dörfler 			} else
167e58807edSAlexander von Gluck IV 				delete trayIcon;
168e58807edSAlexander von Gluck IV 
169e58807edSAlexander von Gluck IV 			// Scale notification icon
170e58807edSAlexander von Gluck IV 			BBitmap* notifyIcon = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32);
171e58807edSAlexander von Gluck IV 			if (notifyIcon->InitCheck() == B_OK
172e58807edSAlexander von Gluck IV 				&& BIconUtils::GetVectorIcon((const uint8 *)data,
173e58807edSAlexander von Gluck IV 					size, notifyIcon) == B_OK) {
174e58807edSAlexander von Gluck IV 				fNotifyIcons[i] = notifyIcon;
175e58807edSAlexander von Gluck IV 			} else
176e58807edSAlexander von Gluck IV 				delete notifyIcon;
177f01106c3SAxel Dörfler 		}
178f01106c3SAxel Dörfler 	}
179f01106c3SAxel Dörfler }
180f01106c3SAxel Dörfler 
181f01106c3SAxel Dörfler 
182f01106c3SAxel Dörfler void
183f01106c3SAxel Dörfler NetworkStatusView::_Quit()
184f01106c3SAxel Dörfler {
185f01106c3SAxel Dörfler 	if (fInDeskbar) {
186f01106c3SAxel Dörfler 		BDeskbar deskbar;
187f01106c3SAxel Dörfler 		deskbar.RemoveItem(kDeskbarItemName);
188f01106c3SAxel Dörfler 	} else
189f01106c3SAxel Dörfler 		be_app->PostMessage(B_QUIT_REQUESTED);
190f01106c3SAxel Dörfler }
191f01106c3SAxel Dörfler 
192f01106c3SAxel Dörfler 
193f01106c3SAxel Dörfler NetworkStatusView*
194f01106c3SAxel Dörfler NetworkStatusView::Instantiate(BMessage* archive)
195f01106c3SAxel Dörfler {
196f01106c3SAxel Dörfler 	if (!validate_instantiation(archive, "NetworkStatusView"))
197f01106c3SAxel Dörfler 		return NULL;
198f01106c3SAxel Dörfler 
199f01106c3SAxel Dörfler 	return new NetworkStatusView(archive);
200f01106c3SAxel Dörfler }
201f01106c3SAxel Dörfler 
202f01106c3SAxel Dörfler 
203f01106c3SAxel Dörfler status_t
204f01106c3SAxel Dörfler NetworkStatusView::Archive(BMessage* archive, bool deep) const
205f01106c3SAxel Dörfler {
206f01106c3SAxel Dörfler 	status_t status = BView::Archive(archive, deep);
207f01106c3SAxel Dörfler 	if (status == B_OK)
208f01106c3SAxel Dörfler 		status = archive->AddString("add_on", kSignature);
209f01106c3SAxel Dörfler 	if (status == B_OK)
210f01106c3SAxel Dörfler 		status = archive->AddString("class", "NetworkStatusView");
211f01106c3SAxel Dörfler 
212f01106c3SAxel Dörfler 	return status;
213f01106c3SAxel Dörfler }
214f01106c3SAxel Dörfler 
215f01106c3SAxel Dörfler 
216f01106c3SAxel Dörfler void
217f01106c3SAxel Dörfler NetworkStatusView::AttachedToWindow()
218f01106c3SAxel Dörfler {
219f01106c3SAxel Dörfler 	BView::AttachedToWindow();
220ff09c7bfSAxel Dörfler 	if (Parent() != NULL) {
221ff09c7bfSAxel Dörfler 		if ((Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0)
222ff09c7bfSAxel Dörfler 			SetViewColor(B_TRANSPARENT_COLOR);
223f01106c3SAxel Dörfler 		else
224ff09c7bfSAxel Dörfler 			SetViewColor(Parent()->ViewColor());
225ff09c7bfSAxel Dörfler 	} else
226f01106c3SAxel Dörfler 		SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
227f01106c3SAxel Dörfler 
228f01106c3SAxel Dörfler 	SetLowColor(ViewColor());
229f01106c3SAxel Dörfler 
230195981bbSAxel Dörfler 	start_watching_network(
231195981bbSAxel Dörfler 		B_WATCH_NETWORK_INTERFACE_CHANGES | B_WATCH_NETWORK_LINK_CHANGES, this);
232f01106c3SAxel Dörfler 
233f01106c3SAxel Dörfler 	_Update();
234f01106c3SAxel Dörfler }
235f01106c3SAxel Dörfler 
236f01106c3SAxel Dörfler 
237f01106c3SAxel Dörfler void
238f01106c3SAxel Dörfler NetworkStatusView::DetachedFromWindow()
239f01106c3SAxel Dörfler {
240195981bbSAxel Dörfler 	stop_watching_network(this);
241f01106c3SAxel Dörfler }
242f01106c3SAxel Dörfler 
243f01106c3SAxel Dörfler 
244f01106c3SAxel Dörfler void
245f01106c3SAxel Dörfler NetworkStatusView::MessageReceived(BMessage* message)
246f01106c3SAxel Dörfler {
247f01106c3SAxel Dörfler 	switch (message->what) {
248195981bbSAxel Dörfler 		case B_NETWORK_MONITOR:
249f01106c3SAxel Dörfler 			_Update();
250f01106c3SAxel Dörfler 			break;
251f01106c3SAxel Dörfler 
252f01106c3SAxel Dörfler 		case kMsgShowConfiguration:
253f01106c3SAxel Dörfler 			_ShowConfiguration(message);
254f01106c3SAxel Dörfler 			break;
255f01106c3SAxel Dörfler 
256c1502c9aSStephan Aßmus 		case kMsgOpenNetworkPreferences:
2573b41ad86SStephan Aßmus 			_OpenNetworksPreferences();
2583b41ad86SStephan Aßmus 			break;
2593b41ad86SStephan Aßmus 
2602e1a6286SAxel Dörfler 		case kMsgJoinNetwork:
2612e1a6286SAxel Dörfler 		{
2622e1a6286SAxel Dörfler 			const char* deviceName;
2632e1a6286SAxel Dörfler 			const char* name;
2646c7caf44SAxel Dörfler 			BNetworkAddress address;
2652e1a6286SAxel Dörfler 			if (message->FindString("device", &deviceName) == B_OK
2666c7caf44SAxel Dörfler 				&& message->FindString("name", &name) == B_OK
2676c7caf44SAxel Dörfler 				&& message->FindFlat("address", &address) == B_OK) {
2682e1a6286SAxel Dörfler 				BNetworkDevice device(deviceName);
2696c7caf44SAxel Dörfler 				status_t status = device.JoinNetwork(address);
2702e1a6286SAxel Dörfler 				if (status != B_OK) {
2712e1a6286SAxel Dörfler 					BString text
2722e1a6286SAxel Dörfler 						= B_TRANSLATE("Could not join wireless network:\n");
2732e1a6286SAxel Dörfler 					text << strerror(status);
2742e1a6286SAxel Dörfler 					BAlert* alert = new BAlert(name, text.String(),
2752e1a6286SAxel Dörfler 						B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL,
2762e1a6286SAxel Dörfler 						B_STOP_ALERT);
277aed35104SHumdinger 					alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
2782e1a6286SAxel Dörfler 					alert->Go(NULL);
2792e1a6286SAxel Dörfler 				}
2802e1a6286SAxel Dörfler 			}
2812e1a6286SAxel Dörfler 			break;
2822e1a6286SAxel Dörfler 		}
2832e1a6286SAxel Dörfler 
284f01106c3SAxel Dörfler 		case B_ABOUT_REQUESTED:
285f01106c3SAxel Dörfler 			_AboutRequested();
286f01106c3SAxel Dörfler 			break;
287f01106c3SAxel Dörfler 
288f01106c3SAxel Dörfler 		case B_QUIT_REQUESTED:
289f01106c3SAxel Dörfler 			_Quit();
290f01106c3SAxel Dörfler 			break;
291f01106c3SAxel Dörfler 
292f01106c3SAxel Dörfler 		default:
293f01106c3SAxel Dörfler 			BView::MessageReceived(message);
294f01106c3SAxel Dörfler 	}
295f01106c3SAxel Dörfler }
296f01106c3SAxel Dörfler 
297f01106c3SAxel Dörfler 
298f01106c3SAxel Dörfler void
299f01106c3SAxel Dörfler NetworkStatusView::FrameResized(float width, float height)
300f01106c3SAxel Dörfler {
301f01106c3SAxel Dörfler 	_UpdateBitmaps();
302d5ba07a3SAxel Dörfler 	Invalidate();
303f01106c3SAxel Dörfler }
304f01106c3SAxel Dörfler 
305f01106c3SAxel Dörfler 
306f01106c3SAxel Dörfler void
307f01106c3SAxel Dörfler NetworkStatusView::Draw(BRect updateRect)
308f01106c3SAxel Dörfler {
3095c46b171SRene Gollent 	int32 status = kStatusUnknown;
3105c46b171SRene Gollent 	for (std::map<BString, int32>::const_iterator it
3115c46b171SRene Gollent 		= fInterfaceStatuses.begin(); it != fInterfaceStatuses.end(); ++it) {
3125c46b171SRene Gollent 		if (it->second > status)
3135c46b171SRene Gollent 			status = it->second;
3145c46b171SRene Gollent 	}
3155c46b171SRene Gollent 
3165c46b171SRene Gollent 	if (fTrayIcons[status] == NULL)
317f01106c3SAxel Dörfler 		return;
318f01106c3SAxel Dörfler 
319f01106c3SAxel Dörfler 	SetDrawingMode(B_OP_ALPHA);
3205c46b171SRene Gollent 	DrawBitmap(fTrayIcons[status]);
321f01106c3SAxel Dörfler 	SetDrawingMode(B_OP_COPY);
322f01106c3SAxel Dörfler }
323f01106c3SAxel Dörfler 
324f01106c3SAxel Dörfler 
325f01106c3SAxel Dörfler void
326f01106c3SAxel Dörfler NetworkStatusView::_ShowConfiguration(BMessage* message)
327f01106c3SAxel Dörfler {
328f01106c3SAxel Dörfler 	const char* name;
329f01106c3SAxel Dörfler 	if (message->FindString("interface", &name) != B_OK)
330f01106c3SAxel Dörfler 		return;
331f01106c3SAxel Dörfler 
3328897f278SStefano Ceccherini 	BNetworkInterface networkInterface(name);
3338897f278SStefano Ceccherini 	if (!networkInterface.Exists())
334f01106c3SAxel Dörfler 		return;
335f01106c3SAxel Dörfler 
3368897f278SStefano Ceccherini 	BNetworkInterfaceAddress address;
3378897f278SStefano Ceccherini 	networkInterface.GetAddressAt(0, address);
3388897f278SStefano Ceccherini 		// TODO: We should get all addresses,
3398897f278SStefano Ceccherini 		// not just the first one.
3402ee8f3f6SSiarzhuk Zharski 	BString text(B_TRANSLATE("%ifaceName information:\n"));
3412ee8f3f6SSiarzhuk Zharski 	text.ReplaceFirst("%ifaceName", name);
342757e7059SAdrien Destugues 
343f01106c3SAxel Dörfler 	size_t boldLength = text.Length();
344f01106c3SAxel Dörfler 
3458897f278SStefano Ceccherini 	text << "\n" << B_TRANSLATE("Address") << ": " << address.Address().ToString();
3468897f278SStefano Ceccherini 	text << "\n" << B_TRANSLATE("Broadcast") << ": " << address.Broadcast().ToString();
3478897f278SStefano Ceccherini 	text << "\n" << B_TRANSLATE("Netmask") << ": " << address.Mask().ToString();
348f01106c3SAxel Dörfler 
349757e7059SAdrien Destugues 	BAlert* alert = new BAlert(name, text.String(), B_TRANSLATE("OK"));
350aed35104SHumdinger 	alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
351f01106c3SAxel Dörfler 	BTextView* view = alert->TextView();
352f01106c3SAxel Dörfler 	BFont font;
353f01106c3SAxel Dörfler 
354f01106c3SAxel Dörfler 	view->SetStylable(true);
355f01106c3SAxel Dörfler 	view->GetFont(&font);
356f01106c3SAxel Dörfler 	font.SetFace(B_BOLD_FACE);
357f01106c3SAxel Dörfler 	view->SetFontAndColor(0, boldLength, &font);
358f01106c3SAxel Dörfler 
359f01106c3SAxel Dörfler 	alert->Go(NULL);
360f01106c3SAxel Dörfler }
361f01106c3SAxel Dörfler 
362f01106c3SAxel Dörfler 
363f01106c3SAxel Dörfler void
364f01106c3SAxel Dörfler NetworkStatusView::MouseDown(BPoint point)
365f01106c3SAxel Dörfler {
366f01106c3SAxel Dörfler 	BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
367a31688d2SAxel Dörfler 	menu->SetAsyncAutoDestruct(true);
368f01106c3SAxel Dörfler 	menu->SetFont(be_plain_font);
3695c46b171SRene Gollent 	BString wifiInterface;
3705c46b171SRene Gollent 	BNetworkDevice wifiDevice;
371f01106c3SAxel Dörfler 
3725fe97f21SAxel Dörfler 	// Add interfaces
3735fe97f21SAxel Dörfler 
3745c46b171SRene Gollent 	for (std::map<BString, int32>::const_iterator it
3755c46b171SRene Gollent 		= fInterfaceStatuses.begin(); it != fInterfaceStatuses.end(); ++it) {
3765c46b171SRene Gollent 		const BString& name = it->first;
377f01106c3SAxel Dörfler 
378f01106c3SAxel Dörfler 		BString label = name;
379f01106c3SAxel Dörfler 		label += ": ";
380f01106c3SAxel Dörfler 		label += kStatusDescriptions[
381f01106c3SAxel Dörfler 			_DetermineInterfaceStatus(name.String())];
382f01106c3SAxel Dörfler 
383f01106c3SAxel Dörfler 		BMessage* info = new BMessage(kMsgShowConfiguration);
384f01106c3SAxel Dörfler 		info->AddString("interface", name.String());
385f01106c3SAxel Dörfler 		menu->AddItem(new BMenuItem(label.String(), info));
3865c46b171SRene Gollent 
3875c46b171SRene Gollent 		// We only show the networks of the first wireless device we find.
3885c46b171SRene Gollent 		if (wifiInterface.IsEmpty()) {
3895c46b171SRene Gollent 			wifiDevice.SetTo(name);
3905c46b171SRene Gollent 			if (wifiDevice.IsWireless())
3915c46b171SRene Gollent 				wifiInterface = name;
3925c46b171SRene Gollent 		}
393f01106c3SAxel Dörfler 	}
394f01106c3SAxel Dörfler 
3955c46b171SRene Gollent 	if (!fInterfaceStatuses.empty())
396f01106c3SAxel Dörfler 		menu->AddSeparatorItem();
3975fe97f21SAxel Dörfler 
3985fe97f21SAxel Dörfler 	// Add wireless networks, if any
3995fe97f21SAxel Dörfler 
4005c46b171SRene Gollent 	if (!wifiInterface.IsEmpty()) {
401440d0e61SAxel Dörfler 		std::set<BNetworkAddress> associated;
402440d0e61SAxel Dörfler 		BNetworkAddress address;
403440d0e61SAxel Dörfler 		uint32 cookie = 0;
4045c46b171SRene Gollent 		while (wifiDevice.GetNextAssociatedNetwork(cookie, address) == B_OK)
405440d0e61SAxel Dörfler 			associated.insert(address);
406440d0e61SAxel Dörfler 
4075fe97f21SAxel Dörfler 		wireless_network network;
4085fe97f21SAxel Dörfler 		int32 count = 0;
409440d0e61SAxel Dörfler 		cookie = 0;
4105c46b171SRene Gollent 		while (wifiDevice.GetNextNetwork(cookie, network) == B_OK) {
4112e1a6286SAxel Dörfler 			BMessage* message = new BMessage(kMsgJoinNetwork);
4125c46b171SRene Gollent 			message->AddString("device", wifiInterface);
4132e1a6286SAxel Dörfler 			message->AddString("name", network.name);
4146c7caf44SAxel Dörfler 			message->AddFlat("address", &network.address);
4152e1a6286SAxel Dörfler 
416440d0e61SAxel Dörfler 			BMenuItem* item = new WirelessNetworkMenuItem(network.name,
4175bb799c2SPrzemysław Buczkowski 				network.signal_strength, network.authentication_mode, message);
418440d0e61SAxel Dörfler 			menu->AddItem(item);
419440d0e61SAxel Dörfler 			if (associated.find(network.address) != associated.end())
420440d0e61SAxel Dörfler 				item->SetMarked(true);
421440d0e61SAxel Dörfler 
4225fe97f21SAxel Dörfler 			count++;
4235fe97f21SAxel Dörfler 		}
4245fe97f21SAxel Dörfler 		if (count == 0) {
4255fe97f21SAxel Dörfler 			BMenuItem* item = new BMenuItem(
4265fe97f21SAxel Dörfler 				B_TRANSLATE("<no wireless networks found>"), NULL);
4275fe97f21SAxel Dörfler 			item->SetEnabled(false);
4285fe97f21SAxel Dörfler 			menu->AddItem(item);
4295fe97f21SAxel Dörfler 		}
4305fe97f21SAxel Dörfler 		menu->AddSeparatorItem();
4315fe97f21SAxel Dörfler 	}
4325fe97f21SAxel Dörfler 
433757e7059SAdrien Destugues 	menu->AddItem(new BMenuItem(B_TRANSLATE(
434757e7059SAdrien Destugues 		"Open network preferences" B_UTF8_ELLIPSIS),
435c1502c9aSStephan Aßmus 		new BMessage(kMsgOpenNetworkPreferences)));
4363b41ad86SStephan Aßmus 
4375fe97f21SAxel Dörfler 	if (fInDeskbar) {
438757e7059SAdrien Destugues 		menu->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
439757e7059SAdrien Destugues 			new BMessage(B_QUIT_REQUESTED)));
4405fe97f21SAxel Dörfler 	}
441f01106c3SAxel Dörfler 	menu->SetTargetForItems(this);
442f01106c3SAxel Dörfler 
443f01106c3SAxel Dörfler 	ConvertToScreen(&point);
444a31688d2SAxel Dörfler 	menu->Go(point, true, true, true);
445f01106c3SAxel Dörfler }
446f01106c3SAxel Dörfler 
447f01106c3SAxel Dörfler 
448f01106c3SAxel Dörfler void
449f01106c3SAxel Dörfler NetworkStatusView::_AboutRequested()
450f01106c3SAxel Dörfler {
45131535ac6SAdrien Destugues 	BAboutWindow* window = new BAboutWindow(
45231535ac6SAdrien Destugues 		B_TRANSLATE_SYSTEM_NAME("NetworkStatus"), kSignature);
453fd19c736SAdrien Destugues 
454730a45eeSJohn Scipione 	const char* authors[] = {
455730a45eeSJohn Scipione 		"Axel Dörfler",
456730a45eeSJohn Scipione 		"Hugo Santos",
457730a45eeSJohn Scipione 		NULL
458730a45eeSJohn Scipione 	};
459f01106c3SAxel Dörfler 
460fd19c736SAdrien Destugues 	window->AddCopyright(2007, "Haiku, Inc.");
461fd19c736SAdrien Destugues 	window->AddAuthors(authors);
462fd19c736SAdrien Destugues 
463fd19c736SAdrien Destugues 	window->Show();
464f01106c3SAxel Dörfler }
465f01106c3SAxel Dörfler 
466f01106c3SAxel Dörfler 
467f01106c3SAxel Dörfler int32
4685c46b171SRene Gollent NetworkStatusView::_DetermineInterfaceStatus(
4695c46b171SRene Gollent 	const BNetworkInterface& interface)
470f01106c3SAxel Dörfler {
4715fe97f21SAxel Dörfler 	uint32 flags = interface.Flags();
472f01106c3SAxel Dörfler 	int32 status = kStatusNoLink;
473f01106c3SAxel Dörfler 
474f01106c3SAxel Dörfler 	// TODO: no kStatusLinkNoConfig yet
475f01106c3SAxel Dörfler 
476f01106c3SAxel Dörfler 	if (flags & IFF_CONFIGURING)
477f01106c3SAxel Dörfler 		status = kStatusConnecting;
4782a17be44SAxel Dörfler 	else if ((flags & (IFF_UP | IFF_LINK)) == (IFF_UP | IFF_LINK))
479f01106c3SAxel Dörfler 		status = kStatusReady;
480f01106c3SAxel Dörfler 
481f01106c3SAxel Dörfler 	return status;
482f01106c3SAxel Dörfler }
483f01106c3SAxel Dörfler 
484f01106c3SAxel Dörfler 
485f01106c3SAxel Dörfler void
486f01106c3SAxel Dörfler NetworkStatusView::_Update(bool force)
487f01106c3SAxel Dörfler {
4885fe97f21SAxel Dörfler 	BNetworkRoster& roster = BNetworkRoster::Default();
4895fe97f21SAxel Dörfler 	BNetworkInterface interface;
4905fe97f21SAxel Dörfler 	uint32 cookie = 0;
4915fe97f21SAxel Dörfler 
4925fe97f21SAxel Dörfler 	while (roster.GetNextInterface(&cookie, interface) == B_OK) {
4935fe97f21SAxel Dörfler 		if ((interface.Flags() & IFF_LOOPBACK) == 0) {
4945c46b171SRene Gollent 			int32 oldStatus = kStatusUnknown;
4955c46b171SRene Gollent 			if (fInterfaceStatuses.find(interface.Name())
4965c46b171SRene Gollent 				!= fInterfaceStatuses.end()) {
4975c46b171SRene Gollent 				oldStatus = fInterfaceStatuses[interface.Name()];
498f01106c3SAxel Dörfler 			}
4995c46b171SRene Gollent 			int32 status = _DetermineInterfaceStatus(interface);
5005c46b171SRene Gollent 			if (oldStatus != status) {
501b44d24c0SAlexander von Gluck IV 				BNotification notification(B_INFORMATION_NOTIFICATION);
502b44d24c0SAlexander von Gluck IV 				notification.SetGroup(B_TRANSLATE("Network Status"));
503b44d24c0SAlexander von Gluck IV 				notification.SetTitle(interface.Name());
504b44d24c0SAlexander von Gluck IV 				notification.SetMessageID(interface.Name());
5055c46b171SRene Gollent 				notification.SetIcon(fNotifyIcons[status]);
5065c46b171SRene Gollent 				if (status == kStatusConnecting
5075c46b171SRene Gollent 					|| (status == kStatusReady
5085c46b171SRene Gollent 						&& oldStatus == kStatusConnecting)
5095c46b171SRene Gollent 					|| (status == kStatusNoLink
5105c46b171SRene Gollent 						&& oldStatus == kStatusReady)
5115c46b171SRene Gollent 					|| (status == kStatusNoLink
5125c46b171SRene Gollent 						&& oldStatus == kStatusConnecting)) {
51343c68287SAlexander von Gluck IV 					// A significant state change, raise notification.
5145c46b171SRene Gollent 					notification.SetContent(kStatusDescriptions[status]);
515b44d24c0SAlexander von Gluck IV 					notification.Send();
516b44d24c0SAlexander von Gluck IV 				}
517f01106c3SAxel Dörfler 				Invalidate();
518f01106c3SAxel Dörfler 			}
5195c46b171SRene Gollent 			fInterfaceStatuses[interface.Name()] = status;
5205c46b171SRene Gollent 		}
5215c46b171SRene Gollent 	}
522b44d24c0SAlexander von Gluck IV }
523f01106c3SAxel Dörfler 
524f01106c3SAxel Dörfler 
5253b41ad86SStephan Aßmus void
5263b41ad86SStephan Aßmus NetworkStatusView::_OpenNetworksPreferences()
5273b41ad86SStephan Aßmus {
528195981bbSAxel Dörfler 	status_t status = be_roster->Launch("application/x-vnd.Haiku-Network");
52946cac7f7SAlexandre Deckner 	if (status != B_OK && status != B_ALREADY_RUNNING) {
530757e7059SAdrien Destugues 		BString errorMessage(B_TRANSLATE("Launching the network preflet "
531757e7059SAdrien Destugues 			"failed.\n\nError: "));
532195981bbSAxel Dörfler 		errorMessage << strerror(status);
5333b41ad86SStephan Aßmus 		BAlert* alert = new BAlert("launch error", errorMessage.String(),
534757e7059SAdrien Destugues 			B_TRANSLATE("OK"));
535aed35104SHumdinger 		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
536195981bbSAxel Dörfler 
537195981bbSAxel Dörfler 		// asynchronous alert in order to not block replicant host application
5383b41ad86SStephan Aßmus 		alert->Go(NULL);
5393b41ad86SStephan Aßmus 	}
5403b41ad86SStephan Aßmus }
5413b41ad86SStephan Aßmus 
5423b41ad86SStephan Aßmus 
543f01106c3SAxel Dörfler //	#pragma mark -
544f01106c3SAxel Dörfler 
545f01106c3SAxel Dörfler 
546f01106c3SAxel Dörfler extern "C" _EXPORT BView *
547f01106c3SAxel Dörfler instantiate_deskbar_item(void)
548f01106c3SAxel Dörfler {
54966eba86fSAxel Dörfler 	return new NetworkStatusView(BRect(0, 0, 15, 15),
55066eba86fSAxel Dörfler 		B_FOLLOW_LEFT | B_FOLLOW_TOP, true);
551f01106c3SAxel Dörfler }
552f01106c3SAxel Dörfler 
553