[haiku-commits] r33640 - in haiku/trunk: build/jam src/apps/devices src/apps/devices/Documentation

  • From: superstippi@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 18 Oct 2009 19:59:07 +0200 (CEST)

Author: stippi
Date: 2009-10-18 19:59:07 +0200 (Sun, 18 Oct 2009)
New Revision: 33640
Changeset: http://dev.haiku-os.org/changeset/33640/haiku

Added:
   haiku/trunk/src/apps/devices/Device.cpp
   haiku/trunk/src/apps/devices/Device.h
   haiku/trunk/src/apps/devices/DevicePCI.cpp
   haiku/trunk/src/apps/devices/DevicePCI.h
   haiku/trunk/src/apps/devices/DevicesApplication.cpp
   haiku/trunk/src/apps/devices/DevicesView.cpp
   haiku/trunk/src/apps/devices/DevicesView.h
   haiku/trunk/src/apps/devices/Documentation/
   haiku/trunk/src/apps/devices/Documentation/Design.txt
   haiku/trunk/src/apps/devices/Documentation/Specification.txt
   haiku/trunk/src/apps/devices/Documentation/Todo.txt
   haiku/trunk/src/apps/devices/PropertyList.cpp
   haiku/trunk/src/apps/devices/PropertyList.h
   haiku/trunk/src/apps/devices/PropertyListPlain.cpp
   haiku/trunk/src/apps/devices/PropertyListPlain.h
   haiku/trunk/src/apps/devices/dm_wrapper.c
   haiku/trunk/src/apps/devices/dm_wrapper.h
Removed:
   haiku/trunk/src/apps/devices/ConfigurationWindow.cpp
   haiku/trunk/src/apps/devices/Devices.cpp
   haiku/trunk/src/apps/devices/DevicesInfo.cpp
   haiku/trunk/src/apps/devices/DevicesInfo.h
   haiku/trunk/src/apps/devices/DevicesWindow.cpp
   haiku/trunk/src/apps/devices/DevicesWindows.h
   haiku/trunk/src/apps/devices/ModemWindow.cpp
   haiku/trunk/src/apps/devices/cm_wrapper.c
   haiku/trunk/src/apps/devices/cm_wrapper.h
Modified:
   haiku/trunk/build/jam/HaikuImage
   haiku/trunk/src/apps/devices/Devices.rdef
   haiku/trunk/src/apps/devices/Jamfile
Log:
Patch by Pieter Panman:
* Rewrote Devices application. -> Thanks a bunch!! Nice work!
* Put Devices onto the image.

Changes by myself:
* Merge some code from the old "preflet" which the new app still relied on.
* Fixed some coding style issues. I didn't review all of the code yet, though.


Modified: haiku/trunk/build/jam/HaikuImage
===================================================================
--- haiku/trunk/build/jam/HaikuImage    2009-10-18 15:40:39 UTC (rev 33639)
+++ haiku/trunk/build/jam/HaikuImage    2009-10-18 17:59:07 UTC (rev 33640)
@@ -62,9 +62,9 @@
        zdiff zforce zgrep zip zipcloak <bin>zipgrep zipnote zipsplit zmore znew
 ;
 
-SYSTEM_APPS = AboutSystem ActivityMonitor CharacterMap CodyCam DeskCalc 
DiskProbe
-       DiskUsage DriveSetup CDPlayer Expander Icon-O-Matic Installer LaunchBox
-       Magnify Mail MediaConverter MediaPlayer MidiPlayer NetworkStatus
+SYSTEM_APPS = AboutSystem ActivityMonitor CharacterMap CodyCam DeskCalc Devices
+       DiskProbe DiskUsage DriveSetup CDPlayer Expander Icon-O-Matic Installer
+       LaunchBox Magnify Mail MediaConverter MediaPlayer MidiPlayer 
NetworkStatus
        PackageInstaller People PoorMan PowerStatus ProcessController Screenshot
        ShowImage SoundRecorder StyledEdit Terminal TextSearch TV Workspaces
 ;
@@ -304,8 +304,8 @@
 # Deskbar Application links
 AddDirectoryToHaikuImage home config be Applications ;
 DESKBAR_APPLICATIONS = ActivityMonitor CharacterMap CodyCam CDPlayer DeskCalc
-       DiskProbe DriveSetup DiskUsage Expander Icon-O-Matic Installer Magnify
-       Mail MediaConverter MediaPlayer MidiPlayer People PoorMan Screenshot
+       Devices DiskProbe DriveSetup DiskUsage Expander Icon-O-Matic Installer
+       Magnify Mail MediaConverter MediaPlayer MidiPlayer People PoorMan 
Screenshot
        SoundRecorder StyledEdit Terminal TV
 ;
 local linkTarget ;

