* Copyright 2004-2015 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Alexander von Gluck, kallisti5@unixzen.com
* John Scipione, jscipione@gmail.com
*/
#include "InterfaceAddressView.h"
#include <stdio.h>
#include <Button.h>
#include <Catalog.h>
#include <ControlLook.h>
#include <LayoutBuilder.h>
#include <MenuItem.h>
#include <MenuField.h>
#include <PopUpMenu.h>
#include <Screen.h>
#include <Size.h>
#include <StringView.h>
#include <TextControl.h>
#include "IPAddressControl.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "IntefaceAddressView"
const uint32 kModeAuto = 'iato';
const uint32 kModeStatic = 'istc';
const uint32 kModeDisabled = 'ioff';
const uint32 kMsgApply = 'aply';
InterfaceAddressView::InterfaceAddressView(int family,
const char* interface, BNetworkSettings& settings)
:
BGroupView(B_VERTICAL),
fFamily(family),
fInterface(interface),
fSettings(settings)
{
SetLayout(new BGroupLayout(B_VERTICAL));
fModePopUpMenu = new BPopUpMenu("modes");
if (fFamily == AF_INET) {
fModePopUpMenu->AddItem(new BMenuItem(B_TRANSLATE("DHCP"),
new BMessage(kModeAuto)));
}
if (fFamily == AF_INET6) {
fModePopUpMenu->AddItem(new BMenuItem(B_TRANSLATE("Automatic"),
new BMessage(kModeAuto)));
}
fModePopUpMenu->AddItem(new BMenuItem(B_TRANSLATE("Static"),
new BMessage(kModeStatic)));
fModePopUpMenu->AddSeparatorItem();
fModePopUpMenu->AddItem(new BMenuItem(B_TRANSLATE("Disabled"),
new BMessage(kModeDisabled)));
fModeField = new BMenuField(B_TRANSLATE("Mode:"), fModePopUpMenu);
fModeField->SetToolTip(
B_TRANSLATE("The method for obtaining an IP address"));
float minimumWidth = be_control_look->DefaultItemSpacing() * 15;
fAddressField = new IPAddressControl(fFamily, B_TRANSLATE("IP address:"),
NULL);
fAddressField->SetToolTip(B_TRANSLATE("Your IP address"));
fAddressField->TextView()->SetExplicitMinSize(
BSize(minimumWidth, B_SIZE_UNSET));
fAddressField->SetAllowEmpty(false);
fNetmaskField = new IPAddressControl(fFamily, B_TRANSLATE("Netmask:"),
NULL);
fNetmaskField->SetToolTip(B_TRANSLATE(
"The netmask defines your local network"));
fNetmaskField->TextView()->SetExplicitMinSize(
BSize(minimumWidth, B_SIZE_UNSET));
fGatewayField = new IPAddressControl(fFamily, B_TRANSLATE("Gateway:"),
NULL);
fGatewayField->SetToolTip(B_TRANSLATE("Your gateway to the internet"));
fGatewayField->TextView()->SetExplicitMinSize(
BSize(minimumWidth, B_SIZE_UNSET));
fApplyButton = new BButton("apply", B_TRANSLATE("Apply"),
new BMessage(kMsgApply));
fSettings.GetInterface(interface, fOriginalSettings);
_UpdateFields();
BLayoutBuilder::Group<>(this)
.AddGrid()
.AddMenuField(fModeField, 0, 0, B_ALIGN_RIGHT)
.AddTextControl(fAddressField, 0, 1, B_ALIGN_RIGHT)
.AddTextControl(fNetmaskField, 0, 2, B_ALIGN_RIGHT)
.AddTextControl(fGatewayField, 0, 3, B_ALIGN_RIGHT)
.End()
.AddGroup(B_HORIZONTAL)
.AddGlue()
.Add(fApplyButton)
.End()
.AddGlue();
}
InterfaceAddressView::~InterfaceAddressView()
{
}
void
InterfaceAddressView::AttachedToWindow()
{
fModePopUpMenu->SetTargetForItems(this);
fApplyButton->SetTarget(this);
}
void
InterfaceAddressView::MessageReceived(BMessage* message)
{
switch (message->what) {
case kModeAuto:
case kModeStatic:
case kModeDisabled:
if (message->what == fLastMode)
break;
_SetModeField(message->what);
if (message->what != kModeStatic)
_UpdateSettings();
break;
case kMsgApply:
_UpdateSettings();
break;
default:
BView::MessageReceived(message);
}
}
status_t
InterfaceAddressView::Revert()
{
return fSettings.AddInterface(fOriginalSettings);
}
bool
InterfaceAddressView::IsRevertable() const
{
BMessage settings;
fSettings.GetInterface(fInterface.Name(), settings);
return !settings.HasSameData(fOriginalSettings);
}
void
InterfaceAddressView::ConfigurationUpdated(const BMessage& message)
{
const char* interface = message.GetString("interface", NULL);
if (interface == NULL || strcmp(interface, fInterface.Name()) != 0)
return;
_UpdateFields();
}
void
InterfaceAddressView::_EnableFields(bool enable)
{
fAddressField->SetEnabled(enable);
fNetmaskField->SetEnabled(enable);
fGatewayField->SetEnabled(enable);
fApplyButton->SetEnabled(enable);
}
The interface settings may be consulted to determine if the
automatic configuration has been specified, if there was no
configuration yet.
*/
void
InterfaceAddressView::_UpdateFields()
{
BMessage interfaceSettings;
fSettings.GetInterface(fInterface.Name(), interfaceSettings);
bool autoConfigure = interfaceSettings.IsEmpty();
if (!autoConfigure) {
BNetworkInterfaceSettings settings(interfaceSettings);
autoConfigure = settings.IsAutoConfigure(fFamily);
}
BNetworkInterfaceAddress address;
status_t status = B_ERROR;
int32 index = fInterface.FindFirstAddress(fFamily);
if (index >= 0)
status = fInterface.GetAddressAt(index, address);
if (!autoConfigure && (index < 0 || status != B_OK
|| address.Address().IsEmpty())) {
_SetModeField(kModeDisabled);
return;
}
if (autoConfigure)
_SetModeField(kModeAuto);
else
_SetModeField(kModeStatic);
fAddressField->SetText(address.Address().ToString());
fNetmaskField->SetText(address.Mask().ToString());
BNetworkAddress gateway;
if (fInterface.GetDefaultGateway(fFamily, gateway) == B_OK)
fGatewayField->SetText(gateway.ToString());
else
fGatewayField->SetText(NULL);
}
void
InterfaceAddressView::_SetModeField(uint32 mode)
{
BMenuItem* item = fModePopUpMenu->FindItem(mode);
if (item != NULL)
item->SetMarked(true);
_EnableFields(mode == kModeStatic);
if (mode == kModeDisabled) {
fAddressField->SetText(NULL);
fNetmaskField->SetText(NULL);
fGatewayField->SetText(NULL);
} else if (mode == kModeStatic)
fAddressField->MakeFocus(true);
fLastMode = mode;
}
void
InterfaceAddressView::_UpdateSettings()
{
BMessage interface;
fSettings.GetInterface(fInterface.Name(), interface);
BNetworkInterfaceSettings settings(interface);
settings.SetName(fInterface.Name());
int32 index = settings.FindFirstAddress(fFamily);
if (index < 0)
index = settings.FindFirstAddress(AF_UNSPEC);
if (index >= 0 && index < settings.CountAddresses()) {
BNetworkInterfaceAddressSettings& address = settings.AddressAt(index);
_ConfigureAddress(address);
} else {
BNetworkInterfaceAddressSettings address;
_ConfigureAddress(address);
settings.AddAddress(address);
}
interface.MakeEmpty();
status_t status = settings.GetMessage(interface);
if (status == B_OK)
fSettings.AddInterface(interface);
else
fprintf(stderr, "Could not add interface: %s\n", strerror(status));
}
uint32
InterfaceAddressView::_Mode() const
{
uint32 mode = kModeAuto;
BMenuItem* item = fModePopUpMenu->FindMarked();
if (item != NULL)
mode = item->Message()->what;
return mode;
}
void
InterfaceAddressView::_ConfigureAddress(
BNetworkInterfaceAddressSettings& settings)
{
uint32 mode = _Mode();
settings.SetFamily(fFamily);
settings.SetAutoConfigure(mode == kModeAuto);
settings.Address().Unset();
settings.Mask().Unset();
settings.Peer().Unset();
settings.Broadcast().Unset();
settings.Gateway().Unset();
if (mode == kModeStatic) {
_SetAddress(settings.Address(), fAddressField->Text());
_SetAddress(settings.Mask(), fNetmaskField->Text());
_SetAddress(settings.Gateway(), fGatewayField->Text());
}
}
void
InterfaceAddressView::_SetAddress(BNetworkAddress& address, const char* text)
{
BString string(text);
string.Trim();
if (string.IsEmpty())
return;
address.SetTo(string.String(), static_cast<uint16>(0),
B_NO_ADDRESS_RESOLUTION);
}