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 <NetworkDevice.h> 415fe97f21SAxel Dörfler #include <NetworkInterface.h> 425fe97f21SAxel Dörfler #include <NetworkRoster.h> 43f01106c3SAxel Dörfler #include <PopUpMenu.h> 44f01106c3SAxel Dörfler #include <Resources.h> 45d5ba07a3SAxel Dörfler #include <Roster.h> 46f01106c3SAxel Dörfler #include <String.h> 47f01106c3SAxel Dörfler #include <TextView.h> 48f01106c3SAxel Dörfler 49195981bbSAxel Dörfler #include "NetworkStatus.h" 50195981bbSAxel Dörfler #include "NetworkStatusIcons.h" 515fe97f21SAxel Dörfler #include "RadioView.h" 523ca00ffdSAxel Dörfler #include "WirelessNetworkMenuItem.h" 53195981bbSAxel Dörfler 54f01106c3SAxel Dörfler 55546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT 56546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "NetworkStatusView" 57757e7059SAdrien Destugues 58757e7059SAdrien Destugues 59f01106c3SAxel Dörfler static const char *kStatusDescriptions[] = { 602ee8f3f6SSiarzhuk Zharski B_TRANSLATE("Unknown"), 612ee8f3f6SSiarzhuk Zharski B_TRANSLATE("No link"), 622ee8f3f6SSiarzhuk Zharski B_TRANSLATE("No stateful configuration"), 632ee8f3f6SSiarzhuk Zharski B_TRANSLATE("Configuring"), 642ee8f3f6SSiarzhuk Zharski B_TRANSLATE("Ready") 65f01106c3SAxel Dörfler }; 66f01106c3SAxel Dörfler 67efafab64SAxel Dörfler extern "C" _EXPORT BView *instantiate_deskbar_item(float maxWidth, float maxHeight); 68f01106c3SAxel Dörfler 69f01106c3SAxel Dörfler 70f01106c3SAxel Dörfler const uint32 kMsgShowConfiguration = 'shcf'; 71c1502c9aSStephan Aßmus const uint32 kMsgOpenNetworkPreferences = 'onwp'; 722e1a6286SAxel Dörfler const uint32 kMsgJoinNetwork = 'join'; 73f01106c3SAxel Dörfler 74f01106c3SAxel Dörfler const uint32 kMinIconWidth = 16; 75f01106c3SAxel Dörfler const uint32 kMinIconHeight = 16; 76f01106c3SAxel Dörfler 77195981bbSAxel Dörfler 78195981bbSAxel Dörfler // #pragma mark - 79f01106c3SAxel Dörfler 80f01106c3SAxel Dörfler 81aba4cb20SMichael Lotz static bool 82aba4cb20SMichael Lotz signal_strength_compare(const wireless_network &a, 83aba4cb20SMichael Lotz const wireless_network &b) 84aba4cb20SMichael Lotz { 85aba4cb20SMichael Lotz if (a.signal_strength == b.signal_strength) 86aba4cb20SMichael Lotz return strcmp(a.name, b.name) > 0; 87aba4cb20SMichael Lotz return a.signal_strength > b.signal_strength; 88aba4cb20SMichael Lotz } 89aba4cb20SMichael Lotz 90aba4cb20SMichael Lotz 91aba4cb20SMichael Lotz // #pragma mark - 92aba4cb20SMichael Lotz 93aba4cb20SMichael Lotz 94f01106c3SAxel Dörfler NetworkStatusView::NetworkStatusView(BRect frame, int32 resizingMode, 95f01106c3SAxel Dörfler bool inDeskbar) 96f01106c3SAxel Dörfler : BView(frame, kDeskbarItemName, resizingMode, 9747102c07SX512 B_WILL_DRAW | B_TRANSPARENT_BACKGROUND | B_FRAME_EVENTS), 985c46b171SRene Gollent fInDeskbar(inDeskbar) 99f01106c3SAxel Dörfler { 100f01106c3SAxel Dörfler _Init(); 101f01106c3SAxel Dörfler 102f01106c3SAxel Dörfler if (!inDeskbar) { 103f01106c3SAxel Dörfler // we were obviously added to a standard window - let's add a dragger 104f01106c3SAxel Dörfler frame.OffsetTo(B_ORIGIN); 105f01106c3SAxel Dörfler frame.top = frame.bottom - 7; 106f01106c3SAxel Dörfler frame.left = frame.right - 7; 107f01106c3SAxel Dörfler BDragger* dragger = new BDragger(frame, this, 108f01106c3SAxel Dörfler B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 109f01106c3SAxel Dörfler AddChild(dragger); 110f01106c3SAxel Dörfler } else 111f01106c3SAxel Dörfler _Update(); 112f01106c3SAxel Dörfler } 113f01106c3SAxel Dörfler 114f01106c3SAxel Dörfler 115f01106c3SAxel Dörfler NetworkStatusView::NetworkStatusView(BMessage* archive) 116d5ba07a3SAxel Dörfler : BView(archive), 117d5ba07a3SAxel Dörfler fInDeskbar(false) 118f01106c3SAxel Dörfler { 119d5ba07a3SAxel Dörfler app_info info; 120d5ba07a3SAxel Dörfler if (be_app->GetAppInfo(&info) == B_OK 121d5ba07a3SAxel Dörfler && !strcasecmp(info.signature, "application/x-vnd.Be-TSKB")) 122d5ba07a3SAxel Dörfler fInDeskbar = true; 123d5ba07a3SAxel Dörfler 124f01106c3SAxel Dörfler _Init(); 125f01106c3SAxel Dörfler } 126f01106c3SAxel Dörfler 127f01106c3SAxel Dörfler 128f01106c3SAxel Dörfler NetworkStatusView::~NetworkStatusView() 129f01106c3SAxel Dörfler { 130f01106c3SAxel Dörfler } 131f01106c3SAxel Dörfler 132f01106c3SAxel Dörfler 133f01106c3SAxel Dörfler void 134f01106c3SAxel Dörfler NetworkStatusView::_Init() 135f01106c3SAxel Dörfler { 136f01106c3SAxel Dörfler for (int i = 0; i < kStatusCount; i++) { 137e58807edSAlexander von Gluck IV fTrayIcons[i] = NULL; 138e58807edSAlexander von Gluck IV fNotifyIcons[i] = NULL; 139f01106c3SAxel Dörfler } 140f01106c3SAxel Dörfler 141f01106c3SAxel Dörfler _UpdateBitmaps(); 142f01106c3SAxel Dörfler } 143f01106c3SAxel Dörfler 144f01106c3SAxel Dörfler 145f01106c3SAxel Dörfler void 146f01106c3SAxel Dörfler NetworkStatusView::_UpdateBitmaps() 147f01106c3SAxel Dörfler { 148f01106c3SAxel Dörfler for (int i = 0; i < kStatusCount; i++) { 149e58807edSAlexander von Gluck IV delete fTrayIcons[i]; 150e58807edSAlexander von Gluck IV delete fNotifyIcons[i]; 151e58807edSAlexander von Gluck IV fTrayIcons[i] = NULL; 152e58807edSAlexander von Gluck IV fNotifyIcons[i] = NULL; 153f01106c3SAxel Dörfler } 154f01106c3SAxel Dörfler 155f01106c3SAxel Dörfler image_info info; 156f01106c3SAxel Dörfler if (our_image(info) != B_OK) 157f01106c3SAxel Dörfler return; 158f01106c3SAxel Dörfler 159f01106c3SAxel Dörfler BFile file(info.name, B_READ_ONLY); 160f01106c3SAxel Dörfler if (file.InitCheck() < B_OK) 161f01106c3SAxel Dörfler return; 162f01106c3SAxel Dörfler 163f01106c3SAxel Dörfler BResources resources(&file); 164f01106c3SAxel Dörfler #ifdef HAIKU_TARGET_PLATFORM_HAIKU 165f01106c3SAxel Dörfler if (resources.InitCheck() < B_OK) 166f01106c3SAxel Dörfler return; 167f01106c3SAxel Dörfler #endif 168f01106c3SAxel Dörfler 169f01106c3SAxel Dörfler for (int i = 0; i < kStatusCount; i++) { 170f01106c3SAxel Dörfler const void* data = NULL; 171f01106c3SAxel Dörfler size_t size; 172f01106c3SAxel Dörfler data = resources.LoadResource(B_VECTOR_ICON_TYPE, 173f01106c3SAxel Dörfler kNetworkStatusNoDevice + i, &size); 174f01106c3SAxel Dörfler if (data != NULL) { 175e58807edSAlexander von Gluck IV // Scale main tray icon 176e58807edSAlexander von Gluck IV BBitmap* trayIcon = new BBitmap(Bounds(), B_RGBA32); 177e58807edSAlexander von Gluck IV if (trayIcon->InitCheck() == B_OK 178f01106c3SAxel Dörfler && BIconUtils::GetVectorIcon((const uint8 *)data, 179e58807edSAlexander von Gluck IV size, trayIcon) == B_OK) { 180e58807edSAlexander von Gluck IV fTrayIcons[i] = trayIcon; 181f01106c3SAxel Dörfler } else 182e58807edSAlexander von Gluck IV delete trayIcon; 183e58807edSAlexander von Gluck IV 184e58807edSAlexander von Gluck IV // Scale notification icon 185e58807edSAlexander von Gluck IV BBitmap* notifyIcon = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32); 186e58807edSAlexander von Gluck IV if (notifyIcon->InitCheck() == B_OK 187e58807edSAlexander von Gluck IV && BIconUtils::GetVectorIcon((const uint8 *)data, 188e58807edSAlexander von Gluck IV size, notifyIcon) == B_OK) { 189e58807edSAlexander von Gluck IV fNotifyIcons[i] = notifyIcon; 190e58807edSAlexander von Gluck IV } else 191e58807edSAlexander von Gluck IV delete notifyIcon; 192f01106c3SAxel Dörfler } 193f01106c3SAxel Dörfler } 194f01106c3SAxel Dörfler } 195f01106c3SAxel Dörfler 196f01106c3SAxel Dörfler 197f01106c3SAxel Dörfler void 198f01106c3SAxel Dörfler NetworkStatusView::_Quit() 199f01106c3SAxel Dörfler { 200f01106c3SAxel Dörfler if (fInDeskbar) { 201f01106c3SAxel Dörfler BDeskbar deskbar; 202f01106c3SAxel Dörfler deskbar.RemoveItem(kDeskbarItemName); 203f01106c3SAxel Dörfler } else 204f01106c3SAxel Dörfler be_app->PostMessage(B_QUIT_REQUESTED); 205f01106c3SAxel Dörfler } 206f01106c3SAxel Dörfler 207f01106c3SAxel Dörfler 208f01106c3SAxel Dörfler NetworkStatusView* 209f01106c3SAxel Dörfler NetworkStatusView::Instantiate(BMessage* archive) 210f01106c3SAxel Dörfler { 211f01106c3SAxel Dörfler if (!validate_instantiation(archive, "NetworkStatusView")) 212f01106c3SAxel Dörfler return NULL; 213f01106c3SAxel Dörfler 214f01106c3SAxel Dörfler return new NetworkStatusView(archive); 215f01106c3SAxel Dörfler } 216f01106c3SAxel Dörfler 217f01106c3SAxel Dörfler 218f01106c3SAxel Dörfler status_t 219f01106c3SAxel Dörfler NetworkStatusView::Archive(BMessage* archive, bool deep) const 220f01106c3SAxel Dörfler { 221f01106c3SAxel Dörfler status_t status = BView::Archive(archive, deep); 222f01106c3SAxel Dörfler if (status == B_OK) 223f01106c3SAxel Dörfler status = archive->AddString("add_on", kSignature); 224f01106c3SAxel Dörfler if (status == B_OK) 225f01106c3SAxel Dörfler status = archive->AddString("class", "NetworkStatusView"); 226f01106c3SAxel Dörfler 227f01106c3SAxel Dörfler return status; 228f01106c3SAxel Dörfler } 229f01106c3SAxel Dörfler 230f01106c3SAxel Dörfler 231f01106c3SAxel Dörfler void 232f01106c3SAxel Dörfler NetworkStatusView::AttachedToWindow() 233f01106c3SAxel Dörfler { 234f01106c3SAxel Dörfler BView::AttachedToWindow(); 235f01106c3SAxel Dörfler 236485a9ea0SX512 SetViewColor(B_TRANSPARENT_COLOR); 237f01106c3SAxel Dörfler 238195981bbSAxel Dörfler start_watching_network( 239195981bbSAxel Dörfler B_WATCH_NETWORK_INTERFACE_CHANGES | B_WATCH_NETWORK_LINK_CHANGES, this); 240f01106c3SAxel Dörfler 241f01106c3SAxel Dörfler _Update(); 242f01106c3SAxel Dörfler } 243f01106c3SAxel Dörfler 244f01106c3SAxel Dörfler 245f01106c3SAxel Dörfler void 246f01106c3SAxel Dörfler NetworkStatusView::DetachedFromWindow() 247f01106c3SAxel Dörfler { 248195981bbSAxel Dörfler stop_watching_network(this); 249f01106c3SAxel Dörfler } 250f01106c3SAxel Dörfler 251f01106c3SAxel Dörfler 252f01106c3SAxel Dörfler void 253f01106c3SAxel Dörfler NetworkStatusView::MessageReceived(BMessage* message) 254f01106c3SAxel Dörfler { 255f01106c3SAxel Dörfler switch (message->what) { 256195981bbSAxel Dörfler case B_NETWORK_MONITOR: 257f01106c3SAxel Dörfler _Update(); 258f01106c3SAxel Dörfler break; 259f01106c3SAxel Dörfler 260f01106c3SAxel Dörfler case kMsgShowConfiguration: 261f01106c3SAxel Dörfler _ShowConfiguration(message); 262f01106c3SAxel Dörfler break; 263f01106c3SAxel Dörfler 264c1502c9aSStephan Aßmus case kMsgOpenNetworkPreferences: 2653b41ad86SStephan Aßmus _OpenNetworksPreferences(); 2663b41ad86SStephan Aßmus break; 2673b41ad86SStephan Aßmus 2682e1a6286SAxel Dörfler case kMsgJoinNetwork: 2692e1a6286SAxel Dörfler { 2702e1a6286SAxel Dörfler const char* deviceName; 2712e1a6286SAxel Dörfler const char* name; 2726c7caf44SAxel Dörfler BNetworkAddress address; 2732e1a6286SAxel Dörfler if (message->FindString("device", &deviceName) == B_OK 2746c7caf44SAxel Dörfler && message->FindString("name", &name) == B_OK 2756c7caf44SAxel Dörfler && message->FindFlat("address", &address) == B_OK) { 2762e1a6286SAxel Dörfler BNetworkDevice device(deviceName); 2776c7caf44SAxel Dörfler status_t status = device.JoinNetwork(address); 2782e1a6286SAxel Dörfler if (status != B_OK) { 2792e1a6286SAxel Dörfler BString text 2802e1a6286SAxel Dörfler = B_TRANSLATE("Could not join wireless network:\n"); 2812e1a6286SAxel Dörfler text << strerror(status); 2822e1a6286SAxel Dörfler BAlert* alert = new BAlert(name, text.String(), 2832e1a6286SAxel Dörfler B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, 2842e1a6286SAxel Dörfler B_STOP_ALERT); 285aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 2862e1a6286SAxel Dörfler alert->Go(NULL); 2872e1a6286SAxel Dörfler } 2882e1a6286SAxel Dörfler } 2892e1a6286SAxel Dörfler break; 2902e1a6286SAxel Dörfler } 2912e1a6286SAxel Dörfler 292f01106c3SAxel Dörfler case B_ABOUT_REQUESTED: 293f01106c3SAxel Dörfler _AboutRequested(); 294f01106c3SAxel Dörfler break; 295f01106c3SAxel Dörfler 296f01106c3SAxel Dörfler case B_QUIT_REQUESTED: 297f01106c3SAxel Dörfler _Quit(); 298f01106c3SAxel Dörfler break; 299f01106c3SAxel Dörfler 300f01106c3SAxel Dörfler default: 301f01106c3SAxel Dörfler BView::MessageReceived(message); 302ab05d368Ssushilhub break; 303f01106c3SAxel Dörfler } 304f01106c3SAxel Dörfler } 305f01106c3SAxel Dörfler 306f01106c3SAxel Dörfler 307f01106c3SAxel Dörfler void 308f01106c3SAxel Dörfler NetworkStatusView::FrameResized(float width, float height) 309f01106c3SAxel Dörfler { 310f01106c3SAxel Dörfler _UpdateBitmaps(); 311d5ba07a3SAxel Dörfler Invalidate(); 312f01106c3SAxel Dörfler } 313f01106c3SAxel Dörfler 314f01106c3SAxel Dörfler 315f01106c3SAxel Dörfler void 316f01106c3SAxel Dörfler NetworkStatusView::Draw(BRect updateRect) 317f01106c3SAxel Dörfler { 3185c46b171SRene Gollent int32 status = kStatusUnknown; 3195c46b171SRene Gollent for (std::map<BString, int32>::const_iterator it 3205c46b171SRene Gollent = fInterfaceStatuses.begin(); it != fInterfaceStatuses.end(); ++it) { 3215c46b171SRene Gollent if (it->second > status) 3225c46b171SRene Gollent status = it->second; 3235c46b171SRene Gollent } 3245c46b171SRene Gollent 3255c46b171SRene Gollent if (fTrayIcons[status] == NULL) 326f01106c3SAxel Dörfler return; 327f01106c3SAxel Dörfler 328f01106c3SAxel Dörfler SetDrawingMode(B_OP_ALPHA); 3295c46b171SRene Gollent DrawBitmap(fTrayIcons[status]); 330f01106c3SAxel Dörfler SetDrawingMode(B_OP_COPY); 331f01106c3SAxel Dörfler } 332f01106c3SAxel Dörfler 333f01106c3SAxel Dörfler 334f01106c3SAxel Dörfler void 335f01106c3SAxel Dörfler NetworkStatusView::_ShowConfiguration(BMessage* message) 336f01106c3SAxel Dörfler { 337f01106c3SAxel Dörfler const char* name; 338f01106c3SAxel Dörfler if (message->FindString("interface", &name) != B_OK) 339f01106c3SAxel Dörfler return; 340f01106c3SAxel Dörfler 3418897f278SStefano Ceccherini BNetworkInterface networkInterface(name); 3428897f278SStefano Ceccherini if (!networkInterface.Exists()) 343f01106c3SAxel Dörfler return; 344f01106c3SAxel Dörfler 3452ee8f3f6SSiarzhuk Zharski BString text(B_TRANSLATE("%ifaceName information:\n")); 3462ee8f3f6SSiarzhuk Zharski text.ReplaceFirst("%ifaceName", name); 347757e7059SAdrien Destugues 348f01106c3SAxel Dörfler size_t boldLength = text.Length(); 349f01106c3SAxel Dörfler 350b81d67edSJeremy Visser int32 numAddrs = networkInterface.CountAddresses(); 351b81d67edSJeremy Visser for (int32 i = 0; i < numAddrs; i++) { 352b81d67edSJeremy Visser BNetworkInterfaceAddress address; 353b81d67edSJeremy Visser networkInterface.GetAddressAt(i, address); 354b81d67edSJeremy Visser switch (address.Address().Family()) { 355b81d67edSJeremy Visser case AF_INET: 356b81d67edSJeremy Visser text << "\n" << B_TRANSLATE("IPv4 Address: ") 357b81d67edSJeremy Visser << address.Address().ToString() 358b81d67edSJeremy Visser << "\n" << B_TRANSLATE("Broadcast: ") 359b81d67edSJeremy Visser << address.Broadcast().ToString() 360b81d67edSJeremy Visser << "\n" << B_TRANSLATE("Netmask: ") 361b81d67edSJeremy Visser << address.Mask().ToString() 362b81d67edSJeremy Visser << "\n"; 363b81d67edSJeremy Visser break; 364b81d67edSJeremy Visser case AF_INET6: 365b81d67edSJeremy Visser text << "\n" << B_TRANSLATE("IPv6 Address: ") 366*96fbe0f7SAdrien Destugues << address.Address().ToString() 367*96fbe0f7SAdrien Destugues << "/" << address.Mask().PrefixLength() 368b81d67edSJeremy Visser << "\n"; 369b81d67edSJeremy Visser break; 370b81d67edSJeremy Visser default: 371b81d67edSJeremy Visser break; 372b81d67edSJeremy Visser } 373b81d67edSJeremy Visser } 374f01106c3SAxel Dörfler 375757e7059SAdrien Destugues BAlert* alert = new BAlert(name, text.String(), B_TRANSLATE("OK")); 376aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 377f01106c3SAxel Dörfler BTextView* view = alert->TextView(); 378f01106c3SAxel Dörfler BFont font; 379f01106c3SAxel Dörfler 380f01106c3SAxel Dörfler view->SetStylable(true); 381f01106c3SAxel Dörfler view->GetFont(&font); 382f01106c3SAxel Dörfler font.SetFace(B_BOLD_FACE); 383f01106c3SAxel Dörfler view->SetFontAndColor(0, boldLength, &font); 384f01106c3SAxel Dörfler 385f01106c3SAxel Dörfler alert->Go(NULL); 386f01106c3SAxel Dörfler } 387f01106c3SAxel Dörfler 388f01106c3SAxel Dörfler 389f01106c3SAxel Dörfler void 390f01106c3SAxel Dörfler NetworkStatusView::MouseDown(BPoint point) 391f01106c3SAxel Dörfler { 392f01106c3SAxel Dörfler BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING, false, false); 393a31688d2SAxel Dörfler menu->SetAsyncAutoDestruct(true); 394f01106c3SAxel Dörfler menu->SetFont(be_plain_font); 3955c46b171SRene Gollent BString wifiInterface; 3965c46b171SRene Gollent BNetworkDevice wifiDevice; 397f01106c3SAxel Dörfler 3985fe97f21SAxel Dörfler // Add interfaces 3995fe97f21SAxel Dörfler 4005c46b171SRene Gollent for (std::map<BString, int32>::const_iterator it 4015c46b171SRene Gollent = fInterfaceStatuses.begin(); it != fInterfaceStatuses.end(); ++it) { 4025c46b171SRene Gollent const BString& name = it->first; 403f01106c3SAxel Dörfler 404f01106c3SAxel Dörfler BString label = name; 405f01106c3SAxel Dörfler label += ": "; 406f01106c3SAxel Dörfler label += kStatusDescriptions[ 407f01106c3SAxel Dörfler _DetermineInterfaceStatus(name.String())]; 408f01106c3SAxel Dörfler 409f01106c3SAxel Dörfler BMessage* info = new BMessage(kMsgShowConfiguration); 410f01106c3SAxel Dörfler info->AddString("interface", name.String()); 411f01106c3SAxel Dörfler menu->AddItem(new BMenuItem(label.String(), info)); 4125c46b171SRene Gollent 4135c46b171SRene Gollent // We only show the networks of the first wireless device we find. 4145c46b171SRene Gollent if (wifiInterface.IsEmpty()) { 4155c46b171SRene Gollent wifiDevice.SetTo(name); 4165c46b171SRene Gollent if (wifiDevice.IsWireless()) 4175c46b171SRene Gollent wifiInterface = name; 4185c46b171SRene Gollent } 419f01106c3SAxel Dörfler } 420f01106c3SAxel Dörfler 4215c46b171SRene Gollent if (!fInterfaceStatuses.empty()) 422f01106c3SAxel Dörfler menu->AddSeparatorItem(); 4235fe97f21SAxel Dörfler 4245fe97f21SAxel Dörfler // Add wireless networks, if any 4255fe97f21SAxel Dörfler 4265c46b171SRene Gollent if (!wifiInterface.IsEmpty()) { 427440d0e61SAxel Dörfler std::set<BNetworkAddress> associated; 428440d0e61SAxel Dörfler BNetworkAddress address; 429440d0e61SAxel Dörfler uint32 cookie = 0; 4305c46b171SRene Gollent while (wifiDevice.GetNextAssociatedNetwork(cookie, address) == B_OK) 431440d0e61SAxel Dörfler associated.insert(address); 432440d0e61SAxel Dörfler 433440d0e61SAxel Dörfler cookie = 0; 434aba4cb20SMichael Lotz wireless_network network; 435aba4cb20SMichael Lotz typedef std::vector<wireless_network> WirelessNetworkVector; 436aba4cb20SMichael Lotz WirelessNetworkVector wirelessNetworks; 437aba4cb20SMichael Lotz while (wifiDevice.GetNextNetwork(cookie, network) == B_OK) 438aba4cb20SMichael Lotz wirelessNetworks.push_back(network); 439aba4cb20SMichael Lotz 440aba4cb20SMichael Lotz std::sort(wirelessNetworks.begin(), wirelessNetworks.end(), 441aba4cb20SMichael Lotz signal_strength_compare); 442aba4cb20SMichael Lotz 443aba4cb20SMichael Lotz int32 count = 0; 444aba4cb20SMichael Lotz for (WirelessNetworkVector::iterator it = wirelessNetworks.begin(); 445aba4cb20SMichael Lotz it != wirelessNetworks.end(); it++) { 446aba4cb20SMichael Lotz wireless_network &network = *it; 447aba4cb20SMichael Lotz 4482e1a6286SAxel Dörfler BMessage* message = new BMessage(kMsgJoinNetwork); 4495c46b171SRene Gollent message->AddString("device", wifiInterface); 4502e1a6286SAxel Dörfler message->AddString("name", network.name); 4516c7caf44SAxel Dörfler message->AddFlat("address", &network.address); 4522e1a6286SAxel Dörfler 453440d0e61SAxel Dörfler BMenuItem* item = new WirelessNetworkMenuItem(network.name, 4545bb799c2SPrzemysław Buczkowski network.signal_strength, network.authentication_mode, message); 455440d0e61SAxel Dörfler menu->AddItem(item); 456440d0e61SAxel Dörfler if (associated.find(network.address) != associated.end()) 457440d0e61SAxel Dörfler item->SetMarked(true); 458440d0e61SAxel Dörfler 4595fe97f21SAxel Dörfler count++; 4605fe97f21SAxel Dörfler } 4615fe97f21SAxel Dörfler if (count == 0) { 4625fe97f21SAxel Dörfler BMenuItem* item = new BMenuItem( 4635fe97f21SAxel Dörfler B_TRANSLATE("<no wireless networks found>"), NULL); 4645fe97f21SAxel Dörfler item->SetEnabled(false); 4655fe97f21SAxel Dörfler menu->AddItem(item); 4665fe97f21SAxel Dörfler } 4675fe97f21SAxel Dörfler menu->AddSeparatorItem(); 4685fe97f21SAxel Dörfler } 4695fe97f21SAxel Dörfler 470757e7059SAdrien Destugues menu->AddItem(new BMenuItem(B_TRANSLATE( 471757e7059SAdrien Destugues "Open network preferences" B_UTF8_ELLIPSIS), 472c1502c9aSStephan Aßmus new BMessage(kMsgOpenNetworkPreferences))); 4733b41ad86SStephan Aßmus 4745fe97f21SAxel Dörfler if (fInDeskbar) { 475757e7059SAdrien Destugues menu->AddItem(new BMenuItem(B_TRANSLATE("Quit"), 476757e7059SAdrien Destugues new BMessage(B_QUIT_REQUESTED))); 4775fe97f21SAxel Dörfler } 478f01106c3SAxel Dörfler menu->SetTargetForItems(this); 479f01106c3SAxel Dörfler 480f01106c3SAxel Dörfler ConvertToScreen(&point); 481a31688d2SAxel Dörfler menu->Go(point, true, true, true); 482f01106c3SAxel Dörfler } 483f01106c3SAxel Dörfler 484f01106c3SAxel Dörfler 485f01106c3SAxel Dörfler void 486f01106c3SAxel Dörfler NetworkStatusView::_AboutRequested() 487f01106c3SAxel Dörfler { 48831535ac6SAdrien Destugues BAboutWindow* window = new BAboutWindow( 48931535ac6SAdrien Destugues B_TRANSLATE_SYSTEM_NAME("NetworkStatus"), kSignature); 490fd19c736SAdrien Destugues 491730a45eeSJohn Scipione const char* authors[] = { 492730a45eeSJohn Scipione "Axel Dörfler", 493730a45eeSJohn Scipione "Hugo Santos", 494730a45eeSJohn Scipione NULL 495730a45eeSJohn Scipione }; 496f01106c3SAxel Dörfler 497fd19c736SAdrien Destugues window->AddCopyright(2007, "Haiku, Inc."); 498fd19c736SAdrien Destugues window->AddAuthors(authors); 499fd19c736SAdrien Destugues 500fd19c736SAdrien Destugues window->Show(); 501f01106c3SAxel Dörfler } 502f01106c3SAxel Dörfler 503f01106c3SAxel Dörfler 504f01106c3SAxel Dörfler int32 5055c46b171SRene Gollent NetworkStatusView::_DetermineInterfaceStatus( 5065c46b171SRene Gollent const BNetworkInterface& interface) 507f01106c3SAxel Dörfler { 5085fe97f21SAxel Dörfler uint32 flags = interface.Flags(); 509f01106c3SAxel Dörfler 510cb7833c7SPhilippe Houdoin if ((flags & IFF_LINK) == 0) 511cb7833c7SPhilippe Houdoin return kStatusNoLink; 512cb7833c7SPhilippe Houdoin if ((flags & (IFF_UP | IFF_LINK | IFF_CONFIGURING)) == IFF_LINK) 513cb7833c7SPhilippe Houdoin return kStatusLinkNoConfig; 5144a531db1SPhilippe Houdoin if ((flags & IFF_CONFIGURING) == IFF_CONFIGURING) 515cb7833c7SPhilippe Houdoin return kStatusConnecting; 516cb7833c7SPhilippe Houdoin if ((flags & (IFF_UP | IFF_LINK)) == (IFF_UP | IFF_LINK)) 517cb7833c7SPhilippe Houdoin return kStatusReady; 518f01106c3SAxel Dörfler 519cb7833c7SPhilippe Houdoin return kStatusUnknown; 520f01106c3SAxel Dörfler } 521f01106c3SAxel Dörfler 522f01106c3SAxel Dörfler 523f01106c3SAxel Dörfler void 524f01106c3SAxel Dörfler NetworkStatusView::_Update(bool force) 525f01106c3SAxel Dörfler { 5265fe97f21SAxel Dörfler BNetworkRoster& roster = BNetworkRoster::Default(); 5275fe97f21SAxel Dörfler BNetworkInterface interface; 5285fe97f21SAxel Dörfler uint32 cookie = 0; 5295fe97f21SAxel Dörfler 5305fe97f21SAxel Dörfler while (roster.GetNextInterface(&cookie, interface) == B_OK) { 5315fe97f21SAxel Dörfler if ((interface.Flags() & IFF_LOOPBACK) == 0) { 5325c46b171SRene Gollent int32 oldStatus = kStatusUnknown; 5335c46b171SRene Gollent if (fInterfaceStatuses.find(interface.Name()) 5345c46b171SRene Gollent != fInterfaceStatuses.end()) { 5355c46b171SRene Gollent oldStatus = fInterfaceStatuses[interface.Name()]; 536f01106c3SAxel Dörfler } 5375c46b171SRene Gollent int32 status = _DetermineInterfaceStatus(interface); 5385c46b171SRene Gollent if (oldStatus != status) { 539b44d24c0SAlexander von Gluck IV BNotification notification(B_INFORMATION_NOTIFICATION); 540b44d24c0SAlexander von Gluck IV notification.SetGroup(B_TRANSLATE("Network Status")); 541b44d24c0SAlexander von Gluck IV notification.SetTitle(interface.Name()); 542b44d24c0SAlexander von Gluck IV notification.SetMessageID(interface.Name()); 5435c46b171SRene Gollent notification.SetIcon(fNotifyIcons[status]); 5445c46b171SRene Gollent if (status == kStatusConnecting 5455c46b171SRene Gollent || (status == kStatusReady 5465c46b171SRene Gollent && oldStatus == kStatusConnecting) 5475c46b171SRene Gollent || (status == kStatusNoLink 5485c46b171SRene Gollent && oldStatus == kStatusReady) 5495c46b171SRene Gollent || (status == kStatusNoLink 5505c46b171SRene Gollent && oldStatus == kStatusConnecting)) { 55143c68287SAlexander von Gluck IV // A significant state change, raise notification. 5525c46b171SRene Gollent notification.SetContent(kStatusDescriptions[status]); 553b44d24c0SAlexander von Gluck IV notification.Send(); 554b44d24c0SAlexander von Gluck IV } 555f01106c3SAxel Dörfler Invalidate(); 556f01106c3SAxel Dörfler } 5575c46b171SRene Gollent fInterfaceStatuses[interface.Name()] = status; 5585c46b171SRene Gollent } 5595c46b171SRene Gollent } 560b44d24c0SAlexander von Gluck IV } 561f01106c3SAxel Dörfler 562f01106c3SAxel Dörfler 5633b41ad86SStephan Aßmus void 5643b41ad86SStephan Aßmus NetworkStatusView::_OpenNetworksPreferences() 5653b41ad86SStephan Aßmus { 566195981bbSAxel Dörfler status_t status = be_roster->Launch("application/x-vnd.Haiku-Network"); 56746cac7f7SAlexandre Deckner if (status != B_OK && status != B_ALREADY_RUNNING) { 568757e7059SAdrien Destugues BString errorMessage(B_TRANSLATE("Launching the network preflet " 569757e7059SAdrien Destugues "failed.\n\nError: ")); 570195981bbSAxel Dörfler errorMessage << strerror(status); 5713b41ad86SStephan Aßmus BAlert* alert = new BAlert("launch error", errorMessage.String(), 572757e7059SAdrien Destugues B_TRANSLATE("OK")); 573aed35104SHumdinger alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 574195981bbSAxel Dörfler 575195981bbSAxel Dörfler // asynchronous alert in order to not block replicant host application 5763b41ad86SStephan Aßmus alert->Go(NULL); 5773b41ad86SStephan Aßmus } 5783b41ad86SStephan Aßmus } 5793b41ad86SStephan Aßmus 5803b41ad86SStephan Aßmus 581f01106c3SAxel Dörfler // #pragma mark - 582f01106c3SAxel Dörfler 583f01106c3SAxel Dörfler 584f01106c3SAxel Dörfler extern "C" _EXPORT BView * 585efafab64SAxel Dörfler instantiate_deskbar_item(float maxWidth, float maxHeight) 586f01106c3SAxel Dörfler { 587efafab64SAxel Dörfler return new NetworkStatusView(BRect(0, 0, maxHeight - 1, maxHeight - 1), 58866eba86fSAxel Dörfler B_FOLLOW_LEFT | B_FOLLOW_TOP, true); 589f01106c3SAxel Dörfler } 590