Files
haiku-beta6/src/prefs/devices/DevicesWindow.cpp
T
Jérôme Duval 22b19ff048 Improvements. Still not beta.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7441 a95241bf-73f2-0310-859d-f6bbb57e9c96
2004-05-07 09:02:48 +00:00

501 lines
15 KiB
C++

// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
//
// Copyright (c) 2003-2004, OpenBeOS
//
// This software is part of the OpenBeOS distribution and is covered
// by the OpenBeOS license.
//
//
// File: DevicesWindow.cpp
// Author: Sikosis, Jérôme Duval
// Description: Devices Preferences
// Created : March 04, 2003
//
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
// Includes -------------------------------------------------------------------------------------------------- //
#include <Alert.h>
#include <Application.h>
#include <Box.h>
#include <Button.h>
#include <ClassInfo.h>
#include <File.h>
#include <FindDirectory.h>
#include <MenuBar.h>
#include <Menu.h>
#include <MenuItem.h>
#include <OutlineListView.h>
#include <Path.h>
#include <Screen.h>
#include <ScrollView.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <String.h>
#include <StringView.h>
#include "DevicesWindows.h"
#include "DevicesInfo.h"
const uint32 MENU_FILE_ABOUT_DEVICES = 'mfad';
const uint32 MENU_FILE_QUIT = 'mfqt';
const uint32 MENU_DEVICES_REMOVE_JUMPERED_DEVICE = 'mdrj';
const uint32 MENU_DEVICES_NEW_JUMPERED_DEVICE = 'mdnj';
const uint32 MENU_DEVICES_NEW_JUMPERED_DEVICE_CUSTOM = 'mdcj';
const uint32 MENU_DEVICES_NEW_JUMPERED_DEVICE_MODEM = 'mdcm';
const uint32 MENU_DEVICES_RESOURCE_USAGE = 'mdru';
const uint32 BTN_CONFIGURE = 'bcfg';
const uint32 SELECTION_CHANGED = 'slch';
// CenterWindowOnScreen -- Centers the BWindow to the Current Screen
void CenterWindowOnScreen(BWindow* w)
{
BRect screenFrame = (BScreen(B_MAIN_SCREEN_ID).Frame());
BPoint pt;
pt.x = screenFrame.Width()/2 - w->Bounds().Width()/2;
pt.y = screenFrame.Height()/2 - w->Bounds().Height()/2;
if (screenFrame.Contains(pt))
w->MoveTo(pt);
}
// ---------------------------------------------------------------------------------------------------------- //
// DevicesWindow - Constructor
DevicesWindow::DevicesWindow(BRect frame) : BWindow (frame, "Devices", B_TITLED_WINDOW, B_NORMAL_WINDOW_FEEL , 0)
{
InitWindow();
CenterWindowOnScreen(this);
// Load User Settings
BPath path;
find_directory(B_USER_SETTINGS_DIRECTORY,&path);
path.Append("Devices_Settings",true);
BFile file(path.Path(),B_READ_ONLY);
BMessage msg;
msg.Unflatten(&file);
LoadSettings (&msg);
status_t error;
if ((error = init_cm_wrapper()) < 0) {
printf("Error initializing configuration manager (%s)\n", strerror(error));
exit(1);
}
InitDevices(B_ISA_BUS);
InitDevices(B_PCI_BUS);
for (int32 i=fList.CountItems()-1; i>=0; i--) {
DevicesInfo *deviceInfo = (DevicesInfo *) fList.ItemAt(i);
struct device_info *info = deviceInfo->GetInfo();
BListItem *item = systemMenu;
if (info->bus == B_ISA_BUS)
item = systemMenu;
else if (info->bus == B_PCI_BUS)
item = pciMenu;
outline->AddUnder(new DeviceItem(deviceInfo, deviceInfo->GetName()), item);
}
if (outline->CountItemsUnder(jumperedMenu, true)==0)
outline->AddUnder(new BStringItem("<no devices>"), jumperedMenu);
if (outline->CountItemsUnder(pciMenu, true)==0)
outline->AddUnder(new BStringItem("<no devices>"), pciMenu);
if (outline->CountItemsUnder(isaMenu, true)==0)
outline->AddUnder(new BStringItem("<no devices>"), isaMenu);
if (outline->CountItemsUnder(systemMenu, true)==0)
outline->AddUnder(new BStringItem("<no devices>"), systemMenu);
Show();
}
// ---------------------------------------------------------------------------------------------------------- //
// DevicesWindow - Destructor
DevicesWindow::~DevicesWindow()
{
void *item;
while ((item = fList.RemoveItem((int32)0)))
delete item;
uninit_cm_wrapper();
}
// ---------------------------------------------------------------------------------------------------------- //
// DevicesWindow::InitWindow -- Initialization Commands here
void DevicesWindow::InitWindow(void)
{
BRect r;
r = Bounds(); // the whole view
BMenuItem *mniRemoveJumperedDevice;
// Add the menu bar
menubar = new BMenuBar(r, "menu_bar");
// Add File menu to menu bar
BMenu *menu = new BMenu("File");
menu->AddItem(new BMenuItem("About Devices" B_UTF8_ELLIPSIS, new BMessage(MENU_FILE_ABOUT_DEVICES), 0));
menu->AddSeparatorItem();
menu->AddItem(new BMenuItem("Quit", new BMessage(MENU_FILE_QUIT), 'Q'));
menubar->AddItem(menu);
menu = new BMenu("Devices");
menubar->AddItem(menu);
BMenu *jumperedDevicesMenu = new BMenu("New Jumpered Device");
jumperedDevicesMenu->AddItem(new BMenuItem("Custom ...", new BMessage(MENU_DEVICES_NEW_JUMPERED_DEVICE_CUSTOM), 0));
jumperedDevicesMenu->AddItem(new BMenuItem("Modem ...", new BMessage(MENU_DEVICES_NEW_JUMPERED_DEVICE_MODEM), 0));
//DevicesMenu->AddItem(new BMenuItem("New Jumpered Device", new BMessage(MENU_DEVICES_NEW_JUMPERED_DEVICE), NULL));
menu->AddItem(jumperedDevicesMenu);
menu->AddItem(mniRemoveJumperedDevice = new BMenuItem("Remove Jumpered Device", new BMessage(MENU_DEVICES_REMOVE_JUMPERED_DEVICE), 'R'));
menu->AddSeparatorItem();
menu->AddItem(new BMenuItem("Resource Usage", new BMessage(MENU_DEVICES_RESOURCE_USAGE), 'U'));
mniRemoveJumperedDevice->SetEnabled(false);
// Create the StringViews
stvDeviceName = new BStringView(BRect(16, 16, 150, 40), "DeviceName", "Device Name");
stvCurrentState = new BStringView(BRect(248, 16, r.right-10, 40), "CurrentState", "Current State");
float fCurrentHeight = 279;
float fCurrentGap = 15;
stvIRQ = new BStringView(BRect(r.left+22,r.top+fCurrentHeight,r.right-13,r.top+fCurrentHeight+20),"IRQ","IRQs:", B_FOLLOW_LEFT | B_FOLLOW_BOTTOM);
fCurrentHeight = fCurrentHeight + fCurrentGap;
stvDMA = new BStringView(BRect(r.left+22,r.top+fCurrentHeight,r.right-13,r.top+fCurrentHeight+20),"DMA","DMAs:", B_FOLLOW_LEFT | B_FOLLOW_BOTTOM);
fCurrentHeight = fCurrentHeight + fCurrentGap;
stvIORanges = new BStringView(BRect(r.left+22,r.top+fCurrentHeight,r.right-13,r.top+fCurrentHeight+20),"IORanges","IO Ranges:", B_FOLLOW_LEFT | B_FOLLOW_BOTTOM);
fCurrentHeight = fCurrentHeight + fCurrentGap;
stvMemoryRanges = new BStringView(BRect(r.left+22,r.top+fCurrentHeight,r.right-13,r.top+fCurrentHeight+20),"MemoryRanges","Memory Ranges:", B_FOLLOW_LEFT | B_FOLLOW_BOTTOM);
fCurrentHeight = fCurrentHeight + fCurrentGap;
// Create the OutlineView
BRect outlinerect(r.left+14,r.top+45,r.right-28,r.top+262);
BScrollView *outlinesv;
outline = new BOutlineListView(outlinerect,"devices_list", B_SINGLE_SELECTION_LIST, B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP_BOTTOM);
outline->AddItem(systemMenu = new DeviceItem(NULL, "System Devices"));
outline->AddItem(isaMenu = new DeviceItem(NULL, "ISA/Plug and Play Devices"));
outline->AddItem(pciMenu = new DeviceItem(NULL, "PCI Devices"));
outline->AddItem(jumperedMenu = new DeviceItem(NULL, "Jumpered Devices"));
outline->SetSelectionMessage(new BMessage(SELECTION_CHANGED));
outline->SetInvocationMessage(new BMessage(BTN_CONFIGURE));
// Add ScrollView to Devices Window
outlinesv = new BScrollView("scroll_devices", outline, B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP_BOTTOM, 0, false, true, B_FANCY_BORDER);
// Setup the OutlineView
outline->AllAttached();
outlinesv->SetBorderHighlighted(true);
// Back and Fore ground Colours
outline->SetHighColor(0,0,0,0);
outline->SetLowColor(255,255,255,0);
// Font Settings
BFont OutlineFont;
OutlineFont.SetSpacing(B_CHAR_SPACING);
OutlineFont.SetSize(12);
outline->SetFont(&OutlineFont,B_FONT_SHEAR | B_FONT_SPACING);
// Create BBox (or Frame)
BBox *BottomFrame;
BRect BottomFrameRect(r.left+11,r.bottom-124,r.right-12,r.bottom-12);
BottomFrame = new BBox(BottomFrameRect, "BottomFrame", B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM, B_WILL_DRAW, B_FANCY_BORDER);
// Create BButton - Configure
BRect ConfigureButtonRect(r.left+298,r.bottom-47,r.right-23,r.bottom-23);
btnConfigure = new BButton(ConfigureButtonRect,"btnConfigure","Configure", new BMessage(BTN_CONFIGURE), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM, B_WILL_DRAW | B_NAVIGABLE);
btnConfigure->MakeDefault(true);
btnConfigure->SetEnabled(false);
// Create a basic View
BBox *background = new BBox(Bounds(), "background", B_FOLLOW_ALL_SIDES, B_WILL_DRAW, B_PLAIN_BORDER);
AddChild(background);
// Add Child(ren)
background->AddChild(menubar);
background->AddChild(stvDeviceName);
background->AddChild(stvCurrentState);
background->AddChild(stvIRQ);
background->AddChild(stvDMA);
background->AddChild(stvIORanges);
background->AddChild(stvMemoryRanges);
background->AddChild(outlinesv);
background->AddChild(btnConfigure);
background->AddChild(BottomFrame);
// Set Window Limits
float xsize = 396 + (be_plain_font->Size()-10)*40;
if (xsize > 443)
xsize = 443;
SetSizeLimits(xsize,xsize,400,BScreen().Frame().Height());
}
// ---------------------------------------------------------------------------------------------------------- //
// DevicesWindow::QuitRequested -- Post a message to the app to quit
bool DevicesWindow::QuitRequested()
{
SaveSettings();
be_app->PostMessage(B_QUIT_REQUESTED);
return true;
}
// ---------------------------------------------------------------------------------------------------------- //
// DevicesWindow::LoadSettings -- Loads your current settings
void DevicesWindow::LoadSettings(BMessage *msg)
{
BRect frame;
if (B_OK == msg->FindRect("windowframe",&frame)) {
MoveTo(frame.left,frame.top);
ResizeTo(frame.right-frame.left,frame.bottom-frame.top);
}
}
// -------------------------------------------------------------------------------------------------------------- //
// DevicesWindow::SaveSettings -- Saves the Users settings
void DevicesWindow::SaveSettings(void)
{
BMessage msg;
msg.AddRect("windowframe",Frame());
BPath path;
status_t result = find_directory(B_USER_SETTINGS_DIRECTORY,&path);
if (result == B_OK)
{
path.Append("Devices_Settings",true);
BFile file(path.Path(),B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
msg.Flatten(&file);
}
}
// ------------------------------------------------------------------------------- //
// DevicesWindow::MessageReceived -- receives messages
void
DevicesWindow::MessageReceived (BMessage *message)
{
switch(message->what)
{
case MENU_FILE_ABOUT_DEVICES:
{
(new BAlert("", "Devices\n\n\t'Just write a simple app to add a jumpered\n\tdevice to the system', he said.\n\n\tAnd many years later another he said\n\t'recreate it' ;)", "OK"))->Go();
}
break;
case MENU_FILE_QUIT:
{
QuitRequested();
}
break;
case MENU_DEVICES_NEW_JUMPERED_DEVICE_MODEM:
{
ptrModemWindow = new ModemWindow(BRect(0,0,200,194), BMessenger(this));
}
break;
case MENU_DEVICES_RESOURCE_USAGE:
{
ptrResourceUsageWindow = new ResourceUsageWindow(BRect(0,0,430,350), fList);
}
break;
case SELECTION_CHANGED:
{
UpdateDeviceInfo();
}
break;
case MODEM_ADDED:
{
}
break;
case BTN_CONFIGURE:
{
DeviceItem *item = (DeviceItem *)outline->ItemAt(outline->CurrentSelection());
if (item && is_instance_of(item, DeviceItem) ) {
if (item->GetWindow()!=NULL)
item->GetWindow()->Activate();
else
new ConfigurationWindow(BRect(150,150,562,602), item);
}
}
break;
default:
BWindow::MessageReceived(message);
break;
}
}
// ---------------------------------------------------------------------------------------------------------- //
void
DevicesWindow::InitDevices(bus_type bus)
{
status_t size;
uint64 cookie;
struct device_info dummy, *info;
struct device_configuration *current;
struct possible_device_configurations *possible;
cookie = 0;
while (get_next_device_info(bus, &cookie, &dummy, sizeof(dummy)) == B_OK) {
info = (struct device_info *)malloc(dummy.size);
if (!info) {
printf("Out of core\n");
break;
}
if (get_device_info_for(cookie, info, dummy.size) != B_OK) {
printf("Error getting device information\n");
break;
}
size = get_size_of_current_configuration_for(cookie);
if (size < B_OK) {
printf("Error getting the size of the current configuration\n");
break;
}
current = (struct device_configuration *)malloc(size);
if (!current) {
printf("Out of core\n");
break;
}
if (get_current_configuration_for(cookie, current, size) != B_OK) {
printf("Error getting the current configuration\n");
break;
}
size = get_size_of_possible_configurations_for(cookie);
if (size < B_OK) {
printf("Error getting the size of the possible configurations\n");
break;
}
possible = (struct possible_device_configurations *)malloc(size);
if (!possible) {
printf("Out of core\n");
break;
}
if (get_possible_configurations_for(cookie, possible, size) != B_OK) {
printf("Error getting the possible configurations\n");
break;
}
fList.AddItem(new DevicesInfo(info, current, possible));
}
}
void
DevicesWindow::UpdateDeviceInfo()
{
DeviceItem *item = (DeviceItem *)outline->ItemAt(outline->CurrentSelection());
if (item && is_instance_of(item, DeviceItem) ) {
DevicesInfo *deviceInfo = item->GetInfo();
struct device_configuration *current = deviceInfo->GetCurrent();
resource_descriptor r;
{
BString text = "IRQs: ";
bool first = true;
int32 num = count_resource_descriptors_of_type(current, B_IRQ_RESOURCE);
for (int32 i=0;i<num;i++) {
get_nth_resource_descriptor_of_type(current, i, B_IRQ_RESOURCE,
&r, sizeof(resource_descriptor));
uint32 mask = r.d.m.mask;
int i = 0;
if (!mask)
continue;
for (;mask;mask>>=1,i++)
if (mask & 1) {
char value[50];
sprintf(value, "%s%d", first ? "" : ",", i);
text += value;
first = false;
}
}
stvIRQ->SetText(text.String());
}
{
BString text = "DMAs: ";
bool first = true;
int32 num = count_resource_descriptors_of_type(current, B_DMA_RESOURCE);
for (int32 i=0;i<num;i++) {
get_nth_resource_descriptor_of_type(current, i, B_DMA_RESOURCE,
&r, sizeof(resource_descriptor));
uint32 mask = r.d.m.mask;
int i = 0;
if (!mask)
continue;
for (;mask;mask>>=1,i++)
if (mask & 1) {
char value[50];
sprintf(value, "%s%d", first ? "" : ",", i);
text += value;
first = false;
}
}
stvDMA->SetText(text.String());
}
{
BString text = "IO Ranges: ";
bool first = true;
int32 num = count_resource_descriptors_of_type(current, B_IO_PORT_RESOURCE);
for (int32 i=0;i<num;i++) {
get_nth_resource_descriptor_of_type(current, i, B_IO_PORT_RESOURCE,
&r, sizeof(resource_descriptor));
char value[50];
sprintf(value, "%s0x%04lx - 0x%04lx", first ? "" : ", ", r.d.r.minbase, r.d.r.minbase + r.d.r.len - 1);
text += value;
first = false;
}
if (text.Length()>70) {
text.Truncate(70);
text += "...";
}
stvIORanges->SetText(text.String());
}
{
BString text = "Memory Ranges: ";
bool first = true;
int32 num = count_resource_descriptors_of_type(current, B_MEMORY_RESOURCE);
for (int32 i=0;i<num;i++) {
get_nth_resource_descriptor_of_type(current, i, B_MEMORY_RESOURCE,
&r, sizeof(resource_descriptor));
char value[50];
sprintf(value, "%s0x%06lx - 0x%06lx", first ? "" : ", ", r.d.r.minbase, r.d.r.minbase + r.d.r.len - 1);
text += value;
first = false;
}
if (text.Length()>70) {
text.Truncate(70);
text += "...";
}
stvMemoryRanges->SetText(text.String());
}
btnConfigure->SetEnabled(true);
} else {
stvIRQ->SetText("IRQs: ");
stvDMA->SetText("DMAs: ");
stvIORanges->SetText("IO Ranges: ");
stvMemoryRanges->SetText("Memory Ranges: ");
btnConfigure->SetEnabled(false);
}
}