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
15aba4cb20SMichael Lotz #include <algorithm>
16440d0e61SAxel Dörfler #include <set>
17aba4cb20SMichael Lotz #include <vector>
18440d0e61SAxel Dörfler
19195981bbSAxel Dörfler #include <arpa/inet.h>
20195981bbSAxel Dörfler #include <net/if.h>
21195981bbSAxel Dörfler #include <stdio.h>
22195981bbSAxel Dörfler #include <stdlib.h>
233aeed660SJérôme Duval #include <strings.h>
24195981bbSAxel Dörfler #include <sys/socket.h>
25195981bbSAxel Dörfler #include <sys/sockio.h>
26195981bbSAxel Dörfler #include <unistd.h>
27f01106c3SAxel Dörfler
28730a45eeSJohn Scipione #include <AboutWindow.h>
29f01106c3SAxel Dörfler #include <Alert.h>
30f01106c3SAxel Dörfler #include <Application.h>
31757e7059SAdrien Destugues #include <Catalog.h>
32f01106c3SAxel Dörfler #include <Bitmap.h>
33f01106c3SAxel Dörfler #include <Deskbar.h>
34f01106c3SAxel Dörfler #include <Dragger.h>
35f01106c3SAxel Dörfler #include <Drivers.h>
36f01106c3SAxel Dörfler #include <IconUtils.h>
37757e7059SAdrien Destugues #include <Locale.h>
38f01106c3SAxel Dörfler #include <MenuItem.h>
39f01106c3SAxel Dörfler #include <MessageRunner.h>
405fe97f21SAxel Dörfler #include <NetworkInterface.h>
415fe97f21SAxel Dörfler #include <NetworkRoster.h>
42f01106c3SAxel Dörfler #include <PopUpMenu.h>
43f01106c3SAxel Dörfler #include <Resources.h>
44d5ba07a3SAxel Dörfler #include <Roster.h>
45f01106c3SAxel Dörfler #include <String.h>
46f01106c3SAxel Dörfler #include <TextView.h>
47f01106c3SAxel Dörfler
48195981bbSAxel Dörfler #include "NetworkStatus.h"
49195981bbSAxel Dörfler #include "NetworkStatusIcons.h"
505fe97f21SAxel Dörfler #include "RadioView.h"
513ca00ffdSAxel Dörfler #include "WirelessNetworkMenuItem.h"
52195981bbSAxel Dörfler
53f01106c3SAxel Dörfler
54546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
55546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "NetworkStatusView"
56757e7059SAdrien Destugues
57757e7059SAdrien Destugues
58f01106c3SAxel Dörfler static const char *kStatusDescriptions[] = {
592ee8f3f6SSiarzhuk Zharski B_TRANSLATE("Unknown"),
602ee8f3f6SSiarzhuk Zharski B_TRANSLATE("No link"),
612ee8f3f6SSiarzhuk Zharski B_TRANSLATE("No stateful configuration"),
622ee8f3f6SSiarzhuk Zharski B_TRANSLATE("Configuring"),
632ee8f3f6SSiarzhuk Zharski B_TRANSLATE("Ready")
64f01106c3SAxel Dörfler };
65f01106c3SAxel Dörfler
66efafab64SAxel Dörfler extern "C" _EXPORT BView *instantiate_deskbar_item(float maxWidth, float maxHeight);
67f01106c3SAxel Dörfler
68f01106c3SAxel Dörfler
69f01106c3SAxel Dörfler const uint32 kMsgShowConfiguration = 'shcf';
70c1502c9aSStephan Aßmus const uint32 kMsgOpenNetworkPreferences = 'onwp';
712e1a6286SAxel Dörfler const uint32 kMsgJoinNetwork = 'join';
72f01106c3SAxel Dörfler
73f01106c3SAxel Dörfler const uint32 kMinIconWidth = 16;
74f01106c3SAxel Dörfler const uint32 kMinIconHeight = 16;
75f01106c3SAxel Dörfler
76195981bbSAxel Dörfler
7702ad9218SJohn Scipione // #pragma mark - NetworkStatusView
78aba4cb20SMichael Lotz
79aba4cb20SMichael Lotz
NetworkStatusView(BRect frame,int32 resizingMode,bool inDeskbar)80f01106c3SAxel Dörfler NetworkStatusView::NetworkStatusView(BRect frame, int32 resizingMode,
81f01106c3SAxel Dörfler bool inDeskbar)
82f01106c3SAxel Dörfler : BView(frame, kDeskbarItemName, resizingMode,
8347102c07SX512 B_WILL_DRAW | B_TRANSPARENT_BACKGROUND | B_FRAME_EVENTS),
845c46b171SRene Gollent fInDeskbar(inDeskbar)
85f01106c3SAxel Dörfler {
86f01106c3SAxel Dörfler _Init();
87f01106c3SAxel Dörfler
88f01106c3SAxel Dörfler if (!inDeskbar) {
89f01106c3SAxel Dörfler // we were obviously added to a standard window - let's add a dragger
90f01106c3SAxel Dörfler frame.OffsetTo(B_ORIGIN);
91f01106c3SAxel Dörfler frame.top = frame.bottom - 7;
92f01106c3SAxel Dörfler frame.left = frame.right - 7;
93f01106c3SAxel Dörfler BDragger* dragger = new BDragger(frame, this,
94f01106c3SAxel Dörfler B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
95f01106c3SAxel Dörfler AddChild(dragger);
96f01106c3SAxel Dörfler } else
97f01106c3SAxel Dörfler _Update();
98f01106c3SAxel Dörfler }
99f01106c3SAxel Dörfler
100f01106c3SAxel Dörfler
NetworkStatusView(BMessage * archive)101f01106c3SAxel Dörfler NetworkStatusView::NetworkStatusView(BMessage* archive)
102d5ba07a3SAxel Dörfler : BView(archive),
103d5ba07a3SAxel Dörfler fInDeskbar(false)
104f01106c3SAxel Dörfler {
105d5ba07a3SAxel Dörfler app_info info;
106d5ba07a3SAxel Dörfler if (be_app->GetAppInfo(&info) == B_OK
107d5ba07a3SAxel Dörfler && !strcasecmp(info.signature, "application/x-vnd.Be-TSKB"))
108d5ba07a3SAxel Dörfler fInDeskbar = true;
109d5ba07a3SAxel Dörfler
110f01106c3SAxel Dörfler _Init();
111f01106c3SAxel Dörfler }
112f01106c3SAxel Dörfler
113f01106c3SAxel Dörfler
~NetworkStatusView()114f01106c3SAxel Dörfler NetworkStatusView::~NetworkStatusView()
115f01106c3SAxel Dörfler {
116f01106c3SAxel Dörfler }
117f01106c3SAxel Dörfler
118f01106c3SAxel Dörfler
119f01106c3SAxel Dörfler void
_Init()120f01106c3SAxel Dörfler NetworkStatusView::_Init()
121f01106c3SAxel Dörfler {
122f01106c3SAxel Dörfler for (int i = 0; i < kStatusCount; i++) {
123e58807edSAlexander von Gluck IV fTrayIcons[i] = NULL;
124e58807edSAlexander von Gluck IV fNotifyIcons[i] = NULL;
125f01106c3SAxel Dörfler }
126f01106c3SAxel Dörfler
127f01106c3SAxel Dörfler _UpdateBitmaps();
128f01106c3SAxel Dörfler }
129f01106c3SAxel Dörfler
130f01106c3SAxel Dörfler
131f01106c3SAxel Dörfler void
_UpdateBitmaps()132f01106c3SAxel Dörfler NetworkStatusView::_UpdateBitmaps()
133f01106c3SAxel Dörfler {
134f01106c3SAxel Dörfler for (int i = 0; i < kStatusCount; i++) {
135e58807edSAlexander von Gluck IV delete fTrayIcons[i];
136e58807edSAlexander von Gluck IV delete fNotifyIcons[i];
137e58807edSAlexander von Gluck IV fTrayIcons[i] = NULL;
138e58807edSAlexander von Gluck IV fNotifyIcons[i] = NULL;
139f01106c3SAxel Dörfler }
140f01106c3SAxel Dörfler
141f01106c3SAxel Dörfler image_info info;
142f01106c3SAxel Dörfler if (our_image(info) != B_OK)
143f01106c3SAxel Dörfler return;
144f01106c3SAxel Dörfler
145f01106c3SAxel Dörfler BFile file(info.name, B_READ_ONLY);
146f01106c3SAxel Dörfler if (file.InitCheck() < B_OK)
147f01106c3SAxel Dörfler return;
148f01106c3SAxel Dörfler
149f01106c3SAxel Dörfler BResources resources(&file);
150f01106c3SAxel Dörfler #ifdef HAIKU_TARGET_PLATFORM_HAIKU
151f01106c3SAxel Dörfler if (resources.InitCheck() < B_OK)
152f01106c3SAxel Dörfler return;
153f01106c3SAxel Dörfler #endif
154f01106c3SAxel Dörfler
155f01106c3SAxel Dörfler for (int i = 0; i < kStatusCount; i++) {
156f01106c3SAxel Dörfler const void* data = NULL;
157f01106c3SAxel Dörfler size_t size;
158f01106c3SAxel Dörfler data = resources.LoadResource(B_VECTOR_ICON_TYPE,
159f01106c3SAxel Dörfler kNetworkStatusNoDevice + i, &size);
160f01106c3SAxel Dörfler if (data != NULL) {
161e58807edSAlexander von Gluck IV // Scale main tray icon
162e58807edSAlexander von Gluck IV BBitmap* trayIcon = new BBitmap(Bounds(), B_RGBA32);
163e58807edSAlexander von Gluck IV if (trayIcon->InitCheck() == B_OK
164f01106c3SAxel Dörfler && BIconUtils::GetVectorIcon((const uint8 *)data,
165e58807edSAlexander von Gluck IV size, trayIcon) == B_OK) {
166e58807edSAlexander von Gluck IV fTrayIcons[i] = trayIcon;
167f01106c3SAxel Dörfler } else
168e58807edSAlexander von Gluck IV delete trayIcon;
169e58807edSAlexander von Gluck IV
170e58807edSAlexander von Gluck IV // Scale notification icon
171e58807edSAlexander von Gluck IV BBitmap* notifyIcon = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32);
172e58807edSAlexander von Gluck IV if (notifyIcon->InitCheck() == B_OK
173e58807edSAlexander von Gluck IV && BIconUtils::GetVectorIcon((const uint8 *)data,
174e58807edSAlexander von Gluck IV size, notifyIcon) == B_OK) {
175e58807edSAlexander von Gluck IV fNotifyIcons[i] = notifyIcon;
176e58807edSAlexander von Gluck IV } else
177e58807edSAlexander von Gluck IV delete notifyIcon;
178f01106c3SAxel Dörfler }
179f01106c3SAxel Dörfler }
180f01106c3SAxel Dörfler }
181f01106c3SAxel Dörfler
182f01106c3SAxel Dörfler
183f01106c3SAxel Dörfler void
_Quit()184f01106c3SAxel Dörfler NetworkStatusView::_Quit()
185f01106c3SAxel Dörfler {
186f01106c3SAxel Dörfler if (fInDeskbar) {
187f01106c3SAxel Dörfler BDeskbar deskbar;
188f01106c3SAxel Dörfler deskbar.RemoveItem(kDeskbarItemName);
189f01106c3SAxel Dörfler } else
190f01106c3SAxel Dörfler be_app->PostMessage(B_QUIT_REQUESTED);
191f01106c3SAxel Dörfler }
192f01106c3SAxel Dörfler
193f01106c3SAxel Dörfler
194f01106c3SAxel Dörfler NetworkStatusView*
Instantiate(BMessage * archive)195f01106c3SAxel Dörfler NetworkStatusView::Instantiate(BMessage* archive)
196f01106c3SAxel Dörfler {
197f01106c3SAxel Dörfler if (!validate_instantiation(archive, "NetworkStatusView"))
198f01106c3SAxel Dörfler return NULL;
199f01106c3SAxel Dörfler
200f01106c3SAxel Dörfler return new NetworkStatusView(archive);
201f01106c3SAxel Dörfler }
202f01106c3SAxel Dörfler
203f01106c3SAxel Dörfler
204f01106c3SAxel Dörfler status_t
Archive(BMessage * archive,bool deep) const205f01106c3SAxel Dörfler NetworkStatusView::Archive(BMessage* archive, bool deep) const
206f01106c3SAxel Dörfler {
207f01106c3SAxel Dörfler status_t status = BView::Archive(archive, deep);
208f01106c3SAxel Dörfler if (status == B_OK)
209f01106c3SAxel Dörfler status = archive->AddString("add_on", kSignature);
210f01106c3SAxel Dörfler if (status == B_OK)
211f01106c3SAxel Dörfler status = archive->AddString("class", "NetworkStatusView");
212f01106c3SAxel Dörfler
213f01106c3SAxel Dörfler return status;
214f01106c3SAxel Dörfler }
215f01106c3SAxel Dörfler
216f01106c3SAxel Dörfler
217f01106c3SAxel Dörfler void
AttachedToWindow()218f01106c3SAxel Dörfler NetworkStatusView::AttachedToWindow()
219f01106c3SAxel Dörfler {
220f01106c3SAxel Dörfler BView::AttachedToWindow();
221f01106c3SAxel Dörfler
222485a9ea0SX512 SetViewColor(B_TRANSPARENT_COLOR);
223f01106c3SAxel Dörfler
224195981bbSAxel Dörfler start_watching_network(
225195981bbSAxel Dörfler B_WATCH_NETWORK_INTERFACE_CHANGES | B_WATCH_NETWORK_LINK_CHANGES, this);
226f01106c3SAxel Dörfler
227f01106c3SAxel Dörfler _Update();
228f01106c3SAxel Dörfler }
229f01106c3SAxel Dörfler
230f01106c3SAxel Dörfler
231f01106c3SAxel Dörfler void
DetachedFromWindow()232f01106c3SAxel Dörfler NetworkStatusView::DetachedFromWindow()
233f01106c3SAxel Dörfler {
234195981bbSAxel Dörfler stop_watching_network(this);
235f01106c3SAxel Dörfler }
236f01106c3SAxel Dörfler
237f01106c3SAxel Dörfler
238f01106c3SAxel Dörfler void
MessageReceived(BMessage * message)239f01106c3SAxel Dörfler NetworkStatusView::MessageReceived(BMessage* message)
240f01106c3SAxel Dörfler {
241f01106c3SAxel Dörfler switch (message->what) {
242195981bbSAxel Dörfler case B_NETWORK_MONITOR:
243f01106c3SAxel Dörfler _Update();
244f01106c3SAxel Dörfler break;
245f01106c3SAxel Dörfler
246f01106c3SAxel Dörfler case kMsgShowConfiguration:
247f01106c3SAxel Dörfler _ShowConfiguration(message);
248f01106c3SAxel Dörfler break;
249f01106c3SAxel Dörfler
250c1502c9aSStephan Aßmus case kMsgOpenNetworkPreferences:
2513b41ad86SStephan Aßmus _OpenNetworksPreferences();
2523b41ad86SStephan Aßmus break;
2533b41ad86SStephan Aßmus
2542e1a6286SAxel Dörfler case kMsgJoinNetwork:
2552e1a6286SAxel Dörfler {
2562e1a6286SAxel Dörfler const char* deviceName;
2572e1a6286SAxel Dörfler const char* name;
2586c7caf44SAxel Dörfler BNetworkAddress address;
2592e1a6286SAxel Dörfler if (message->FindString("device", &deviceName) == B_OK
2606c7caf44SAxel Dörfler && message->FindString("name", &name) == B_OK
2616c7caf44SAxel Dörfler && message->FindFlat("address", &address) == B_OK) {
2622e1a6286SAxel Dörfler BNetworkDevice device(deviceName);
2636c7caf44SAxel Dörfler status_t status = device.JoinNetwork(address);
2642e1a6286SAxel Dörfler if (status != B_OK) {
2652e1a6286SAxel Dörfler BString text
2662e1a6286SAxel Dörfler = B_TRANSLATE("Could not join wireless network:\n");
2672e1a6286SAxel Dörfler text << strerror(status);
2682e1a6286SAxel Dörfler BAlert* alert = new BAlert(name, text.String(),
2692e1a6286SAxel Dörfler B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL,
2702e1a6286SAxel Dörfler B_STOP_ALERT);
271aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
2722e1a6286SAxel Dörfler alert->Go(NULL);
2732e1a6286SAxel Dörfler }
2742e1a6286SAxel Dörfler }
2752e1a6286SAxel Dörfler break;
2762e1a6286SAxel Dörfler }
2772e1a6286SAxel Dörfler
278f01106c3SAxel Dörfler case B_ABOUT_REQUESTED:
279f01106c3SAxel Dörfler _AboutRequested();
280f01106c3SAxel Dörfler break;
281f01106c3SAxel Dörfler
282f01106c3SAxel Dörfler case B_QUIT_REQUESTED:
283f01106c3SAxel Dörfler _Quit();
284f01106c3SAxel Dörfler break;
285f01106c3SAxel Dörfler
286f01106c3SAxel Dörfler default:
287f01106c3SAxel Dörfler BView::MessageReceived(message);
288ab05d368Ssushilhub break;
289f01106c3SAxel Dörfler }
290f01106c3SAxel Dörfler }
291f01106c3SAxel Dörfler
292f01106c3SAxel Dörfler
293f01106c3SAxel Dörfler void
FrameResized(float width,float height)294f01106c3SAxel Dörfler NetworkStatusView::FrameResized(float width, float height)
295f01106c3SAxel Dörfler {
296f01106c3SAxel Dörfler _UpdateBitmaps();
297d5ba07a3SAxel Dörfler Invalidate();
298f01106c3SAxel Dörfler }
299f01106c3SAxel Dörfler
300f01106c3SAxel Dörfler
301f01106c3SAxel Dörfler void
Draw(BRect updateRect)302f01106c3SAxel Dörfler NetworkStatusView::Draw(BRect updateRect)
303f01106c3SAxel Dörfler {
3045c46b171SRene Gollent int32 status = kStatusUnknown;
3055c46b171SRene Gollent for (std::map<BString, int32>::const_iterator it
3065c46b171SRene Gollent = fInterfaceStatuses.begin(); it != fInterfaceStatuses.end(); ++it) {
3075c46b171SRene Gollent if (it->second > status)
3085c46b171SRene Gollent status = it->second;
3095c46b171SRene Gollent }
3105c46b171SRene Gollent
3115c46b171SRene Gollent if (fTrayIcons[status] == NULL)
312f01106c3SAxel Dörfler return;
313f01106c3SAxel Dörfler
314f01106c3SAxel Dörfler SetDrawingMode(B_OP_ALPHA);
3155c46b171SRene Gollent DrawBitmap(fTrayIcons[status]);
316f01106c3SAxel Dörfler SetDrawingMode(B_OP_COPY);
317f01106c3SAxel Dörfler }
318f01106c3SAxel Dörfler
319f01106c3SAxel Dörfler
320f01106c3SAxel Dörfler void
_ShowConfiguration(BMessage * message)321f01106c3SAxel Dörfler NetworkStatusView::_ShowConfiguration(BMessage* message)
322f01106c3SAxel Dörfler {
323f01106c3SAxel Dörfler const char* name;
324f01106c3SAxel Dörfler if (message->FindString("interface", &name) != B_OK)
325f01106c3SAxel Dörfler return;
326f01106c3SAxel Dörfler
3278897f278SStefano Ceccherini BNetworkInterface networkInterface(name);
3288897f278SStefano Ceccherini if (!networkInterface.Exists())
329f01106c3SAxel Dörfler return;
330f01106c3SAxel Dörfler
3312ee8f3f6SSiarzhuk Zharski BString text(B_TRANSLATE("%ifaceName information:\n"));
3322ee8f3f6SSiarzhuk Zharski text.ReplaceFirst("%ifaceName", name);
333757e7059SAdrien Destugues
334f01106c3SAxel Dörfler size_t boldLength = text.Length();
335f01106c3SAxel Dörfler
336b81d67edSJeremy Visser int32 numAddrs = networkInterface.CountAddresses();
337b81d67edSJeremy Visser for (int32 i = 0; i < numAddrs; i++) {
338b81d67edSJeremy Visser BNetworkInterfaceAddress address;
339b81d67edSJeremy Visser networkInterface.GetAddressAt(i, address);
340b81d67edSJeremy Visser switch (address.Address().Family()) {
341b81d67edSJeremy Visser case AF_INET:
3428ff235aaSHumdinger text << "\n" << B_TRANSLATE("IPv4 address:") << " "
343b81d67edSJeremy Visser << address.Address().ToString()
3448ff235aaSHumdinger << "\n" << B_TRANSLATE("Broadcast:") << " "
345b81d67edSJeremy Visser << address.Broadcast().ToString()
3468ff235aaSHumdinger << "\n" << B_TRANSLATE("Netmask:") << " "
347b81d67edSJeremy Visser << address.Mask().ToString()
348b81d67edSJeremy Visser << "\n";
349b81d67edSJeremy Visser break;
350b81d67edSJeremy Visser case AF_INET6:
3518ff235aaSHumdinger text << "\n" << B_TRANSLATE("IPv6 address:") << " "
35296fbe0f7SAdrien Destugues << address.Address().ToString()
35396fbe0f7SAdrien Destugues << "/" << address.Mask().PrefixLength()
354b81d67edSJeremy Visser << "\n";
355b81d67edSJeremy Visser break;
356b81d67edSJeremy Visser default:
357b81d67edSJeremy Visser break;
358b81d67edSJeremy Visser }
359b81d67edSJeremy Visser }
360f01106c3SAxel Dörfler
361757e7059SAdrien Destugues BAlert* alert = new BAlert(name, text.String(), B_TRANSLATE("OK"));
362aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
363f01106c3SAxel Dörfler BTextView* view = alert->TextView();
364f01106c3SAxel Dörfler BFont font;
365f01106c3SAxel Dörfler
366f01106c3SAxel Dörfler view->SetStylable(true);
367f01106c3SAxel Dörfler view->GetFont(&font);
368f01106c3SAxel Dörfler font.SetFace(B_BOLD_FACE);
369f01106c3SAxel Dörfler view->SetFontAndColor(0, boldLength, &font);
370f01106c3SAxel Dörfler
371f01106c3SAxel Dörfler alert->Go(NULL);
372f01106c3SAxel Dörfler }
373f01106c3SAxel Dörfler
374f01106c3SAxel Dörfler
375f01106c3SAxel Dörfler void
MouseDown(BPoint point)376f01106c3SAxel Dörfler NetworkStatusView::MouseDown(BPoint point)
377f01106c3SAxel Dörfler {
378f01106c3SAxel Dörfler BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
379a31688d2SAxel Dörfler menu->SetAsyncAutoDestruct(true);
380f01106c3SAxel Dörfler menu->SetFont(be_plain_font);
3815c46b171SRene Gollent BString wifiInterface;
38202ad9218SJohn Scipione BNetworkDevice device;
383f01106c3SAxel Dörfler
38402ad9218SJohn Scipione if (!fInterfaceStatuses.empty()) {
3855c46b171SRene Gollent for (std::map<BString, int32>::const_iterator it
38602ad9218SJohn Scipione = fInterfaceStatuses.begin(); it != fInterfaceStatuses.end();
38702ad9218SJohn Scipione ++it) {
3885c46b171SRene Gollent const BString& name = it->first;
389f01106c3SAxel Dörfler
39002ad9218SJohn Scipione // we only show network of the first wireless device we find
3915c46b171SRene Gollent if (wifiInterface.IsEmpty()) {
39202ad9218SJohn Scipione device.SetTo(name);
39302ad9218SJohn Scipione if (device.IsWireless())
3945c46b171SRene Gollent wifiInterface = name;
3955c46b171SRene Gollent }
396f01106c3SAxel Dörfler }
39702ad9218SJohn Scipione }
398f01106c3SAxel Dörfler
39902ad9218SJohn Scipione // Add wireless networks, if any, first so that we can sort the menu
4005fe97f21SAxel Dörfler
4015c46b171SRene Gollent if (!wifiInterface.IsEmpty()) {
402440d0e61SAxel Dörfler std::set<BNetworkAddress> associated;
403440d0e61SAxel Dörfler BNetworkAddress address;
404440d0e61SAxel Dörfler uint32 cookie = 0;
40502ad9218SJohn Scipione while (device.GetNextAssociatedNetwork(cookie, address) == B_OK)
406440d0e61SAxel Dörfler associated.insert(address);
407440d0e61SAxel Dörfler
408*b2c77ad2SAugustin Cavalier uint32 networksCount = 0;
409*b2c77ad2SAugustin Cavalier wireless_network* networks = NULL;
410*b2c77ad2SAugustin Cavalier device.GetNetworks(networks, networksCount);
411*b2c77ad2SAugustin Cavalier for (uint32 i = 0; i < networksCount; i++) {
412*b2c77ad2SAugustin Cavalier const wireless_network& network = networks[i];
4132e1a6286SAxel Dörfler BMessage* message = new BMessage(kMsgJoinNetwork);
4145c46b171SRene Gollent message->AddString("device", wifiInterface);
4152e1a6286SAxel Dörfler message->AddString("name", network.name);
4166c7caf44SAxel Dörfler message->AddFlat("address", &network.address);
4172e1a6286SAxel Dörfler
41802ad9218SJohn Scipione BMenuItem* item = new WirelessNetworkMenuItem(network, message);
419440d0e61SAxel Dörfler menu->AddItem(item);
420440d0e61SAxel Dörfler if (associated.find(network.address) != associated.end())
421440d0e61SAxel Dörfler item->SetMarked(true);
4225fe97f21SAxel Dörfler }
423*b2c77ad2SAugustin Cavalier delete[] networks;
42402ad9218SJohn Scipione
425*b2c77ad2SAugustin Cavalier if (networksCount == 0) {
4265fe97f21SAxel Dörfler BMenuItem* item = new BMenuItem(
4275fe97f21SAxel Dörfler B_TRANSLATE("<no wireless networks found>"), NULL);
4285fe97f21SAxel Dörfler item->SetEnabled(false);
4295fe97f21SAxel Dörfler menu->AddItem(item);
43002ad9218SJohn Scipione } else
43102ad9218SJohn Scipione menu->SortItems(WirelessNetworkMenuItem::CompareSignalStrength);
43202ad9218SJohn Scipione
4335fe97f21SAxel Dörfler menu->AddSeparatorItem();
4345fe97f21SAxel Dörfler }
4355fe97f21SAxel Dörfler
43602ad9218SJohn Scipione // add action menu items
43702ad9218SJohn Scipione
438757e7059SAdrien Destugues menu->AddItem(new BMenuItem(B_TRANSLATE(
439757e7059SAdrien Destugues "Open network preferences" B_UTF8_ELLIPSIS),
440c1502c9aSStephan Aßmus new BMessage(kMsgOpenNetworkPreferences)));
4413b41ad86SStephan Aßmus
4425fe97f21SAxel Dörfler if (fInDeskbar) {
443757e7059SAdrien Destugues menu->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
444757e7059SAdrien Destugues new BMessage(B_QUIT_REQUESTED)));
4455fe97f21SAxel Dörfler }
44602ad9218SJohn Scipione
44702ad9218SJohn Scipione // Add wired interfaces to top of menu
44802ad9218SJohn Scipione if (!fInterfaceStatuses.empty()) {
44902ad9218SJohn Scipione int32 wiredCount = 0;
45002ad9218SJohn Scipione for (std::map<BString, int32>::const_iterator it
45102ad9218SJohn Scipione = fInterfaceStatuses.begin(); it != fInterfaceStatuses.end();
45202ad9218SJohn Scipione ++it) {
45302ad9218SJohn Scipione const BString& name = it->first;
45402ad9218SJohn Scipione
45502ad9218SJohn Scipione BString label = name;
45602ad9218SJohn Scipione label += ": ";
45702ad9218SJohn Scipione label += kStatusDescriptions[
45802ad9218SJohn Scipione _DetermineInterfaceStatus(name.String())];
45902ad9218SJohn Scipione
46002ad9218SJohn Scipione BMessage* info = new BMessage(kMsgShowConfiguration);
46102ad9218SJohn Scipione info->AddString("interface", name.String());
46202ad9218SJohn Scipione menu->AddItem(new BMenuItem(label.String(), info), wiredCount);
46302ad9218SJohn Scipione wiredCount++;
46402ad9218SJohn Scipione }
46502ad9218SJohn Scipione
46602ad9218SJohn Scipione // add separator item between wired and wireless networks
46702ad9218SJohn Scipione // (or between wired networks and actions if no wireless found)
46802ad9218SJohn Scipione if (wiredCount > 0)
46902ad9218SJohn Scipione menu->AddItem(new BSeparatorItem(), wiredCount);
47002ad9218SJohn Scipione }
47102ad9218SJohn Scipione
472f01106c3SAxel Dörfler menu->SetTargetForItems(this);
473f01106c3SAxel Dörfler
474f01106c3SAxel Dörfler ConvertToScreen(&point);
475a31688d2SAxel Dörfler menu->Go(point, true, true, true);
476f01106c3SAxel Dörfler }
477f01106c3SAxel Dörfler
478f01106c3SAxel Dörfler
479f01106c3SAxel Dörfler void
_AboutRequested()480f01106c3SAxel Dörfler NetworkStatusView::_AboutRequested()
481f01106c3SAxel Dörfler {
48231535ac6SAdrien Destugues BAboutWindow* window = new BAboutWindow(
48331535ac6SAdrien Destugues B_TRANSLATE_SYSTEM_NAME("NetworkStatus"), kSignature);
484fd19c736SAdrien Destugues
485730a45eeSJohn Scipione const char* authors[] = {
486730a45eeSJohn Scipione "Axel Dörfler",
487730a45eeSJohn Scipione "Hugo Santos",
488730a45eeSJohn Scipione NULL
489730a45eeSJohn Scipione };
490f01106c3SAxel Dörfler
491fd19c736SAdrien Destugues window->AddCopyright(2007, "Haiku, Inc.");
492fd19c736SAdrien Destugues window->AddAuthors(authors);
493fd19c736SAdrien Destugues
494fd19c736SAdrien Destugues window->Show();
495f01106c3SAxel Dörfler }
496f01106c3SAxel Dörfler
497f01106c3SAxel Dörfler
498f01106c3SAxel Dörfler int32
_DetermineInterfaceStatus(const BNetworkInterface & interface)4995c46b171SRene Gollent NetworkStatusView::_DetermineInterfaceStatus(
5005c46b171SRene Gollent const BNetworkInterface& interface)
501f01106c3SAxel Dörfler {
5025fe97f21SAxel Dörfler uint32 flags = interface.Flags();
503f01106c3SAxel Dörfler
504cb7833c7SPhilippe Houdoin if ((flags & IFF_LINK) == 0)
505cb7833c7SPhilippe Houdoin return kStatusNoLink;
506cb7833c7SPhilippe Houdoin if ((flags & (IFF_UP | IFF_LINK | IFF_CONFIGURING)) == IFF_LINK)
507cb7833c7SPhilippe Houdoin return kStatusLinkNoConfig;
5084a531db1SPhilippe Houdoin if ((flags & IFF_CONFIGURING) == IFF_CONFIGURING)
509cb7833c7SPhilippe Houdoin return kStatusConnecting;
510cb7833c7SPhilippe Houdoin if ((flags & (IFF_UP | IFF_LINK)) == (IFF_UP | IFF_LINK))
511cb7833c7SPhilippe Houdoin return kStatusReady;
512f01106c3SAxel Dörfler
513cb7833c7SPhilippe Houdoin return kStatusUnknown;
514f01106c3SAxel Dörfler }
515f01106c3SAxel Dörfler
516f01106c3SAxel Dörfler
517f01106c3SAxel Dörfler void
_Update(bool force)518f01106c3SAxel Dörfler NetworkStatusView::_Update(bool force)
519f01106c3SAxel Dörfler {
5205fe97f21SAxel Dörfler BNetworkRoster& roster = BNetworkRoster::Default();
5215fe97f21SAxel Dörfler BNetworkInterface interface;
5225fe97f21SAxel Dörfler uint32 cookie = 0;
523702ff421SJavier Steinaker std::set<BString> currentInterfaces;
5245fe97f21SAxel Dörfler
5255fe97f21SAxel Dörfler while (roster.GetNextInterface(&cookie, interface) == B_OK) {
5265fe97f21SAxel Dörfler if ((interface.Flags() & IFF_LOOPBACK) == 0) {
527702ff421SJavier Steinaker currentInterfaces.insert((BString)interface.Name());
5285c46b171SRene Gollent int32 oldStatus = kStatusUnknown;
5295c46b171SRene Gollent if (fInterfaceStatuses.find(interface.Name())
5305c46b171SRene Gollent != fInterfaceStatuses.end()) {
5315c46b171SRene Gollent oldStatus = fInterfaceStatuses[interface.Name()];
532f01106c3SAxel Dörfler }
5335c46b171SRene Gollent int32 status = _DetermineInterfaceStatus(interface);
5345c46b171SRene Gollent if (oldStatus != status) {
535b44d24c0SAlexander von Gluck IV BNotification notification(B_INFORMATION_NOTIFICATION);
536b44d24c0SAlexander von Gluck IV notification.SetGroup(B_TRANSLATE("Network Status"));
537b44d24c0SAlexander von Gluck IV notification.SetTitle(interface.Name());
538b44d24c0SAlexander von Gluck IV notification.SetMessageID(interface.Name());
5395c46b171SRene Gollent notification.SetIcon(fNotifyIcons[status]);
5405c46b171SRene Gollent if (status == kStatusConnecting
5415c46b171SRene Gollent || (status == kStatusReady
5425c46b171SRene Gollent && oldStatus == kStatusConnecting)
5435c46b171SRene Gollent || (status == kStatusNoLink
5445c46b171SRene Gollent && oldStatus == kStatusReady)
5455c46b171SRene Gollent || (status == kStatusNoLink
5465c46b171SRene Gollent && oldStatus == kStatusConnecting)) {
54743c68287SAlexander von Gluck IV // A significant state change, raise notification.
5485c46b171SRene Gollent notification.SetContent(kStatusDescriptions[status]);
549b44d24c0SAlexander von Gluck IV notification.Send();
550b44d24c0SAlexander von Gluck IV }
551f01106c3SAxel Dörfler Invalidate();
552f01106c3SAxel Dörfler }
5535c46b171SRene Gollent fInterfaceStatuses[interface.Name()] = status;
5545c46b171SRene Gollent }
5555c46b171SRene Gollent }
556702ff421SJavier Steinaker
557702ff421SJavier Steinaker // Check every element in fInterfaceStatuses against our current interface
558702ff421SJavier Steinaker // list. If it's not there, then the interface is not present anymore and
559702ff421SJavier Steinaker // should be removed from fInterfaceStatuses.
560702ff421SJavier Steinaker std::map<BString, int32>::iterator it = fInterfaceStatuses.begin();
561702ff421SJavier Steinaker while (it != fInterfaceStatuses.end()) {
562702ff421SJavier Steinaker std::map<BString, int32>::iterator backupIt = it;
563702ff421SJavier Steinaker if (currentInterfaces.find(it->first) == currentInterfaces.end())
564702ff421SJavier Steinaker fInterfaceStatuses.erase(it);
565702ff421SJavier Steinaker it = ++backupIt;
566702ff421SJavier Steinaker }
567b44d24c0SAlexander von Gluck IV }
568f01106c3SAxel Dörfler
569f01106c3SAxel Dörfler
5703b41ad86SStephan Aßmus void
_OpenNetworksPreferences()5713b41ad86SStephan Aßmus NetworkStatusView::_OpenNetworksPreferences()
5723b41ad86SStephan Aßmus {
573195981bbSAxel Dörfler status_t status = be_roster->Launch("application/x-vnd.Haiku-Network");
57446cac7f7SAlexandre Deckner if (status != B_OK && status != B_ALREADY_RUNNING) {
575757e7059SAdrien Destugues BString errorMessage(B_TRANSLATE("Launching the network preflet "
576757e7059SAdrien Destugues "failed.\n\nError: "));
577195981bbSAxel Dörfler errorMessage << strerror(status);
5783b41ad86SStephan Aßmus BAlert* alert = new BAlert("launch error", errorMessage.String(),
579757e7059SAdrien Destugues B_TRANSLATE("OK"));
580aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
581195981bbSAxel Dörfler
582195981bbSAxel Dörfler // asynchronous alert in order to not block replicant host application
5833b41ad86SStephan Aßmus alert->Go(NULL);
5843b41ad86SStephan Aßmus }
5853b41ad86SStephan Aßmus }
5863b41ad86SStephan Aßmus
5873b41ad86SStephan Aßmus
588f01106c3SAxel Dörfler // #pragma mark -
589f01106c3SAxel Dörfler
590f01106c3SAxel Dörfler
591f01106c3SAxel Dörfler extern "C" _EXPORT BView *
instantiate_deskbar_item(float maxWidth,float maxHeight)592efafab64SAxel Dörfler instantiate_deskbar_item(float maxWidth, float maxHeight)
593f01106c3SAxel Dörfler {
594efafab64SAxel Dörfler return new NetworkStatusView(BRect(0, 0, maxHeight - 1, maxHeight - 1),
59566eba86fSAxel Dörfler B_FOLLOW_LEFT | B_FOLLOW_TOP, true);
596f01106c3SAxel Dörfler }
597