* Copyright 2004-2015 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, <axeld@pinc-software.de>
* Alexander von Gluck, kallisti5@unixzen.com
* John Scipione, jscipione@gmail.com
*/
#include "InterfaceView.h"
#include <set>
#include <net/if_media.h>
#include <AutoDeleter.h>
#include <Button.h>
#include <Catalog.h>
#include <ControlLook.h>
#include <LayoutBuilder.h>
#include <NetworkAddress.h>
#include <StringForSize.h>
#include <StringView.h>
#include <TextControl.h>
#include "MediaTypes.h"
#include "WirelessNetworkMenuItem.h"
static const uint32 kMsgInterfaceToggle = 'onof';
static const uint32 kMsgInterfaceRenegotiate = 'redo';
static const uint32 kMsgJoinNetwork = 'join';
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "IntefaceView"
InterfaceView::InterfaceView()
:
BGroupView(B_VERTICAL),
fPulseCount(0)
{
SetFlags(Flags() | B_PULSE_NEEDED);
BStringView* statusLabel = new BStringView("status label", B_TRANSLATE("Status:"));
statusLabel->SetAlignment(B_ALIGN_RIGHT);
fStatusField = new BStringView("status field", "");
BStringView* macAddressLabel = new BStringView("mac address label",
B_TRANSLATE("MAC address:"));
macAddressLabel->SetAlignment(B_ALIGN_RIGHT);
fMacAddressField = new BStringView("mac address field", "");
BStringView* linkSpeedLabel = new BStringView("link speed label",
B_TRANSLATE("Link speed:"));
linkSpeedLabel->SetAlignment(B_ALIGN_RIGHT);
fLinkSpeedField = new BStringView("link speed field", "");
BStringView* linkTxLabel = new BStringView("tx label",
B_TRANSLATE("Sent:"));
linkTxLabel->SetAlignment(B_ALIGN_RIGHT);
fLinkTxField = new BStringView("tx field", "");
BStringView* linkRxLabel = new BStringView("rx label",
B_TRANSLATE("Received:"));
linkRxLabel->SetAlignment(B_ALIGN_RIGHT);
fLinkRxField = new BStringView("rx field", "");
fNetworkMenuField = new BMenuField(B_TRANSLATE("Network:"), new BMenu(
B_TRANSLATE("Choose automatically")));
fNetworkMenuField->SetAlignment(B_ALIGN_RIGHT);
fNetworkMenuField->Menu()->SetLabelFromMarked(true);
fToggleButton = new BButton("onoff", B_TRANSLATE("Disable"),
new BMessage(kMsgInterfaceToggle));
fRenegotiateButton = new BButton("heal", B_TRANSLATE("Renegotiate"),
new BMessage(kMsgInterfaceRenegotiate));
fRenegotiateButton->SetEnabled(false);
BLayoutBuilder::Group<>(this)
.AddGrid()
.Add(statusLabel, 0, 0)
.Add(fStatusField, 1, 0)
.AddMenuField(fNetworkMenuField, 0, 1, B_ALIGN_RIGHT, 1, 2)
.Add(macAddressLabel, 0, 2)
.Add(fMacAddressField, 1, 2)
.Add(linkSpeedLabel, 0, 3)
.Add(fLinkSpeedField, 1, 3)
.Add(linkTxLabel, 0, 4)
.Add(fLinkTxField, 1, 4)
.Add(linkRxLabel, 0, 5)
.Add(fLinkRxField, 1, 5)
.End()
.AddGlue()
.AddGroup(B_HORIZONTAL)
.AddGlue()
.Add(fToggleButton)
.Add(fRenegotiateButton)
.End();
}
InterfaceView::~InterfaceView()
{
}
void
InterfaceView::SetTo(const char* name)
{
fInterface.SetTo(name);
}
void
InterfaceView::AttachedToWindow()
{
_Update();
fToggleButton->SetTarget(this);
fRenegotiateButton->SetTarget(this);
}
void
InterfaceView::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgJoinNetwork:
{
const char* name;
BNetworkAddress address;
if (message->FindString("name", &name) == B_OK
&& message->FindFlat("address", &address) == B_OK) {
BNetworkDevice device(fInterface.Name());
status_t status = device.JoinNetwork(address);
if (status != B_OK) {
}
}
break;
}
case kMsgInterfaceToggle:
{
uint32 flags = fInterface.Flags();
if ((flags & IFF_UP) != 0)
flags &= ~IFF_UP;
else
flags |= IFF_UP;
if (fInterface.SetFlags(flags) == B_OK)
_Update();
break;
}
case kMsgInterfaceRenegotiate:
{
break;
}
default:
BView::MessageReceived(message);
}
}
void
InterfaceView::Pulse()
{
_Update((fPulseCount++ % 5) == 0);
}
*/
status_t
InterfaceView::_Update(bool updateWirelessNetworks)
{
BNetworkDevice device(fInterface.Name());
bool isWireless = device.IsWireless();
bool disabled = (fInterface.Flags() & IFF_UP) == 0;
if (fInterface.HasLink())
fStatusField->SetText(B_TRANSLATE("connected"));
else
fStatusField->SetText(B_TRANSLATE("disconnected"));
BNetworkAddress hardwareAddress;
if (device.GetHardwareAddress(hardwareAddress) == B_OK)
fMacAddressField->SetText(hardwareAddress.ToString());
else
fMacAddressField->SetText("-");
int media = fInterface.Media();
if ((media & IFM_ACTIVE) != 0)
fLinkSpeedField->SetText(media_type_to_string(media));
else
fLinkSpeedField->SetText("-");
ifreq_stats stats;
if (fInterface.GetStats(stats) == B_OK) {
char buffer[100];
string_for_size(stats.send.bytes, buffer, sizeof(buffer));
fLinkTxField->SetText(buffer);
string_for_size(stats.receive.bytes, buffer, sizeof(buffer));
fLinkRxField->SetText(buffer);
}
if (fNetworkMenuField->IsHidden(fNetworkMenuField) && isWireless)
fNetworkMenuField->Show();
else if (!fNetworkMenuField->IsHidden(fNetworkMenuField) && !isWireless)
fNetworkMenuField->Hide();
if (isWireless && updateWirelessNetworks) {
BMenu* menu = fNetworkMenuField->Menu();
int32 count = menu->CountItems();
BMenuItem* chooseItem = NULL;
BSeparatorItem* separatorItem = NULL;
if (count > 0 && strcmp(menu->ItemAt(0)->Label(),
B_TRANSLATE("Choose automatically")) == 0) {
chooseItem = menu->RemoveItem((int32)0);
separatorItem = (BSeparatorItem*)menu->RemoveItem((int32)0);
count -= 2;
}
BMenuItem* noNetworksFoundItem = NULL;
if (menu->CountItems() > 0 && strcmp(menu->ItemAt(0)->Label(),
B_TRANSLATE("<no wireless networks found>")) == 0) {
noNetworksFoundItem = menu->RemoveItem((int32)0);
count--;
}
std::set<BNetworkAddress> associated;
BNetworkAddress address;
uint32 cookie = 0;
while (device.GetNextAssociatedNetwork(cookie, address) == B_OK)
associated.insert(address);
wireless_network* networks = NULL;
uint32 networksCount = 0;
device.GetNetworks(networks, networksCount);
if ((fPulseCount % 15) == 0 && networksCount == 0) {
device.Scan(false, false);
snooze(50 * 1000);
device.GetNetworks(networks, networksCount);
}
ArrayDeleter<wireless_network> networksDeleter(networks);
for (int32 index = 0; index < count; index++) {
WirelessNetworkMenuItem* networkItem =
dynamic_cast<WirelessNetworkMenuItem*>(
menu->ItemAt(index));
if (networkItem == NULL)
break;
bool networkFound = false;
for (uint32 i = 0; i < networksCount; i++) {
if (networkItem->Network() == networks[i]) {
networkFound = true;
break;
}
}
if (!networkFound) {
menu->RemoveItem(networkItem);
count--;
}
}
for (uint32 i = 0; i < networksCount; i++) {
const wireless_network& network = networks[i];
bool networkFound = false;
for (int32 index = 0; index < count; index++) {
WirelessNetworkMenuItem* networkItem =
dynamic_cast<WirelessNetworkMenuItem*>(
menu->ItemAt(index));
if (networkItem == NULL)
break;
if (networkItem->Network() == network) {
networkFound = true;
if (associated.find(network.address) != associated.end())
networkItem->SetMarked(true);
break;
}
}
if (!networkFound) {
BMessage* message = new BMessage(kMsgJoinNetwork);
message->AddString("device", fInterface.Name());
message->AddString("name", network.name);
message->AddFlat("address", &network.address);
BMenuItem* item = new WirelessNetworkMenuItem(network,
message);
menu->AddItem(item);
if (associated.find(network.address) != associated.end())
item->SetMarked(true);
}
count++;
}
if (count == 0) {
if (noNetworksFoundItem != NULL)
menu->AddItem(noNetworksFoundItem);
else {
BMenuItem* item = new BMenuItem(
B_TRANSLATE("<no wireless networks found>"), NULL);
item->SetEnabled(false);
menu->AddItem(item);
}
} else {
menu->SortItems(WirelessNetworkMenuItem::CompareSignalStrength);
if (chooseItem != NULL) {
menu->AddItem(chooseItem, 0);
menu->AddItem(separatorItem, 1);
} else {
BMenuItem* item = new BMenuItem(
B_TRANSLATE("Choose automatically"), NULL);
if (menu->FindMarked() == NULL)
item->SetMarked(true);
menu->AddItem(item, 0);
menu->AddItem(new BSeparatorItem(), 1);
}
}
menu->SetTargetForItems(this);
}
fToggleButton->SetLabel(disabled
? B_TRANSLATE("Enable") : B_TRANSLATE("Disable"));
return B_OK;
}