1f01106c3SAxel Dörfler /* 25c46b171SRene Gollent * Copyright 2006-2012, 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> 21195981bbSAxel Dörfler #include <string.h> 22195981bbSAxel Dörfler #include <sys/socket.h> 23195981bbSAxel Dörfler #include <sys/sockio.h> 24195981bbSAxel Dörfler #include <unistd.h> 25f01106c3SAxel Dörfler 26f01106c3SAxel Dörfler #include <Alert.h> 27f01106c3SAxel Dörfler #include <Application.h> 28757e7059SAdrien Destugues #include <Catalog.h> 29f01106c3SAxel Dörfler #include <Bitmap.h> 30f01106c3SAxel Dörfler #include <Deskbar.h> 31f01106c3SAxel Dörfler #include <Dragger.h> 32f01106c3SAxel Dörfler #include <Drivers.h> 33f01106c3SAxel Dörfler #include <IconUtils.h> 34757e7059SAdrien Destugues #include <Locale.h> 35f01106c3SAxel Dörfler #include <MenuItem.h> 36f01106c3SAxel Dörfler #include <MessageRunner.h> 375fe97f21SAxel Dörfler #include <NetworkDevice.h> 385fe97f21SAxel Dörfler #include <NetworkInterface.h> 395fe97f21SAxel Dörfler #include <NetworkRoster.h> 40f01106c3SAxel Dörfler #include <PopUpMenu.h> 41f01106c3SAxel Dörfler #include <Resources.h> 42d5ba07a3SAxel Dörfler #include <Roster.h> 43f01106c3SAxel Dörfler #include <String.h> 44f01106c3SAxel Dörfler #include <TextView.h> 45f01106c3SAxel Dörfler 46195981bbSAxel Dörfler #include "NetworkStatus.h" 47195981bbSAxel Dörfler #include "NetworkStatusIcons.h" 485fe97f21SAxel Dörfler #include "RadioView.h" 493ca00ffdSAxel Dörfler #include "WirelessNetworkMenuItem.h" 50195981bbSAxel Dörfler 51f01106c3SAxel Dörfler 52*546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT 53*546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "NetworkStatusView" 54757e7059SAdrien Destugues 55757e7059SAdrien Destugues 56f01106c3SAxel Dörfler static const char *kStatusDescriptions[] = { 572ee8f3f6SSiarzhuk Zharski B_TRANSLATE("Unknown"), 582ee8f3f6SSiarzhuk Zharski B_TRANSLATE("No link"), 592ee8f3f6SSiarzhuk Zharski B_TRANSLATE("No stateful configuration"), 602ee8f3f6SSiarzhuk Zharski B_TRANSLATE("Configuring"), 612ee8f3f6SSiarzhuk Zharski B_TRANSLATE("Ready") 62f01106c3SAxel Dörfler }; 63f01106c3SAxel Dörfler 64f01106c3SAxel Dörfler extern "C" _EXPORT BView *instantiate_deskbar_item(void); 65f01106c3SAxel Dörfler 66f01106c3SAxel Dörfler 67f01106c3SAxel Dörfler const uint32 kMsgShowConfiguration = 'shcf'; 68c1502c9aSStephan Aßmus const uint32 kMsgOpenNetworkPreferences = 'onwp'; 692e1a6286SAxel Dörfler const uint32 kMsgJoinNetwork = 'join'; 70f01106c3SAxel Dörfler 71f01106c3SAxel Dörfler const uint32 kMinIconWidth = 16; 72f01106c3SAxel Dörfler const uint32 kMinIconHeight = 16; 73f01106c3SAxel Dörfler 74195981bbSAxel Dörfler 75195981bbSAxel Dörfler class SocketOpener { 76195981bbSAxel Dörfler public: 77195981bbSAxel Dörfler SocketOpener() 78195981bbSAxel Dörfler { 79195981bbSAxel Dörfler fSocket = socket(AF_INET, SOCK_DGRAM, 0); 80195981bbSAxel Dörfler } 81195981bbSAxel Dörfler 82195981bbSAxel Dörfler ~SocketOpener() 83195981bbSAxel Dörfler { 84195981bbSAxel Dörfler close(fSocket); 85195981bbSAxel Dörfler } 86195981bbSAxel Dörfler 87195981bbSAxel Dörfler status_t InitCheck() 88195981bbSAxel Dörfler { 89195981bbSAxel Dörfler return fSocket >= 0 ? B_OK : B_ERROR; 90195981bbSAxel Dörfler } 91195981bbSAxel Dörfler 92195981bbSAxel Dörfler operator int() const 93195981bbSAxel Dörfler { 94195981bbSAxel Dörfler return fSocket; 95195981bbSAxel Dörfler } 96195981bbSAxel Dörfler 97195981bbSAxel Dörfler private: 98195981bbSAxel Dörfler int fSocket; 99195981bbSAxel Dörfler }; 100195981bbSAxel Dörfler 101195981bbSAxel Dörfler 102195981bbSAxel Dörfler // #pragma mark - 103f01106c3SAxel Dörfler 104f01106c3SAxel Dörfler 105f01106c3SAxel Dörfler NetworkStatusView::NetworkStatusView(BRect frame, int32 resizingMode, 106f01106c3SAxel Dörfler bool inDeskbar) 107f01106c3SAxel Dörfler : BView(frame, kDeskbarItemName, resizingMode, 108d5ba07a3SAxel Dörfler B_WILL_DRAW | B_FRAME_EVENTS), 1095c46b171SRene Gollent fInDeskbar(inDeskbar) 110f01106c3SAxel Dörfler { 111f01106c3SAxel Dörfler _Init(); 112f01106c3SAxel Dörfler 113f01106c3SAxel Dörfler if (!inDeskbar) { 114f01106c3SAxel Dörfler // we were obviously added to a standard window - let's add a dragger 115f01106c3SAxel Dörfler frame.OffsetTo(B_ORIGIN); 116f01106c3SAxel Dörfler frame.top = frame.bottom - 7; 117f01106c3SAxel Dörfler frame.left = frame.right - 7; 118f01106c3SAxel Dörfler BDragger* dragger = new BDragger(frame, this, 119f01106c3SAxel Dörfler B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 120f01106c3SAxel Dörfler AddChild(dragger); 121f01106c3SAxel Dörfler } else 122f01106c3SAxel Dörfler _Update(); 123f01106c3SAxel Dörfler } 124f01106c3SAxel Dörfler 125f01106c3SAxel Dörfler 126f01106c3SAxel Dörfler NetworkStatusView::NetworkStatusView(BMessage* archive) 127d5ba07a3SAxel Dörfler : BView(archive), 128d5ba07a3SAxel Dörfler fInDeskbar(false) 129f01106c3SAxel Dörfler { 130d5ba07a3SAxel Dörfler app_info info; 131d5ba07a3SAxel Dörfler if (be_app->GetAppInfo(&info) == B_OK 132d5ba07a3SAxel Dörfler && !strcasecmp(info.signature, "application/x-vnd.Be-TSKB")) 133d5ba07a3SAxel Dörfler fInDeskbar = true; 134d5ba07a3SAxel Dörfler 135f01106c3SAxel Dörfler _Init(); 136f01106c3SAxel Dörfler } 137f01106c3SAxel Dörfler 138f01106c3SAxel Dörfler 139f01106c3SAxel Dörfler NetworkStatusView::~NetworkStatusView() 140f01106c3SAxel Dörfler { 141f01106c3SAxel Dörfler } 142f01106c3SAxel Dörfler 143f01106c3SAxel Dörfler 144f01106c3SAxel Dörfler void 145f01106c3SAxel Dörfler NetworkStatusView::_Init() 146f01106c3SAxel Dörfler { 147f01106c3SAxel Dörfler for (int i = 0; i < kStatusCount; i++) { 148e58807edSAlexander von Gluck IV fTrayIcons[i] = NULL; 149e58807edSAlexander von Gluck IV fNotifyIcons[i] = NULL; 150f01106c3SAxel Dörfler } 151f01106c3SAxel Dörfler 152f01106c3SAxel Dörfler _UpdateBitmaps(); 153f01106c3SAxel Dörfler } 154f01106c3SAxel Dörfler 155f01106c3SAxel Dörfler 156f01106c3SAxel Dörfler void 157f01106c3SAxel Dörfler NetworkStatusView::_UpdateBitmaps() 158f01106c3SAxel Dörfler { 159f01106c3SAxel Dörfler for (int i = 0; i < kStatusCount; i++) { 160e58807edSAlexander von Gluck IV delete fTrayIcons[i]; 161e58807edSAlexander von Gluck IV delete fNotifyIcons[i]; 162e58807edSAlexander von Gluck IV fTrayIcons[i] = NULL; 163e58807edSAlexander von Gluck IV fNotifyIcons[i] = NULL; 164f01106c3SAxel Dörfler } 165f01106c3SAxel Dörfler 166f01106c3SAxel Dörfler image_info info; 167f01106c3SAxel Dörfler if (our_image(info) != B_OK) 168f01106c3SAxel Dörfler return; 169f01106c3SAxel Dörfler 170f01106c3SAxel Dörfler BFile file(info.name, B_READ_ONLY); 171f01106c3SAxel Dörfler if (file.InitCheck() < B_OK) 172f01106c3SAxel Dörfler return; 173f01106c3SAxel Dörfler 174f01106c3SAxel Dörfler BResources resources(&file); 175f01106c3SAxel Dörfler #ifdef HAIKU_TARGET_PLATFORM_HAIKU 176f01106c3SAxel Dörfler if (resources.InitCheck() < B_OK) 177f01106c3SAxel Dörfler return; 178f01106c3SAxel Dörfler #endif 179f01106c3SAxel Dörfler 180f01106c3SAxel Dörfler for (int i = 0; i < kStatusCount; i++) { 181f01106c3SAxel Dörfler const void* data = NULL; 182f01106c3SAxel Dörfler size_t size; 183f01106c3SAxel Dörfler data = resources.LoadResource(B_VECTOR_ICON_TYPE, 184f01106c3SAxel Dörfler kNetworkStatusNoDevice + i, &size); 185f01106c3SAxel Dörfler if (data != NULL) { 186e58807edSAlexander von Gluck IV // Scale main tray icon 187e58807edSAlexander von Gluck IV BBitmap* trayIcon = new BBitmap(Bounds(), B_RGBA32); 188e58807edSAlexander von Gluck IV if (trayIcon->InitCheck() == B_OK 189f01106c3SAxel Dörfler && BIconUtils::GetVectorIcon((const uint8 *)data, 190e58807edSAlexander von Gluck IV size, trayIcon) == B_OK) { 191e58807edSAlexander von Gluck IV fTrayIcons[i] = trayIcon; 192f01106c3SAxel Dörfler } else 193e58807edSAlexander von Gluck IV delete trayIcon; 194e58807edSAlexander von Gluck IV 195e58807edSAlexander von Gluck IV // Scale notification icon 196e58807edSAlexander von Gluck IV BBitmap* notifyIcon = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32); 197e58807edSAlexander von Gluck IV if (notifyIcon->InitCheck() == B_OK 198e58807edSAlexander von Gluck IV && BIconUtils::GetVectorIcon((const uint8 *)data, 199e58807edSAlexander von Gluck IV size, notifyIcon) == B_OK) { 200e58807edSAlexander von Gluck IV fNotifyIcons[i] = notifyIcon; 201e58807edSAlexander von Gluck IV } else 202e58807edSAlexander von Gluck IV delete notifyIcon; 203f01106c3SAxel Dörfler } 204f01106c3SAxel Dörfler } 205f01106c3SAxel Dörfler } 206f01106c3SAxel Dörfler 207f01106c3SAxel Dörfler 208f01106c3SAxel Dörfler void 209f01106c3SAxel Dörfler NetworkStatusView::_Quit() 210f01106c3SAxel Dörfler { 211f01106c3SAxel Dörfler if (fInDeskbar) { 212f01106c3SAxel Dörfler BDeskbar deskbar; 213f01106c3SAxel Dörfler deskbar.RemoveItem(kDeskbarItemName); 214f01106c3SAxel Dörfler } else 215f01106c3SAxel Dörfler be_app->PostMessage(B_QUIT_REQUESTED); 216f01106c3SAxel Dörfler } 217f01106c3SAxel Dörfler 218f01106c3SAxel Dörfler 219f01106c3SAxel Dörfler NetworkStatusView * 220f01106c3SAxel Dörfler NetworkStatusView::Instantiate(BMessage* archive) 221f01106c3SAxel Dörfler { 222f01106c3SAxel Dörfler if (!validate_instantiation(archive, "NetworkStatusView")) 223f01106c3SAxel Dörfler return NULL; 224f01106c3SAxel Dörfler 225f01106c3SAxel Dörfler return new NetworkStatusView(archive); 226f01106c3SAxel Dörfler } 227f01106c3SAxel Dörfler 228f01106c3SAxel Dörfler 229f01106c3SAxel Dörfler status_t 230f01106c3SAxel Dörfler NetworkStatusView::Archive(BMessage* archive, bool deep) const 231f01106c3SAxel Dörfler { 232f01106c3SAxel Dörfler status_t status = BView::Archive(archive, deep); 233f01106c3SAxel Dörfler if (status == B_OK) 234f01106c3SAxel Dörfler status = archive->AddString("add_on", kSignature); 235f01106c3SAxel Dörfler if (status == B_OK) 236f01106c3SAxel Dörfler status = archive->AddString("class", "NetworkStatusView"); 237f01106c3SAxel Dörfler 238f01106c3SAxel Dörfler return status; 239f01106c3SAxel Dörfler } 240f01106c3SAxel Dörfler 241f01106c3SAxel Dörfler 242f01106c3SAxel Dörfler void 243f01106c3SAxel Dörfler NetworkStatusView::AttachedToWindow() 244f01106c3SAxel Dörfler { 245f01106c3SAxel Dörfler BView::AttachedToWindow(); 246f01106c3SAxel Dörfler if (Parent()) 247f01106c3SAxel Dörfler SetViewColor(Parent()->ViewColor()); 248f01106c3SAxel Dörfler else 249f01106c3SAxel Dörfler SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 250f01106c3SAxel Dörfler 251f01106c3SAxel Dörfler SetLowColor(ViewColor()); 252f01106c3SAxel Dörfler 253195981bbSAxel Dörfler start_watching_network( 254195981bbSAxel Dörfler B_WATCH_NETWORK_INTERFACE_CHANGES | B_WATCH_NETWORK_LINK_CHANGES, this); 255f01106c3SAxel Dörfler 256f01106c3SAxel Dörfler _Update(); 257f01106c3SAxel Dörfler } 258f01106c3SAxel Dörfler 259f01106c3SAxel Dörfler 260f01106c3SAxel Dörfler void 261f01106c3SAxel Dörfler NetworkStatusView::DetachedFromWindow() 262f01106c3SAxel Dörfler { 263195981bbSAxel Dörfler stop_watching_network(this); 264f01106c3SAxel Dörfler } 265f01106c3SAxel Dörfler 266f01106c3SAxel Dörfler 267f01106c3SAxel Dörfler void 268f01106c3SAxel Dörfler NetworkStatusView::MessageReceived(BMessage* message) 269f01106c3SAxel Dörfler { 270f01106c3SAxel Dörfler switch (message->what) { 271195981bbSAxel Dörfler case B_NETWORK_MONITOR: 272f01106c3SAxel Dörfler _Update(); 273f01106c3SAxel Dörfler break; 274f01106c3SAxel Dörfler 275f01106c3SAxel Dörfler case kMsgShowConfiguration: 276f01106c3SAxel Dörfler _ShowConfiguration(message); 277f01106c3SAxel Dörfler break; 278f01106c3SAxel Dörfler 279c1502c9aSStephan Aßmus case kMsgOpenNetworkPreferences: 2803b41ad86SStephan Aßmus _OpenNetworksPreferences(); 2813b41ad86SStephan Aßmus break; 2823b41ad86SStephan Aßmus 2832e1a6286SAxel Dörfler case kMsgJoinNetwork: 2842e1a6286SAxel Dörfler { 2852e1a6286SAxel Dörfler const char* deviceName; 2862e1a6286SAxel Dörfler const char* name; 2872e1a6286SAxel Dörfler if (message->FindString("device", &deviceName) == B_OK 2882e1a6286SAxel Dörfler && message->FindString("name", &name) == B_OK) { 2892e1a6286SAxel Dörfler BNetworkDevice device(deviceName); 2902e1a6286SAxel Dörfler status_t status = device.JoinNetwork(name); 2912e1a6286SAxel Dörfler if (status != B_OK) { 2922e1a6286SAxel Dörfler BString text 2932e1a6286SAxel Dörfler = B_TRANSLATE("Could not join wireless network:\n"); 2942e1a6286SAxel Dörfler text << strerror(status); 2952e1a6286SAxel Dörfler BAlert* alert = new BAlert(name, text.String(), 2962e1a6286SAxel Dörfler B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL, 2972e1a6286SAxel Dörfler B_STOP_ALERT); 2982e1a6286SAxel Dörfler alert->Go(NULL); 2992e1a6286SAxel Dörfler } 3002e1a6286SAxel Dörfler } 3012e1a6286SAxel Dörfler break; 3022e1a6286SAxel Dörfler } 3032e1a6286SAxel Dörfler 304f01106c3SAxel Dörfler case B_ABOUT_REQUESTED: 305f01106c3SAxel Dörfler _AboutRequested(); 306f01106c3SAxel Dörfler break; 307f01106c3SAxel Dörfler 308f01106c3SAxel Dörfler case B_QUIT_REQUESTED: 309f01106c3SAxel Dörfler _Quit(); 310f01106c3SAxel Dörfler break; 311f01106c3SAxel Dörfler 312f01106c3SAxel Dörfler default: 313f01106c3SAxel Dörfler BView::MessageReceived(message); 314f01106c3SAxel Dörfler } 315f01106c3SAxel Dörfler } 316f01106c3SAxel Dörfler 317f01106c3SAxel Dörfler 318f01106c3SAxel Dörfler void 319f01106c3SAxel Dörfler NetworkStatusView::FrameResized(float width, float height) 320f01106c3SAxel Dörfler { 321f01106c3SAxel Dörfler _UpdateBitmaps(); 322d5ba07a3SAxel Dörfler Invalidate(); 323f01106c3SAxel Dörfler } 324f01106c3SAxel Dörfler 325f01106c3SAxel Dörfler 326f01106c3SAxel Dörfler void 327f01106c3SAxel Dörfler NetworkStatusView::Draw(BRect updateRect) 328f01106c3SAxel Dörfler { 3295c46b171SRene Gollent int32 status = kStatusUnknown; 3305c46b171SRene Gollent for (std::map<BString, int32>::const_iterator it 3315c46b171SRene Gollent = fInterfaceStatuses.begin(); it != fInterfaceStatuses.end(); ++it) { 3325c46b171SRene Gollent if (it->second > status) 3335c46b171SRene Gollent status = it->second; 3345c46b171SRene Gollent } 3355c46b171SRene Gollent 3365c46b171SRene Gollent if (fTrayIcons[status] == NULL) 337f01106c3SAxel Dörfler return; 338f01106c3SAxel Dörfler 339f01106c3SAxel Dörfler SetDrawingMode(B_OP_ALPHA); 3405c46b171SRene Gollent DrawBitmap(fTrayIcons[status]); 341f01106c3SAxel Dörfler SetDrawingMode(B_OP_COPY); 342f01106c3SAxel Dörfler } 343f01106c3SAxel Dörfler 344f01106c3SAxel Dörfler 345f01106c3SAxel Dörfler void 346f01106c3SAxel Dörfler NetworkStatusView::_ShowConfiguration(BMessage* message) 347f01106c3SAxel Dörfler { 348f01106c3SAxel Dörfler static const struct information_entry { 349f01106c3SAxel Dörfler const char* label; 350f01106c3SAxel Dörfler int32 control; 351f01106c3SAxel Dörfler } kInformationEntries[] = { 3522ee8f3f6SSiarzhuk Zharski { B_TRANSLATE("Address"), SIOCGIFADDR }, 3532ee8f3f6SSiarzhuk Zharski { B_TRANSLATE("Broadcast"), SIOCGIFBRDADDR }, 3542ee8f3f6SSiarzhuk Zharski { B_TRANSLATE("Netmask"), SIOCGIFNETMASK }, 355f01106c3SAxel Dörfler { NULL } 356f01106c3SAxel Dörfler }; 357f01106c3SAxel Dörfler 358195981bbSAxel Dörfler SocketOpener socket; 359195981bbSAxel Dörfler if (socket.InitCheck() != B_OK) 360195981bbSAxel Dörfler return; 361195981bbSAxel Dörfler 362f01106c3SAxel Dörfler const char* name; 363f01106c3SAxel Dörfler if (message->FindString("interface", &name) != B_OK) 364f01106c3SAxel Dörfler return; 365f01106c3SAxel Dörfler 366f01106c3SAxel Dörfler ifreq request; 367f01106c3SAxel Dörfler if (!_PrepareRequest(request, name)) 368f01106c3SAxel Dörfler return; 369f01106c3SAxel Dörfler 3702ee8f3f6SSiarzhuk Zharski BString text(B_TRANSLATE("%ifaceName information:\n")); 3712ee8f3f6SSiarzhuk Zharski text.ReplaceFirst("%ifaceName", name); 372757e7059SAdrien Destugues 373f01106c3SAxel Dörfler size_t boldLength = text.Length(); 374f01106c3SAxel Dörfler 375f01106c3SAxel Dörfler for (int i = 0; kInformationEntries[i].label; i++) { 376195981bbSAxel Dörfler if (ioctl(socket, kInformationEntries[i].control, &request, 377f01106c3SAxel Dörfler sizeof(request)) < 0) { 378f01106c3SAxel Dörfler continue; 379f01106c3SAxel Dörfler } 380f01106c3SAxel Dörfler 381f01106c3SAxel Dörfler char address[32]; 382f01106c3SAxel Dörfler sockaddr_in* inetAddress = NULL; 383f01106c3SAxel Dörfler switch (kInformationEntries[i].control) { 384f01106c3SAxel Dörfler case SIOCGIFNETMASK: 385f01106c3SAxel Dörfler inetAddress = (sockaddr_in*)&request.ifr_mask; 386f01106c3SAxel Dörfler break; 387f01106c3SAxel Dörfler default: 388f01106c3SAxel Dörfler inetAddress = (sockaddr_in*)&request.ifr_addr; 389f01106c3SAxel Dörfler break; 390f01106c3SAxel Dörfler } 391f01106c3SAxel Dörfler 392f01106c3SAxel Dörfler if (inet_ntop(AF_INET, &inetAddress->sin_addr, address, 393f01106c3SAxel Dörfler sizeof(address)) == NULL) { 394f01106c3SAxel Dörfler return; 395f01106c3SAxel Dörfler } 396f01106c3SAxel Dörfler 3972ee8f3f6SSiarzhuk Zharski text << "\n" << kInformationEntries[i].label << ": " << address; 398f01106c3SAxel Dörfler } 399f01106c3SAxel Dörfler 400757e7059SAdrien Destugues BAlert* alert = new BAlert(name, text.String(), B_TRANSLATE("OK")); 401f01106c3SAxel Dörfler BTextView* view = alert->TextView(); 402f01106c3SAxel Dörfler BFont font; 403f01106c3SAxel Dörfler 404f01106c3SAxel Dörfler view->SetStylable(true); 405f01106c3SAxel Dörfler view->GetFont(&font); 406f01106c3SAxel Dörfler font.SetFace(B_BOLD_FACE); 407f01106c3SAxel Dörfler view->SetFontAndColor(0, boldLength, &font); 408f01106c3SAxel Dörfler 409f01106c3SAxel Dörfler alert->Go(NULL); 410f01106c3SAxel Dörfler } 411f01106c3SAxel Dörfler 412f01106c3SAxel Dörfler 413f01106c3SAxel Dörfler void 414f01106c3SAxel Dörfler NetworkStatusView::MouseDown(BPoint point) 415f01106c3SAxel Dörfler { 416f01106c3SAxel Dörfler BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING, false, false); 417a31688d2SAxel Dörfler menu->SetAsyncAutoDestruct(true); 418f01106c3SAxel Dörfler menu->SetFont(be_plain_font); 4195c46b171SRene Gollent BString wifiInterface; 4205c46b171SRene Gollent BNetworkDevice wifiDevice; 421f01106c3SAxel Dörfler 4225fe97f21SAxel Dörfler // Add interfaces 4235fe97f21SAxel Dörfler 4245c46b171SRene Gollent for (std::map<BString, int32>::const_iterator it 4255c46b171SRene Gollent = fInterfaceStatuses.begin(); it != fInterfaceStatuses.end(); ++it) { 4265c46b171SRene Gollent const BString& name = it->first; 427f01106c3SAxel Dörfler 428f01106c3SAxel Dörfler BString label = name; 429f01106c3SAxel Dörfler label += ": "; 430f01106c3SAxel Dörfler label += kStatusDescriptions[ 431f01106c3SAxel Dörfler _DetermineInterfaceStatus(name.String())]; 432f01106c3SAxel Dörfler 433f01106c3SAxel Dörfler BMessage* info = new BMessage(kMsgShowConfiguration); 434f01106c3SAxel Dörfler info->AddString("interface", name.String()); 435f01106c3SAxel Dörfler menu->AddItem(new BMenuItem(label.String(), info)); 4365c46b171SRene Gollent 4375c46b171SRene Gollent // We only show the networks of the first wireless device we find. 4385c46b171SRene Gollent if (wifiInterface.IsEmpty()) { 4395c46b171SRene Gollent wifiDevice.SetTo(name); 4405c46b171SRene Gollent if (wifiDevice.IsWireless()) 4415c46b171SRene Gollent wifiInterface = name; 4425c46b171SRene Gollent } 443f01106c3SAxel Dörfler } 444f01106c3SAxel Dörfler 4455c46b171SRene Gollent if (!fInterfaceStatuses.empty()) 446f01106c3SAxel Dörfler menu->AddSeparatorItem(); 4475fe97f21SAxel Dörfler 4485fe97f21SAxel Dörfler // Add wireless networks, if any 4495fe97f21SAxel Dörfler 4505c46b171SRene Gollent if (!wifiInterface.IsEmpty()) { 451440d0e61SAxel Dörfler std::set<BNetworkAddress> associated; 452440d0e61SAxel Dörfler BNetworkAddress address; 453440d0e61SAxel Dörfler uint32 cookie = 0; 4545c46b171SRene Gollent while (wifiDevice.GetNextAssociatedNetwork(cookie, address) == B_OK) 455440d0e61SAxel Dörfler associated.insert(address); 456440d0e61SAxel Dörfler 4575fe97f21SAxel Dörfler wireless_network network; 4585fe97f21SAxel Dörfler int32 count = 0; 459440d0e61SAxel Dörfler cookie = 0; 4605c46b171SRene Gollent while (wifiDevice.GetNextNetwork(cookie, network) == B_OK) { 4612e1a6286SAxel Dörfler BMessage* message = new BMessage(kMsgJoinNetwork); 4625c46b171SRene Gollent message->AddString("device", wifiInterface); 4632e1a6286SAxel Dörfler message->AddString("name", network.name); 4642e1a6286SAxel Dörfler 465440d0e61SAxel Dörfler BMenuItem* item = new WirelessNetworkMenuItem(network.name, 466440d0e61SAxel Dörfler network.signal_strength, 4672e1a6286SAxel Dörfler (network.flags & B_NETWORK_IS_ENCRYPTED) != 0, message); 468440d0e61SAxel Dörfler menu->AddItem(item); 469440d0e61SAxel Dörfler if (associated.find(network.address) != associated.end()) 470440d0e61SAxel Dörfler item->SetMarked(true); 471440d0e61SAxel Dörfler 4725fe97f21SAxel Dörfler count++; 4735fe97f21SAxel Dörfler } 4745fe97f21SAxel Dörfler if (count == 0) { 4755fe97f21SAxel Dörfler BMenuItem* item = new BMenuItem( 4765fe97f21SAxel Dörfler B_TRANSLATE("<no wireless networks found>"), NULL); 4775fe97f21SAxel Dörfler item->SetEnabled(false); 4785fe97f21SAxel Dörfler menu->AddItem(item); 4795fe97f21SAxel Dörfler } 4805fe97f21SAxel Dörfler menu->AddSeparatorItem(); 4815fe97f21SAxel Dörfler } 4825fe97f21SAxel Dörfler 483757e7059SAdrien Destugues menu->AddItem(new BMenuItem(B_TRANSLATE( 484757e7059SAdrien Destugues "Open network preferences" B_UTF8_ELLIPSIS), 485c1502c9aSStephan Aßmus new BMessage(kMsgOpenNetworkPreferences))); 4863b41ad86SStephan Aßmus 4875fe97f21SAxel Dörfler if (fInDeskbar) { 488757e7059SAdrien Destugues menu->AddItem(new BMenuItem(B_TRANSLATE("Quit"), 489757e7059SAdrien Destugues new BMessage(B_QUIT_REQUESTED))); 4905fe97f21SAxel Dörfler } 491f01106c3SAxel Dörfler menu->SetTargetForItems(this); 492f01106c3SAxel Dörfler 493f01106c3SAxel Dörfler ConvertToScreen(&point); 494a31688d2SAxel Dörfler menu->Go(point, true, true, true); 495f01106c3SAxel Dörfler } 496f01106c3SAxel Dörfler 497f01106c3SAxel Dörfler 498f01106c3SAxel Dörfler void 499f01106c3SAxel Dörfler NetworkStatusView::_AboutRequested() 500f01106c3SAxel Dörfler { 5015fe97f21SAxel Dörfler BString about = B_TRANSLATE( 502757e7059SAdrien Destugues "NetworkStatus\n\twritten by %1 and Hugo Santos\n\t%2, Haiku, Inc.\n" 503757e7059SAdrien Destugues ); 5045fe97f21SAxel Dörfler about.ReplaceFirst("%1", "Axel Dörfler"); 505757e7059SAdrien Destugues // Append a new developer here 5065fe97f21SAxel Dörfler about.ReplaceFirst("%2", "Copyright 2007-2010"); 507757e7059SAdrien Destugues // Append a new year here 5085fe97f21SAxel Dörfler BAlert* alert = new BAlert("about", about, B_TRANSLATE("OK")); 509f01106c3SAxel Dörfler BTextView *view = alert->TextView(); 510f01106c3SAxel Dörfler BFont font; 511f01106c3SAxel Dörfler 512f01106c3SAxel Dörfler view->SetStylable(true); 513f01106c3SAxel Dörfler 514f01106c3SAxel Dörfler view->GetFont(&font); 515f01106c3SAxel Dörfler font.SetSize(18); 516f01106c3SAxel Dörfler font.SetFace(B_BOLD_FACE); 517f01106c3SAxel Dörfler view->SetFontAndColor(0, 13, &font); 518f01106c3SAxel Dörfler 519f01106c3SAxel Dörfler alert->Go(); 520f01106c3SAxel Dörfler } 521f01106c3SAxel Dörfler 522f01106c3SAxel Dörfler 523f01106c3SAxel Dörfler bool 524f01106c3SAxel Dörfler NetworkStatusView::_PrepareRequest(struct ifreq& request, const char* name) 525f01106c3SAxel Dörfler { 526f01106c3SAxel Dörfler if (strlen(name) > IF_NAMESIZE) 527f01106c3SAxel Dörfler return false; 528f01106c3SAxel Dörfler 529f01106c3SAxel Dörfler strcpy(request.ifr_name, name); 530f01106c3SAxel Dörfler return true; 531f01106c3SAxel Dörfler } 532f01106c3SAxel Dörfler 533f01106c3SAxel Dörfler 534f01106c3SAxel Dörfler int32 5355c46b171SRene Gollent NetworkStatusView::_DetermineInterfaceStatus( 5365c46b171SRene Gollent const BNetworkInterface& interface) 537f01106c3SAxel Dörfler { 5385fe97f21SAxel Dörfler uint32 flags = interface.Flags(); 539f01106c3SAxel Dörfler int32 status = kStatusNoLink; 540f01106c3SAxel Dörfler 541f01106c3SAxel Dörfler // TODO: no kStatusLinkNoConfig yet 542f01106c3SAxel Dörfler 543f01106c3SAxel Dörfler if (flags & IFF_CONFIGURING) 544f01106c3SAxel Dörfler status = kStatusConnecting; 5452a17be44SAxel Dörfler else if ((flags & (IFF_UP | IFF_LINK)) == (IFF_UP | IFF_LINK)) 546f01106c3SAxel Dörfler status = kStatusReady; 547f01106c3SAxel Dörfler 548f01106c3SAxel Dörfler return status; 549f01106c3SAxel Dörfler } 550f01106c3SAxel Dörfler 551f01106c3SAxel Dörfler 552f01106c3SAxel Dörfler void 553f01106c3SAxel Dörfler NetworkStatusView::_Update(bool force) 554f01106c3SAxel Dörfler { 5555fe97f21SAxel Dörfler BNetworkRoster& roster = BNetworkRoster::Default(); 5565fe97f21SAxel Dörfler BNetworkInterface interface; 5575fe97f21SAxel Dörfler uint32 cookie = 0; 5585fe97f21SAxel Dörfler 5595fe97f21SAxel Dörfler while (roster.GetNextInterface(&cookie, interface) == B_OK) { 5605fe97f21SAxel Dörfler if ((interface.Flags() & IFF_LOOPBACK) == 0) { 5615c46b171SRene Gollent int32 oldStatus = kStatusUnknown; 5625c46b171SRene Gollent if (fInterfaceStatuses.find(interface.Name()) 5635c46b171SRene Gollent != fInterfaceStatuses.end()) { 5645c46b171SRene Gollent oldStatus = fInterfaceStatuses[interface.Name()]; 565f01106c3SAxel Dörfler } 5665c46b171SRene Gollent int32 status = _DetermineInterfaceStatus(interface); 5675c46b171SRene Gollent if (oldStatus != status) { 568b44d24c0SAlexander von Gluck IV BNotification notification(B_INFORMATION_NOTIFICATION); 569b44d24c0SAlexander von Gluck IV notification.SetGroup(B_TRANSLATE("Network Status")); 570b44d24c0SAlexander von Gluck IV notification.SetTitle(interface.Name()); 571b44d24c0SAlexander von Gluck IV notification.SetMessageID(interface.Name()); 5725c46b171SRene Gollent notification.SetIcon(fNotifyIcons[status]); 5735c46b171SRene Gollent if (status == kStatusConnecting 5745c46b171SRene Gollent || (status == kStatusReady 5755c46b171SRene Gollent && oldStatus == kStatusConnecting) 5765c46b171SRene Gollent || (status == kStatusNoLink 5775c46b171SRene Gollent && oldStatus == kStatusReady) 5785c46b171SRene Gollent || (status == kStatusNoLink 5795c46b171SRene Gollent && oldStatus == kStatusConnecting)) { 58043c68287SAlexander von Gluck IV // A significant state change, raise notification. 5815c46b171SRene Gollent notification.SetContent(kStatusDescriptions[status]); 582b44d24c0SAlexander von Gluck IV notification.Send(); 583b44d24c0SAlexander von Gluck IV } 584f01106c3SAxel Dörfler Invalidate(); 585f01106c3SAxel Dörfler } 5865c46b171SRene Gollent fInterfaceStatuses[interface.Name()] = status; 5875c46b171SRene Gollent } 5885c46b171SRene Gollent } 589b44d24c0SAlexander von Gluck IV } 590f01106c3SAxel Dörfler 591f01106c3SAxel Dörfler 5923b41ad86SStephan Aßmus void 5933b41ad86SStephan Aßmus NetworkStatusView::_OpenNetworksPreferences() 5943b41ad86SStephan Aßmus { 595195981bbSAxel Dörfler status_t status = be_roster->Launch("application/x-vnd.Haiku-Network"); 59646cac7f7SAlexandre Deckner if (status != B_OK && status != B_ALREADY_RUNNING) { 597757e7059SAdrien Destugues BString errorMessage(B_TRANSLATE("Launching the network preflet " 598757e7059SAdrien Destugues "failed.\n\nError: ")); 599195981bbSAxel Dörfler errorMessage << strerror(status); 6003b41ad86SStephan Aßmus BAlert* alert = new BAlert("launch error", errorMessage.String(), 601757e7059SAdrien Destugues B_TRANSLATE("OK")); 602195981bbSAxel Dörfler 603195981bbSAxel Dörfler // asynchronous alert in order to not block replicant host application 6043b41ad86SStephan Aßmus alert->Go(NULL); 6053b41ad86SStephan Aßmus } 6063b41ad86SStephan Aßmus } 6073b41ad86SStephan Aßmus 6083b41ad86SStephan Aßmus 609f01106c3SAxel Dörfler // #pragma mark - 610f01106c3SAxel Dörfler 611f01106c3SAxel Dörfler 612f01106c3SAxel Dörfler extern "C" _EXPORT BView * 613f01106c3SAxel Dörfler instantiate_deskbar_item(void) 614f01106c3SAxel Dörfler { 61566eba86fSAxel Dörfler return new NetworkStatusView(BRect(0, 0, 15, 15), 61666eba86fSAxel Dörfler B_FOLLOW_LEFT | B_FOLLOW_TOP, true); 617f01106c3SAxel Dörfler } 618f01106c3SAxel Dörfler 619