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