Added: haiku/trunk/src/apps/devices/Device.cpp
===================================================================
--- haiku/trunk/src/apps/devices/Device.cpp                             (rev 0)
+++ haiku/trunk/src/apps/devices/Device.cpp     2009-10-18 17:59:07 UTC (rev 
33640)
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2008-2009 Haiku Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Pieter Panman
+ */
+
+
+#include "Device.h"
+
+#include <iostream>
+
+
+// This list comes from the pciid list, except for the last one
+const char* kCategoryString[] = {
+       "Unclassified device",                                  // 0x00
+       "Mass storage controller",                              // 0x01
+       "Network controller",                                   // 0x02
+       "Display controller",                                   // 0x03
+       "Multimedia controller",                                // 0x04
+       "Memory controller",                                    // 0x05
+       "Bridge",                                                               
// 0x06
+       "Communication controller",                     // 0x07
+       "Generic system peripheral",                    // 0x08
+       "Input device controller",                      // 0x09
+       "Docking station",                                      // 0x0a
+       "Processor",                                                    // 0x0b
+       "Serial bus controller",                                // 0x0c
+       "Wireless controller",                                  // 0x0d
+       "Intelligent controller",                               // 0x0e
+       "Satellite communications controller",  // 0x0f
+       "Encryption controller",                                // 0x10
+       "Signal processing controller",                 // 0x11
+       "Computer"                                                              
// 0x12 (added later)
+};
+
+
+Device::Device(Device* physicalParent, BusType busType, Category category,
+                       const BString& name, const BString& manufacturer,
+                       const BString& driverUsed, const BString& 
devPathsPublished)
+       :
+       BStringItem(name.String()),
+       fBusType(busType),
+       fCategory(category),
+       fPhysicalParent(physicalParent)
+{
+       SetAttribute("Device name", name);
+       SetAttribute("Manufacturer", manufacturer);
+       SetAttribute("Driver used", driverUsed);
+       SetAttribute("Device paths", devPathsPublished);
+}
+
+
+Device::~Device()
+{
+}
+
+
+void
+Device::SetAttribute(const BString& name, const BString& value)
+{
+       if (name == "Device name") {
+               SetText(value.String());
+       }
+       fAttributeMap[name] = value;
+}
+
+
+Attributes
+Device::GetBasicAttributes()
+{
+       Attributes attributes;
+       attributes.push_back(Attribute("Device name:", GetName()));
+       attributes.push_back(Attribute("Manufacturer:", GetManufacturer()));
+       return attributes;
+}
+
+
+Attributes
+Device::GetBusAttributes()
+{
+       Attributes attributes;
+       attributes.push_back(Attribute("None", ""));
+       return attributes;
+}
+
+
+Attributes
+Device::GetAllAttributes()
+{
+       Attributes attributes;
+       AttributeMapIterator iter;
+       for (iter = fAttributeMap.begin(); iter != fAttributeMap.end(); iter++) 
{
+               attributes.push_back(Attribute(iter->first, iter->second));
+       }
+       return attributes;
+}
+
+
+BString
+Device::GetBasicStrings()
+{
+       BString str;
+       str << "Device Name\t\t\t\t: " << GetName() << "\n";
+       str << "Manufacturer\t\t\t: " << GetManufacturer() << "\n";
+       str << "Driver used\t\t\t\t: " << GetDriverUsed() << "\n";
+       str << "Device paths\t: " << GetDevPathsPublished();
+       return str;
+}
+
+BString
+Device::GetBusStrings()
+{
+       return "None";
+}
+
+
+BString
+Device::GetAllStrings()
+{
+       BString str;
+       AttributeMapIterator iter;
+       for (iter = fAttributeMap.begin(); iter != fAttributeMap.end(); iter++) 
{
+               str << iter->first << " : " << iter->second << "\n";
+       }
+       return str;
+}

Added: haiku/trunk/src/apps/devices/Device.h
===================================================================
--- haiku/trunk/src/apps/devices/Device.h                               (rev 0)
+++ haiku/trunk/src/apps/devices/Device.h       2009-10-18 17:59:07 UTC (rev 
33640)
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2008-2009 Haiku Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Pieter Panman
+ */
+#ifndef DEVICE_H
+#define DEVICE_H
+
+
+#include <map>
+#include <vector>
+
+#include <String.h>
+#include <StringItem.h>
+
+extern "C" {
+#include "dm_wrapper.h"
+}
+
+
+typedef enum {
+       BUS_ISA = 1,
+       BUS_PCI,
+       BUS_SCSI,
+       BUS_NONE
+} BusType;
+
+
+struct Attribute {
+                       Attribute(BString name, BString value)
+                               { fName = name; fValue = value; }
+       BString fName;
+       BString fValue;
+};
+
+
+typedef std::map<BString, BString>::const_iterator AttributeMapIterator;
+typedef std::map<BString, BString> AttributeMap;
+typedef std::pair<BString, BString> AttributePair;
+typedef std::vector<Attribute> Attributes;
+
+
+typedef enum {
+       CAT_NONE = 0,
+       CAT_BUS = 6,
+       CAT_COMPUTER = 0x12
+} Category;
+
+
+extern const char* kCategoryString[];
+
+
+class Device : public BStringItem {
+public:
+                                                       Device(Device* 
physicalParent,
+                                                               BusType 
busType=BUS_NONE, 
+                                                               Category 
category=CAT_NONE, 
+                                                               const BString& 
name = "unknown",
+                                                               const BString& 
manufacturer = "unknown",
+                                                               const BString& 
driverUsed = "unknown",
+                                                               const BString& 
devPathsPublished = "unknown");
+       virtual                                 ~Device();
+
+       virtual BString                 GetName()
+                                                               { return 
fAttributeMap["Device name"]; }
+       virtual BString                 GetManufacturer()
+                                                               { return 
fAttributeMap["Manufacturer"]; }
+       virtual BString                 GetDriverUsed()
+                                                               { return 
fAttributeMap["Driver used"]; }
+       virtual BString                 GetDevPathsPublished()
+                                                               { return 
fAttributeMap["Device paths"]; }
+       virtual Category                GetCategory() const
+                                                               { return 
fCategory; }
+       virtual Device*                 GetPhysicalParent() const
+                                                               { return 
fPhysicalParent; }
+       virtual BusType                 GetBusType() const
+                                                               { return 
fBusType; }
+
+       virtual Attributes              GetBasicAttributes();
+       virtual Attributes              GetBusAttributes();
+       virtual Attributes              GetAllAttributes();
+
+       virtual BString                 GetBasicStrings();
+       virtual BString                 GetBusStrings();
+       virtual BString                 GetAllStrings();
+       
+       virtual BString                 GetBusTabName()
+                                                               { return "Bus 
Information"; }
+
+       virtual Attribute               GetAttribute(const BString& name)
+                                                               { return 
Attribute(name.String(),
+                                                                        
fAttributeMap[name]); }
+
+       virtual void                    SetAttribute(const BString& name,
+                                                               const BString& 
value);
+
+       virtual void                    InitFromAttributes() { return; }
+
+protected:
+                       AttributeMap    fAttributeMap;
+                       BusType                 fBusType;
+                       Category                fCategory;
+                       Device*                 fPhysicalParent;
+};
+
+#endif /* DEVICE_H */
+

Added: haiku/trunk/src/apps/devices/DevicePCI.cpp
===================================================================
--- haiku/trunk/src/apps/devices/DevicePCI.cpp                          (rev 0)
+++ haiku/trunk/src/apps/devices/DevicePCI.cpp  2009-10-18 17:59:07 UTC (rev 
33640)
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2008-2009 Haiku Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Pieter Panman
+ */
+
+
+#include <sstream>
+
+#include "DevicePCI.h"
+
+extern "C" {
+#include "dm_wrapper.h"
+#include "pcihdr.h"
+#include "pci-utils.h"
+}
+
+
+DevicePCI::DevicePCI(Device* parent)
+       :
+       Device(parent),
+       fClassBaseId(0),
+       fClassSubId(0),
+       fClassApiId(0),
+       fVendorId(0),
+       fDeviceId(0),
+       fSubsystemVendorId(0),
+       fSubSystemId(0)
+{
+}
+
+
+DevicePCI::~DevicePCI()
+{
+}
+
+
+BString ToHex(uint16 num)
+{
+       std::stringstream ss;
+       ss.flags(std::ios::hex | std::ios::showbase);
+       ss << num;
+       return BString(ss.str().c_str());
+}
+
+
+void
+DevicePCI::InitFromAttributes()
+{
+       // Process the attributes
+       fClassBaseId = atoi(fAttributeMap[B_DEVICE_TYPE].String());
+       fClassSubId = atoi(fAttributeMap[B_DEVICE_SUB_TYPE].String());
+       fClassApiId = atoi(fAttributeMap[B_DEVICE_INTERFACE].String());
+       fVendorId = atoi(fAttributeMap[B_DEVICE_VENDOR_ID].String());
+       fDeviceId = atoi(fAttributeMap[B_DEVICE_ID].String());
+
+       // Looks better in Hex, so rewrite
+       fAttributeMap[B_DEVICE_TYPE] = ToHex(fClassBaseId);
+       fAttributeMap[B_DEVICE_SUB_TYPE] = ToHex(fClassSubId);
+       fAttributeMap[B_DEVICE_INTERFACE] = ToHex(fClassApiId);
+       fAttributeMap[B_DEVICE_VENDOR_ID] = ToHex(fVendorId);
+       fAttributeMap[B_DEVICE_ID] = ToHex(fDeviceId);
+
+       // Fetch ClassInfo      
+       char classInfo[64];
+       get_class_info(fClassBaseId, fClassSubId, fClassApiId, classInfo, 
sizeof(classInfo));
+       
+       // Fetch ManufacturerName
+       BString ManufacturerName;
+       const char *venShort;
+       const char *venFull;
+       get_vendor_info(fVendorId, &venShort, &venFull);
+       if (!venShort && !venFull) {
+               ManufacturerName << "Unkown";
+       } else if (venShort && venFull) {
+               ManufacturerName << venFull << "(" << venShort << ")";
+       } else {
+               ManufacturerName << (venShort ? venShort : venFull);
+       }
+       
+       // Fetch DeviceName
+       BString DeviceName;
+       const char *devShort;
+       const char *devFull;
+       get_device_info(fVendorId, fDeviceId, fSubsystemVendorId, fSubSystemId, 
&devShort, &devFull);
+       if (!devShort && !devFull) {
+               DeviceName << "Unknown";
+       } else if (devShort && devFull) {
+               DeviceName << devFull << "(" << devShort << ")";
+       } else {
+               DeviceName << (devShort ? devShort : devFull);
+       }
+       
+       SetAttribute("Device name", DeviceName);
+       SetAttribute("Manufacturer", ManufacturerName);
+       SetAttribute("Driver used", "Not implemented");
+       SetAttribute("Device paths", "Not implemented");
+       SetAttribute("Class Info", classInfo);
+       fCategory = (Category)fClassBaseId;
+       BString outlineName;
+       outlineName << ManufacturerName << " " << DeviceName;
+       SetText(outlineName.String());
+}
+
+
+Attributes
+DevicePCI::GetBusAttributes()
+{
+       Attributes attributes;
+       attributes.push_back(GetAttribute(B_DEVICE_TYPE));
+       attributes.push_back(GetAttribute(B_DEVICE_SUB_TYPE));
+       attributes.push_back(GetAttribute(B_DEVICE_INTERFACE));
+       attributes.push_back(GetAttribute(B_DEVICE_VENDOR_ID));
+       attributes.push_back(GetAttribute(B_DEVICE_ID));
+       return attributes;
+}
+
+
+BString
+DevicePCI::GetBusStrings()
+{
+       BString str;
+       str << "Class Info:\t\t\t\t: " << fAttributeMap["Class Info"];
+       return str;
+}

Added: haiku/trunk/src/apps/devices/DevicePCI.h
===================================================================
--- haiku/trunk/src/apps/devices/DevicePCI.h                            (rev 0)
+++ haiku/trunk/src/apps/devices/DevicePCI.h    2009-10-18 17:59:07 UTC (rev 
33640)
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008-2009 Haiku Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Pieter Panman
+ */
+#ifndef DEVICEPCI_H
+#define DEVICEPCI_H
+
+
+#include "Device.h"
+
+
+class DevicePCI : public Device {
+public:
+                                               DevicePCI(Device* parent);
+       virtual                         ~DevicePCI();
+       virtual Attributes      GetBusAttributes();
+       virtual BString         GetBusStrings();
+       virtual void            InitFromAttributes();
+       
+       virtual BString         GetBusTabName()
+                                                       { return "PCI 
Information"; }
+
+private:
+       uint16                          fClassBaseId;
+       uint16                          fClassSubId;
+       uint16                          fClassApiId;
+       uint16                          fVendorId;
+       uint16                          fDeviceId;
+       uint16                          fSubsystemVendorId;
+       uint16                          fSubSystemId;
+};
+
+#endif /* DEVICEPCI_H */

Modified: haiku/trunk/src/apps/devices/Devices.rdef
===================================================================
--- haiku/trunk/src/apps/devices/Devices.rdef   2009-10-18 15:40:39 UTC (rev 
33639)
+++ haiku/trunk/src/apps/devices/Devices.rdef   2009-10-18 17:59:07 UTC (rev 
33640)
@@ -1,5 +1,5 @@
 
-resource app_signature "application/x-vnd.Haiku.Devices";
+resource app_signature "application/x-vnd.Haiku-Devices";
 
 resource app_version
 {
@@ -9,12 +9,12 @@
 
        /* 0 = development      1 = alpha                       2 = beta
           3 = gamma            4 = golden master       5 = final */
-       variety = 2,
+       variety = 1,
 
        internal = 0,
 
        short_info = "Devices", 
-       long_info  = "Devices ©2002-2009 Haiku"
+       long_info  = "Devices ©2009 Haiku"
 };
 
 resource app_flags B_SINGLE_LAUNCH;

Added: haiku/trunk/src/apps/devices/DevicesApplication.cpp
===================================================================
--- haiku/trunk/src/apps/devices/DevicesApplication.cpp                         
(rev 0)
+++ haiku/trunk/src/apps/devices/DevicesApplication.cpp 2009-10-18 17:59:07 UTC 
(rev 33640)
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2008-2009 Haiku Inc. All rights reserved.
+ * Distributed under the terms of the MIT license.
+ *
+ * Authors:
+ *             Pieter Panman
+ */
+
+#include <Alert.h>
+#include <Application.h>
+#include <TextView.h>
+
+#include "DevicesView.h"
+
+
+class DevicesApplication : public BApplication {
+public:
+                                                               
DevicesApplication();
+       virtual void                            AboutRequested();
+       static  void                            ShowAbout();
+};
+
+
+class DevicesWindow : public BWindow {
+public:
+                                                               DevicesWindow();
+       virtual void                            MessageReceived(BMessage* 
message);
+private:
+                       DevicesView*            fDevicesView;
+};
+
+
+DevicesApplication::DevicesApplication()
+       :
+       BApplication("application/x-vnd.Haiku-Devices")
+{
+       DevicesWindow* window = new DevicesWindow();
+       window->CenterOnScreen();
+       window->Show();
+}
+
+
+void
+DevicesApplication::AboutRequested()
+{
+       ShowAbout();
+}
+
+
+void
+DevicesApplication::ShowAbout()
+{
+       BAlert* alert = new BAlert("about", "Devices\n"
+               "\twritten by Pieter Panman\n"
+               "\n"
+               "\tBased on listdev by Jérôme Duval\n"
+               "\tand the previous Devices preference\n"
+               "\tby Jérôme Duval and Sikosis\n"
+               "\tCopyright 2009, Haiku Inc.\n", "Ok");
+       BTextView* view = alert->TextView();
+       BFont font;
+
+       view->SetStylable(true);
+
+       view->GetFont(&font);
+       font.SetSize(18);
+       font.SetFace(B_BOLD_FACE);
+       view->SetFontAndColor(0, 7, &font);
+
+       alert->Go();
+}
+
+
+DevicesWindow::DevicesWindow()
+       :
+       BWindow(BRect(50, 50, 750, 550), "Devices", B_TITLED_WINDOW,
+               B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS
+                       | B_QUIT_ON_WINDOW_CLOSE)
+{
+       float minWidth;
+       float maxWidth;
+       float minHeight;
+       float maxHeight;
+       GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight);
+       minWidth = 600;
+       minHeight = 300;
+       SetSizeLimits(minWidth, maxWidth, minHeight, maxHeight);
+       fDevicesView = new DevicesView(Bounds());
+       AddChild(fDevicesView);
+}
+
+
+void
+DevicesWindow::MessageReceived(BMessage* message)
+{
+       switch (message->what) {
+               case kMsgRefresh:
+               case kMsgReportCompatibility:
+               case kMsgGenerateSysInfo:
+               case kMsgSelectionChanged:
+               case kMsgOrderCategory:
+               case kMsgOrderConnection:
+                       fDevicesView->MessageReceived(message);
+                       break;
+
+               default:
+                       BWindow::MessageReceived(message);
+                       break;
+       }
+}
+
+
+int
+main()
+{
+       DevicesApplication app;
+       app.Run();
+       return 0;
+}

Added: haiku/trunk/src/apps/devices/DevicesView.cpp
===================================================================
--- haiku/trunk/src/apps/devices/DevicesView.cpp                                
(rev 0)
+++ haiku/trunk/src/apps/devices/DevicesView.cpp        2009-10-18 17:59:07 UTC 
(rev 33640)
@@ -0,0 +1,392 @@
+/*
+ * Copyright 2008-2009 Haiku Inc. All rights reserved.
+ * Distributed under the terms of the MIT license.
+ *
+ * Authors:
+ *             Pieter Panman
+ */
+
+
+#include <Application.h>
+#include <MenuBar.h>
+
+#include "DevicesView.h"
+
+
+DevicesView::DevicesView(const BRect& rect)
+       : BView(rect, "DevicesView", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS)
+{
+       CreateLayout();
+       RescanDevices();
+       RebuildDevicesOutline();
+}
+
+
+void
+DevicesView::CreateLayout()
+{
+       SetLayout(new BGroupLayout(B_VERTICAL));
+
+       BMenuBar* menuBar = new BMenuBar("menu");
+       BMenu* menu = new BMenu("Devices");
+       BMenuItem* item;
+       menu->AddItem(new BMenuItem("Refresh Devices", new 
BMessage(kMsgRefresh), 'R'));
+       menu->AddItem(item = new BMenuItem("Report Compatibility",
+               new BMessage(kMsgReportCompatibility)));
+       item->SetEnabled(false);
+       menu->AddItem(item = new BMenuItem("Generate System Information",
+               new BMessage(kMsgGenerateSysInfo)));
+       item->SetEnabled(false);
+       menu->AddSeparatorItem();
+       menu->AddItem(item = new BMenuItem("About Devices" B_UTF8_ELLIPSIS,
+               new BMessage(B_ABOUT_REQUESTED)));
+       menu->AddSeparatorItem();
+       menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 
'Q'));
+       menu->SetTargetForItems(this);
+       item->SetTarget(be_app);
+       menuBar->AddItem(menu);
+
+       fDevicesOutline = new BOutlineListView("devices_list");
+       fDevicesOutline->SetTarget(this);
+       fDevicesOutline->SetSelectionMessage(new 
BMessage(kMsgSelectionChanged));
+
+       BScrollView *scrollView = new BScrollView("devicesScrollView",
+               fDevicesOutline, B_WILL_DRAW | B_FRAME_EVENTS, true, true);
+       // Horizontal scrollbar doesn't behave properly like the vertical
+       // scrollbar... If you make the view bigger (exposing a larger 
percentage
+       // of the view), it does not adjust the width of the scroll 'dragger'
+       // why? Bug? In scrollview or in outlinelistview?
+
+       BPopUpMenu* orderByPopupMenu = new BPopUpMenu("orderByMenu");
+       BMenuItem* byCategory = new BMenuItem("category", 
+               new BMessage(kMsgOrderCategory));
+       BMenuItem* byConnection = new BMenuItem("connection",
+               new BMessage(kMsgOrderConnection));
+       byCategory->SetMarked(true);
+       fOrderBy = byCategory->IsMarked() ? ORDER_BY_CATEGORY : 
+               ORDER_BY_CONNECTION;
+       orderByPopupMenu->AddItem(byCategory);
+       orderByPopupMenu->AddItem(byConnection);
+       fOrderByMenu = new BMenuField("Order by:", orderByPopupMenu);
+
+       fTabView = new BTabView("fTabView", B_WIDTH_FROM_LABEL);
+
+       fBasicTab = new BTab();
+       fBasicView = new PropertyListPlain("basicView");
+       fTabView->AddTab(fBasicView, fBasicTab);
+       fBasicTab->SetLabel("Basic Information");
+
+       fDeviceTypeTab = new BTab();
+       fBusView = new PropertyListPlain("busView");
+       fTabView->AddTab(fBusView, fDeviceTypeTab);
+       fDeviceTypeTab->SetLabel("Bus");
+
+       fDetailedTab = new BTab();
+       fAttributesView = new PropertyList("attributesView");
+       fTabView->AddTab(fAttributesView, fDetailedTab);
+       fDetailedTab->SetLabel("Detailed");
+
+       AddChild(BGroupLayoutBuilder(B_VERTICAL,0)
+                               .Add(menuBar)
+                               .Add(BSplitLayoutBuilder(B_HORIZONTAL, 5)
+                                       .Add(BGroupLayoutBuilder(B_VERTICAL, 5)
+                                               .Add(fOrderByMenu, 1)
+                                               .Add(scrollView, 2)
+                                       )
+                                       .Add(fTabView, 2)
+                                       .SetInsets(5, 5, 5, 5)
+                               )
+                       );
+}
+
+
+void
+DevicesView::RescanDevices()
+{
+       // Empty the outline and delete the devices in the list, incl. 
categories
+       fDevicesOutline->MakeEmpty();
+       DeleteDevices();
+       DeleteCategoryMap();
+
+       // Fill the devices list
+       status_t error;
+       device_node_cookie rootCookie;
+       if ((error = init_dm_wrapper()) < 0) {
+               std::cerr << "Error initializing device manager: " << 
strerror(error)
+                       << std::endl;
+               return;
+       }
+
+       get_root(&rootCookie);
+       AddDeviceAndChildren(&rootCookie, NULL);
+
+       uninit_dm_wrapper();
+
+       CreateCategoryMap();
+}
+
+
+void
+DevicesView::DeleteDevices()
+{
+       while(fDevices.size() > 0) {
+               delete fDevices.back();
+               fDevices.pop_back();
+       }
+}
+
+
+void
+DevicesView::CreateCategoryMap()
+{
+       CategoryMapIterator iter;
+       for (unsigned int i = 0; i < fDevices.size(); i++) {
+               Category category = fDevices[i]->GetCategory();
+               const char* categoryName = kCategoryString[category];
+
+               iter = fCategoryMap.find(category);
+               if( iter == fCategoryMap.end() ) {
+                       // This category has not yet been added, add it.
+                       fCategoryMap[category] = new Device(NULL, BUS_NONE, 
CAT_NONE,
+                               categoryName);
+               }
+       }
+}
+
+
+void
+DevicesView::DeleteCategoryMap()
+{
+       CategoryMapIterator iter;
+       for(iter = fCategoryMap.begin(); iter != fCategoryMap.end(); iter++) {
+               delete iter->second;
+       }
+       fCategoryMap.clear();
+}
+
+
+int
+DevicesView::SortItemsCompare(const BListItem *item1,
+       const BListItem *item2)
+{
+       const BStringItem* stringItem1 = dynamic_cast<const 
BStringItem*>(item1);
+       const BStringItem* stringItem2 = dynamic_cast<const 
BStringItem*>(item2);
+       if (!(stringItem1 && stringItem2)) {
+               // is this check necessary?
+               std::cerr << "Could not cast BListItem to BStringItem, file a 
bug\n";
+               return 0;
+       }
+       return Compare(stringItem1->Text(),stringItem2->Text());
+}
+
+
+void
+DevicesView::RebuildDevicesOutline()
+{
+       // Rearranges existing Devices into the proper hierarchy
+       fDevicesOutline->MakeEmpty();
+
+       if (fOrderBy == ORDER_BY_CONNECTION) {
+               for (unsigned int i = 0; i < fDevices.size(); i++) {
+                       if (fDevices[i]->GetPhysicalParent() == NULL) {
+                               // process each parent device and its children
+                               fDevicesOutline->AddItem(fDevices[i]);
+                               AddChildrenToOutlineByConnection(fDevices[i]);
+                       }
+               }
+       }
+       else if (fOrderBy == ORDER_BY_CATEGORY) {
+               // Add all categories to the outline
+               CategoryMapIterator iter;
+               for (iter = fCategoryMap.begin(); iter != fCategoryMap.end(); 
iter++) {
+                       fDevicesOutline->AddItem(iter->second);
+               }
+
+               // Add all devices under the categories
+               for (unsigned int i = 0; i < fDevices.size(); i++) {
+                       Category category = fDevices[i]->GetCategory();
+
+                       iter = fCategoryMap.find(category);
+                       if(iter == fCategoryMap.end()) {
+                               std::cerr << "Tried to add device without 
category, file a bug\n";
+                               continue;
+                       }
+                       else {
+                               fDevicesOutline->AddUnder(fDevices[i], 
iter->second);
+                       }
+               }
+               fDevicesOutline->SortItemsUnder(NULL, true, SortItemsCompare);
+       }
+       // TODO: Implement BY_BUS
+}
+
+
+void
+DevicesView::AddChildrenToOutlineByConnection(Device* parent)
+{
+       for (unsigned int i = 0; i < fDevices.size(); i++) {
+               if (fDevices[i]->GetPhysicalParent() == parent) {
+                       fDevicesOutline->AddUnder(fDevices[i], parent);
+                       AddChildrenToOutlineByConnection(fDevices[i]);
+               }
+       }
+}
+
+
+void
+DevicesView::AddDeviceAndChildren(device_node_cookie *node, Device* parent)
+{
+       Attributes attributes;
+       Device* newDevice = NULL;
+
+       // Copy all its attributes,
+       // necessary because we can only request them once from the device 
manager
+       char data[256];
+       struct device_attr_info attr;
+       attr.cookie = 0;
+       attr.node_cookie = *node;
+       attr.value.raw.data = data;
+       attr.value.raw.length = sizeof(data);
+
+       while (dm_get_next_attr(&attr) == B_OK) {
+               BString attrString;
+               switch (attr.type) {
+                       case B_STRING_TYPE:
+                               attrString << attr.value.string;
+                               break;
+                       case B_UINT8_TYPE:
+                               attrString << attr.value.ui8;
+                               break;
+                       case B_UINT16_TYPE:
+                               attrString << attr.value.ui16;
+                               break;
+                       case B_UINT32_TYPE:
+                               attrString << attr.value.ui32;
+                               break;
+                       case B_UINT64_TYPE:
+                               attrString << attr.value.ui64;
+                               break;
+                       default:
+                               attrString << "Raw data";
+               }
+               attributes.push_back(Attribute(attr.name, attrString));
+       }
+       
+       // Determine what type of device it is and create it
+       for (unsigned int i = 0; i < attributes.size(); i++) {
+               // Devices Root
+               if (attributes[i].fName == "device/pretty name" 
+                               && attributes[i].fValue == "Devices Root") {
+                       newDevice = new Device(parent, BUS_NONE, CAT_COMPUTER, 
"Computer");
+                       break;
+               }
+               
+               // PCI bus
+               if (attributes[i].fName == "device/pretty name"
+                               && attributes[i].fValue == "PCI") {
+                       newDevice = new Device(parent, BUS_PCI, CAT_BUS, "PCI 
Bus");
+                       break;
+               }
+
+               // ISA bus
+               if (attributes[i].fName == "device/bus"
+                               && attributes[i].fValue == "isa") {
+                       newDevice = new Device(parent, BUS_ISA, CAT_BUS, "ISA 
Bus");
+                       break;
+               }
+
+               // PCI device
+               if (attributes[i].fName == B_DEVICE_BUS
+                               && attributes[i].fValue == "pci") {
+                       newDevice = new DevicePCI(parent);
+                       break;
+               }
+       }
+       
+       if (newDevice == NULL) {
+               newDevice = new Device(parent, BUS_NONE, CAT_NONE, "Unknown 
Device");
+       }
+       
+       // Add its attributes to the device, initialize it and add to the list.
+       for (unsigned int i = 0; i < attributes.size(); i++) {
+               newDevice->SetAttribute(attributes[i].fName, 
attributes[i].fValue);
+       }
+       newDevice->InitFromAttributes();
+       fDevices.push_back(newDevice);
+
+       // Process children
+       status_t err;
+       device_node_cookie child = *node;
+
+       if (get_child(&child) != B_OK)
+               return;
+
+       do {
+               AddDeviceAndChildren(&child, newDevice);
+       } while ((err = get_next_child(&child)) == B_OK);
+}
+
+
+DevicesView::~DevicesView()
+{
+       DeleteDevices();
+}
+
+
+void
+DevicesView::MessageReceived(BMessage *msg)
+{
+       switch (msg->what) {
+               case kMsgSelectionChanged:
+               {
+                       int32 selected = fDevicesOutline->CurrentSelection(0);
+                       if (selected >= 0) {
+                               Device* device = 
(Device*)fDevicesOutline->ItemAt(selected);
+                               
fBasicView->AddAttributes(device->GetBasicAttributes());
+                               
fBusView->AddAttributes(device->GetBusAttributes());
+                               
fAttributesView->AddAttributes(device->GetAllAttributes());
+                               
fDeviceTypeTab->SetLabel(device->GetBusTabName());
+                               // hmm the label doesn't automatically refresh
+                               fTabView->Invalidate();
+                       }
+                       break;
+               }
+
+               case kMsgOrderCategory:
+               {
+                       fOrderBy = ORDER_BY_CATEGORY;
+                       RescanDevices();
+                       RebuildDevicesOutline();
+                       break;
+               }
+
+               case kMsgOrderConnection:
+               {
+                       fOrderBy = ORDER_BY_CONNECTION;
+                       RescanDevices();
+                       RebuildDevicesOutline();
+                       break;
+               }
+
+               case kMsgRefresh:
+               {
+                       RescanDevices();
+                       RebuildDevicesOutline();
+                       break;
+               }
+
+               case kMsgReportCompatibility:
+               {
+                       break;
+               }
+
+               case kMsgGenerateSysInfo:
+               {
+                       break;
+               }
+
+               default:
+                       BView::MessageReceived(msg);
+                       break;

[... truncated: 774 lines follow ...]

Other related posts: