branch merge
This commit is contained in:
@@ -121,7 +121,7 @@ event with a context different from the execution context of the caller. This AP
|
||||
by the ns-3 logging system to report the execution context of each log line.
|
||||
<li><b>Object::DoStart</b>: Users who need to complete their object setup at the start of a simulation
|
||||
can override this virtual method, perform their adhoc setup, and then, must chain up to their parent.
|
||||
<li><b>Aod hoc On-Demand Distance Vector (AODV)</b> routing model,
|
||||
<li><b>Ad hoc On-Demand Distance Vector (AODV)</b> routing model,
|
||||
<a href=http://www.ietf.org/rfc/rfc3561.txt>RFC 3561</a> </li>
|
||||
<li><b>Ipv4::IsDestinationAddress (Ipv4Address address, uint32_t iif)</b> Method added to support checks of whether a destination address should be accepted
|
||||
as one of the host's own addresses. RFC 1122 Strong/Weak end system behavior can be changed with a new attribute (WeakEsModel) in class Ipv4. </li>
|
||||
|
||||
1351
doc/doxygen.conf
1351
doc/doxygen.conf
File diff suppressed because it is too large
Load Diff
@@ -135,7 +135,7 @@ If you want to store a newed object into a smart pointer,
|
||||
we recommend you to use the CreateObject template functions
|
||||
to create the object and store it in a smart pointer to avoid
|
||||
memory leaks. These functions are really small convenience
|
||||
functions and their goal is just is save you a small
|
||||
functions and their goal is just to save you a small
|
||||
bit of typing.
|
||||
|
||||
@subsection CreateObject and Create
|
||||
@@ -292,7 +292,7 @@ For example:
|
||||
factory.Set ("SystemLoss", DoubleValue (3.0));
|
||||
// Create another object
|
||||
Ptr<Object> object = m_factory.Create ();
|
||||
Wend verbatim
|
||||
@end verbatim
|
||||
|
||||
@node Downcasting
|
||||
@section Downcasting
|
||||
|
||||
7
examples/tap/lxc-left.conf
Normal file
7
examples/tap/lxc-left.conf
Normal file
@@ -0,0 +1,7 @@
|
||||
# Container with network virtualized using a pre-configured bridge named br-left and
|
||||
# veth pair virtual network devices
|
||||
lxc.utsname = left
|
||||
lxc.network.type = veth
|
||||
lxc.network.flags = up
|
||||
lxc.network.link = br-left
|
||||
lxc.network.ipv4 = 10.0.0.1/24
|
||||
7
examples/tap/lxc-right.conf
Normal file
7
examples/tap/lxc-right.conf
Normal file
@@ -0,0 +1,7 @@
|
||||
# Container with network virtualized using a pre-configured bridge named br-right and
|
||||
# veth pair virtual network devices
|
||||
lxc.utsname = right
|
||||
lxc.network.type = veth
|
||||
lxc.network.flags = up
|
||||
lxc.network.link = br-right
|
||||
lxc.network.ipv4 = 10.0.0.2/24
|
||||
133
examples/tap/tap-csma-virtual-machine.cc
Normal file
133
examples/tap/tap-csma-virtual-machine.cc
Normal file
@@ -0,0 +1,133 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
//
|
||||
// This is an illustration of how one could use virtualization techniques to
|
||||
// allow running applications on virtual machines talking over simulated
|
||||
// networks.
|
||||
//
|
||||
// The actual steps required to configure the virtual machines can be rather
|
||||
// involved, so we don't go into that here. Please have a look at one of
|
||||
// our HOWTOs on the nsnam wiki for more details about how to get the
|
||||
// system confgured. For an example, have a look at "HOWTO Use Linux
|
||||
// Containers to set up virtual networks" which uses this code as an
|
||||
// example.
|
||||
//
|
||||
// The configuration you are after is explained in great detail in the
|
||||
// HOWTO, but looks like the following:
|
||||
//
|
||||
// +----------+ +----------+
|
||||
// | virtual | | virtual |
|
||||
// | Linux | | Linux |
|
||||
// | Host | | Host |
|
||||
// | | | |
|
||||
// | eth0 | | eth0 |
|
||||
// +----------+ +----------+
|
||||
// | |
|
||||
// +----------+ +----------+
|
||||
// | Linux | | Linux |
|
||||
// | Bridge | | Bridge |
|
||||
// +----------+ +----------+
|
||||
// | |
|
||||
// +------------+ +-------------+
|
||||
// | "tap-left" | | "tap-right" |
|
||||
// +------------+ +-------------+
|
||||
// | n0 n1 |
|
||||
// | +--------+ +--------+ |
|
||||
// +-------| tap | | tap |-------+
|
||||
// | bridge | | bridge |
|
||||
// +--------+ +--------+
|
||||
// | CSMA | | CSMA |
|
||||
// +--------+ +--------+
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// ===============
|
||||
// CSMA LAN 10.0.0
|
||||
//
|
||||
// The CSMA device on node zero is: 10.0.0.1
|
||||
// The CSMA device on node one is: 10.0.0.2
|
||||
//
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TapCsmaVirtualMachineExample");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
//
|
||||
// We are interacting with the outside, real, world. This means we have to
|
||||
// interact in real-time and therefore means we have to use the real-time
|
||||
// simulator and take the time to calculate checksums.
|
||||
//
|
||||
GlobalValue::Bind ("SimulatorImplementationType", StringValue ("ns3::RealtimeSimulatorImpl"));
|
||||
GlobalValue::Bind ("ChecksumEnabled", BooleanValue (true));
|
||||
|
||||
//
|
||||
// Create two ghost nodes. The first will represent the virtual machine host
|
||||
// on the left side of the network; and the second will represent the VM on
|
||||
// the right side.
|
||||
//
|
||||
NodeContainer nodes;
|
||||
nodes.Create (2);
|
||||
|
||||
//
|
||||
// Use a CsmaHelper to get a CSMA channel created, and the needed net
|
||||
// devices installed on both of the nodes. The data rate and delay for the
|
||||
// channel can be set through the command-line parser. For example,
|
||||
//
|
||||
// ./waf --run "tap=csma-virtual-machine --ns3::CsmaChannel::DataRate=10000000"
|
||||
//
|
||||
CsmaHelper csma;
|
||||
NetDeviceContainer devices = csma.Install (nodes);
|
||||
|
||||
//
|
||||
// Use the TapBridgeHelper to connect to the pre-configured tap devices for
|
||||
// the left side. We go with "UseBridge" mode since the CSMA devices support
|
||||
// promiscuous mode and can therefore make it appear that the bridge is
|
||||
// extended into ns-3. The install method essentially bridges the specified
|
||||
// tap to the specified CSMA device.
|
||||
//
|
||||
TapBridgeHelper tapBridge;
|
||||
tapBridge.SetAttribute ("Mode", StringValue ("UseBridge"));
|
||||
tapBridge.SetAttribute ("DeviceName", StringValue ("tap-left"));
|
||||
tapBridge.Install (nodes.Get (0), devices.Get (0));
|
||||
|
||||
//
|
||||
// Connect the right side tap to the right side CSMA device on the right-side
|
||||
// ghost node.
|
||||
//
|
||||
tapBridge.SetAttribute ("DeviceName", StringValue ("tap-right"));
|
||||
tapBridge.Install (nodes.Get (1), devices.Get (1));
|
||||
|
||||
//
|
||||
// Run the simulation for ten minutes to give the user time to play around
|
||||
//
|
||||
Simulator::Stop (Seconds (600.));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
171
examples/tap/tap-wifi-virtual-machine.cc
Normal file
171
examples/tap/tap-wifi-virtual-machine.cc
Normal file
@@ -0,0 +1,171 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
//
|
||||
// This is an illustration of how one could use virtualization techniques to
|
||||
// allow running applications on virtual machines talking over simulated
|
||||
// networks.
|
||||
//
|
||||
// The actual steps required to configure the virtual machines can be rather
|
||||
// involved, so we don't go into that here. Please have a look at one of
|
||||
// our HOWTOs on the nsnam wiki for more details about how to get the
|
||||
// system confgured. For an example, have a look at "HOWTO Use Linux
|
||||
// Containers to set up virtual networks" which uses this code as an
|
||||
// example.
|
||||
//
|
||||
// The configuration you are after is explained in great detail in the
|
||||
// HOWTO, but looks like the following:
|
||||
//
|
||||
// +----------+ +----------+
|
||||
// | virtual | | virtual |
|
||||
// | Linux | | Linux |
|
||||
// | Host | | Host |
|
||||
// | | | |
|
||||
// | eth0 | | eth0 |
|
||||
// +----------+ +----------+
|
||||
// | |
|
||||
// +----------+ +----------+
|
||||
// | Linux | | Linux |
|
||||
// | Bridge | | Bridge |
|
||||
// +----------+ +----------+
|
||||
// | |
|
||||
// +------------+ +-------------+
|
||||
// | "tap-left" | | "tap-right" |
|
||||
// +------------+ +-------------+
|
||||
// | n0 n1 |
|
||||
// | +--------+ +--------+ |
|
||||
// +-------| tap | | tap |-------+
|
||||
// | bridge | | bridge |
|
||||
// +--------+ +--------+
|
||||
// | wifi | | wifi |
|
||||
// +--------+ +--------+
|
||||
// | |
|
||||
// ((*)) ((*))
|
||||
//
|
||||
// Wifi LAN 10.0.0
|
||||
//
|
||||
// ((*))
|
||||
// |
|
||||
// +--------+
|
||||
// | wifi |
|
||||
// +--------+
|
||||
// | access |
|
||||
// | point |
|
||||
// +--------+
|
||||
//
|
||||
// The wifi device on node zero is: 10.0.0.1
|
||||
// The wifi device on node one is: 10.0.0.2
|
||||
// The wifi device (AP) is: 10.0.0.3
|
||||
//
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "ns3/simulator-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/wifi-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TapWifiVirtualMachineExample");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
//
|
||||
// We are interacting with the outside, real, world. This means we have to
|
||||
// interact in real-time and therefore means we have to use the real-time
|
||||
// simulator and take the time to calculate checksums.
|
||||
//
|
||||
GlobalValue::Bind ("SimulatorImplementationType", StringValue ("ns3::RealtimeSimulatorImpl"));
|
||||
GlobalValue::Bind ("ChecksumEnabled", BooleanValue (true));
|
||||
|
||||
//
|
||||
// Create two ghost nodes. The first will represent the virtual machine host
|
||||
// on the left side of the network; and the second will represent the VM on
|
||||
// the right side.
|
||||
//
|
||||
NodeContainer nodes;
|
||||
nodes.Create (2);
|
||||
|
||||
//
|
||||
// We're going to use 802.11 A so set up a wifi helper to reflect that.
|
||||
//
|
||||
WifiHelper wifi = WifiHelper::Default ();
|
||||
wifi.SetStandard (WIFI_PHY_STANDARD_80211a);
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue ("wifia-54mbs"));
|
||||
|
||||
//
|
||||
// No reason for pesky access points, so we'll use an ad-hoc network.
|
||||
//
|
||||
NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
|
||||
wifiMac.SetType ("ns3::AdhocWifiMac");
|
||||
|
||||
//
|
||||
// Configure the physcial layer.
|
||||
//
|
||||
YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
|
||||
YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
|
||||
wifiPhy.SetChannel (wifiChannel.Create ());
|
||||
|
||||
//
|
||||
// Install the wireless devices onto our ghost nodes.
|
||||
//
|
||||
NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, nodes);
|
||||
|
||||
//
|
||||
// We need location information since we are talking about wifi, so add a
|
||||
// constant position to the ghost nodes.
|
||||
//
|
||||
MobilityHelper mobility;
|
||||
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
|
||||
positionAlloc->Add (Vector (0.0, 0.0, 0.0));
|
||||
positionAlloc->Add (Vector (5.0, 0.0, 0.0));
|
||||
mobility.SetPositionAllocator (positionAlloc);
|
||||
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
|
||||
mobility.Install (nodes);
|
||||
|
||||
//
|
||||
// Use the TapBridgeHelper to connect to the pre-configured tap devices for
|
||||
// the left side. We go with "UseLocal" mode since the wifi devices do not
|
||||
// support promiscuous mode (because of their natures0. This is a special
|
||||
// case mode that allows us to extend a linux bridge into ns-3 IFF we will
|
||||
// only see traffic from one other device on that bridge. That is the case
|
||||
// for this configuration.
|
||||
//
|
||||
TapBridgeHelper tapBridge;
|
||||
tapBridge.SetAttribute ("Mode", StringValue ("UseLocal"));
|
||||
tapBridge.SetAttribute ("DeviceName", StringValue ("tap-left"));
|
||||
tapBridge.Install (nodes.Get (0), devices.Get (0));
|
||||
|
||||
//
|
||||
// Connect the right side tap to the right side wifi device on the right-side
|
||||
// ghost node.
|
||||
//
|
||||
tapBridge.SetAttribute ("DeviceName", StringValue ("tap-right"));
|
||||
tapBridge.Install (nodes.Get (1), devices.Get (1));
|
||||
|
||||
//
|
||||
// Run the simulation for ten minutes to give the user time to play around
|
||||
//
|
||||
Simulator::Stop (Seconds (600.));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
@@ -5,5 +5,9 @@ def build(bld):
|
||||
if env['ENABLE_TAP']:
|
||||
obj = bld.create_ns3_program('tap-csma', ['csma', 'tap-bridge', 'internet-stack'])
|
||||
obj.source = 'tap-csma.cc'
|
||||
obj = bld.create_ns3_program('tap-csma-virtual-machine', ['csma', 'tap-bridge', 'internet-stack'])
|
||||
obj.source = 'tap-csma-virtual-machine.cc'
|
||||
obj = bld.create_ns3_program('tap-wifi-virtual-machine', ['csma', 'tap-bridge', 'internet-stack'])
|
||||
obj.source = 'tap-wifi-virtual-machine.cc'
|
||||
obj = bld.create_ns3_program('tap-wifi-dumbbell', ['wifi', 'csma', 'point-to-point', 'tap-bridge', 'internet-stack'])
|
||||
obj.source = 'tap-wifi-dumbbell.cc'
|
||||
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
|
||||
/**
|
||||
* \brief creates a traceBasedStreamer application
|
||||
* \param dataSize ip the destination ip address to which the stream will be sent
|
||||
* \param ip the destination ip address to which the stream will be sent
|
||||
* \param port the destination udp port to which the stream will be sent
|
||||
* \param traceFile a path to an MPEG4 trace file formatted as follows:
|
||||
* FrameNo Frametype Time[ms] Length [byte]
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
|
||||
/**
|
||||
* \brief set the trace file to be used by the application
|
||||
* \param traceFile a path to an MPEG4 trace file formatted as follows:
|
||||
* \param filename a path to an MPEG4 trace file formatted as follows:
|
||||
* Frame No Frametype Time[ms] Length [byte]
|
||||
* Frame No Frametype Time[ms] Length [byte]
|
||||
* ...
|
||||
|
||||
@@ -130,6 +130,9 @@ public:
|
||||
* time zone from UTC/GMT. For example, Pacific Standard Time in the US is
|
||||
* GMT-8, so one would enter -8 for that correction. Defaults to 0 (UTC).
|
||||
*
|
||||
* \param swapMode Flag indicating a difference in endianness of the
|
||||
* writing system. Defaults to false.
|
||||
*
|
||||
* \return false if the open succeeds, true otherwise.
|
||||
*
|
||||
* \warning Calling this method on an existing file will result in the loss
|
||||
@@ -256,7 +259,7 @@ public:
|
||||
* \param f1 First PCAP file name
|
||||
* \param f2 Second PCAP file name
|
||||
* \param sec [out] Time stamp of first different packet, seconds. Undefined if files doesn't differ.
|
||||
* \param uses [out] Time stamp of first different packet, microseconds. Undefined if files doesn't differ.
|
||||
* \param usec [out] Time stamp of first different packet, microseconds. Undefined if files doesn't differ.
|
||||
* \param snapLen Snap length (if used)
|
||||
*/
|
||||
static bool Diff (std::string const & f1, std::string const & f2,
|
||||
|
||||
@@ -252,7 +252,9 @@ public:
|
||||
*/
|
||||
double GetSystemLoss (void) const;
|
||||
/**
|
||||
* \Set the model antenna height above the node's Z coordinate
|
||||
* \param heightAboveZ the model antenna height above the node's Z coordinate
|
||||
*
|
||||
* Set the model antenna height above the node's Z coordinate
|
||||
*/
|
||||
void SetHeightAboveZ (double heightAboveZ);
|
||||
|
||||
|
||||
@@ -1,15 +1,35 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Faker Moatamri <faker.moatamri@sophia.inria.fr>
|
||||
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
#include "attribute-default-iterator.h"
|
||||
#include "ns3/type-id.h"
|
||||
#include "ns3/attribute.h"
|
||||
#include "ns3/object-vector.h"
|
||||
#include "ns3/pointer.h"
|
||||
#include "ns3/global-value.h"
|
||||
#include "ns3/string.h"
|
||||
|
||||
namespace ns3 {
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
AttributeDefaultIterator::~AttributeDefaultIterator ()
|
||||
{}
|
||||
{
|
||||
}
|
||||
void
|
||||
AttributeDefaultIterator::Iterate (void)
|
||||
{
|
||||
@@ -17,72 +37,87 @@ AttributeDefaultIterator::Iterate (void)
|
||||
{
|
||||
TypeId tid = TypeId::GetRegistered (i);
|
||||
if (tid.MustHideFromDocumentation ())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool calledStart = false;
|
||||
for (uint32_t j = 0; j < tid.GetAttributeN (); j++)
|
||||
{
|
||||
uint32_t flags = tid.GetAttributeFlags (j);
|
||||
if (!(flags & TypeId::ATTR_CONSTRUCT))
|
||||
{
|
||||
// we can't construct the attribute, so, there is no
|
||||
// initial value for the attribute
|
||||
continue;
|
||||
}
|
||||
Ptr<const AttributeAccessor> accessor = tid.GetAttributeAccessor (j);
|
||||
if (accessor == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!accessor->HasSetter ())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (j);
|
||||
if (checker == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Ptr<const AttributeValue> value = tid.GetAttributeInitialValue (j);
|
||||
if (value == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Ptr<const ObjectVectorValue> vector = DynamicCast<const ObjectVectorValue> (value);
|
||||
if (vector != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Ptr<const PointerValue> pointer = DynamicCast<const PointerValue> (value);
|
||||
if (pointer != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!calledStart)
|
||||
{
|
||||
StartVisitTypeId (tid.GetName ());
|
||||
}
|
||||
VisitAttribute (tid.GetAttributeName (j),
|
||||
value->SerializeToString (checker));
|
||||
calledStart = true;
|
||||
}
|
||||
{
|
||||
uint32_t flags = tid.GetAttributeFlags (j);
|
||||
if (!(flags & TypeId::ATTR_CONSTRUCT))
|
||||
{
|
||||
// we can't construct the attribute, so, there is no
|
||||
// initial value for the attribute
|
||||
continue;
|
||||
}
|
||||
Ptr<const AttributeAccessor> accessor = tid.GetAttributeAccessor (j);
|
||||
//No accessor, go to next attribute
|
||||
if (accessor == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!accessor->HasSetter ())
|
||||
{
|
||||
//skip this attribute it doesn't have an setter
|
||||
continue;
|
||||
}
|
||||
Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (j);
|
||||
if (checker == 0)
|
||||
{
|
||||
//skip, it doesn't have a checker
|
||||
continue;
|
||||
}
|
||||
Ptr<const AttributeValue> value = tid.GetAttributeInitialValue (j);
|
||||
if (value == 0)
|
||||
{
|
||||
//No value, check next attribute
|
||||
continue;
|
||||
}
|
||||
Ptr<const ObjectVectorValue> vector = DynamicCast<const ObjectVectorValue> (value);
|
||||
if (vector != 0)
|
||||
{
|
||||
//a vector value, won't take it
|
||||
continue;
|
||||
}
|
||||
Ptr<const PointerValue> pointer = DynamicCast<const PointerValue> (value);
|
||||
if (pointer != 0)
|
||||
{
|
||||
//pointer value, won't take it
|
||||
continue;
|
||||
}
|
||||
//We take only values, no pointers or vectors
|
||||
if (!calledStart)
|
||||
{
|
||||
StartVisitTypeId (tid.GetName ());
|
||||
}
|
||||
VisitAttribute (tid, tid.GetAttributeName (j), value->SerializeToString (checker), j);
|
||||
calledStart = true;
|
||||
}
|
||||
if (calledStart)
|
||||
{
|
||||
EndVisitTypeId ();
|
||||
}
|
||||
{
|
||||
EndVisitTypeId ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AttributeDefaultIterator::StartVisitTypeId (std::string name)
|
||||
{}
|
||||
{
|
||||
}
|
||||
void
|
||||
AttributeDefaultIterator::EndVisitTypeId (void)
|
||||
{}
|
||||
void
|
||||
AttributeDefaultIterator::VisitAttribute (std::string name, std::string defaultValue)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AttributeDefaultIterator::DoVisitAttribute (std::string name, std::string defaultValue)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AttributeDefaultIterator::VisitAttribute (TypeId tid, std::string name, std::string defaultValue, uint32_t index)
|
||||
{
|
||||
DoVisitAttribute (name, defaultValue);
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -1,6 +1,26 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Faker Moatamri <faker.moatamri@sophia.inria.fr>
|
||||
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
#ifndef ATTRIBUTE_DEFAULT_ITERATOR_H
|
||||
#define ATTRIBUTE_DEFAULT_ITERATOR_H
|
||||
|
||||
#include "ns3/type-id.h"
|
||||
#include <string>
|
||||
|
||||
namespace ns3 {
|
||||
@@ -9,11 +29,30 @@ class AttributeDefaultIterator
|
||||
{
|
||||
public:
|
||||
virtual ~AttributeDefaultIterator () = 0;
|
||||
/**
|
||||
* \brief This function will go through all the TypeIds and get only the attributes which are
|
||||
* explicit values (not vectors or pointer or arrays) and apply StartVisitTypeId
|
||||
* and VisitAttribute on the attributes in one TypeId. At the end of each TypeId
|
||||
* EndVisitTypeId is called.
|
||||
*/
|
||||
void Iterate (void);
|
||||
private:
|
||||
/**
|
||||
* \brief Just an interface that needs to be implemented
|
||||
*/
|
||||
virtual void StartVisitTypeId (std::string name);
|
||||
/**
|
||||
* \brief Just an interface that needs to be implemented
|
||||
*/
|
||||
virtual void EndVisitTypeId (void);
|
||||
virtual void VisitAttribute (std::string name, std::string defaultValue);
|
||||
/**
|
||||
* \brief This method can be implemented, otherwise, it will call DoVisitAttribute
|
||||
*/
|
||||
virtual void VisitAttribute (TypeId tid, std::string name, std::string defaultValue, uint32_t index);
|
||||
/**
|
||||
* \brief This method is just an interface and needs to be implemented
|
||||
*/
|
||||
virtual void DoVisitAttribute (std::string name, std::string defaultValue);
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
#include "attribute-iterator.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/log.h"
|
||||
@@ -13,10 +31,12 @@ namespace ns3 {
|
||||
|
||||
|
||||
AttributeIterator::AttributeIterator ()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
AttributeIterator::~AttributeIterator ()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AttributeIterator::Iterate (void)
|
||||
@@ -38,9 +58,9 @@ AttributeIterator::IsExamined (Ptr<const Object> object)
|
||||
for (uint32_t i = 0; i < m_examined.size (); ++i)
|
||||
{
|
||||
if (object == m_examined[i])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -74,28 +94,36 @@ AttributeIterator::GetCurrentPath (void) const
|
||||
|
||||
void
|
||||
AttributeIterator::DoStartVisitObject (Ptr<Object> object)
|
||||
{}
|
||||
{
|
||||
}
|
||||
void
|
||||
AttributeIterator::DoEndVisitObject (void)
|
||||
{}
|
||||
{
|
||||
}
|
||||
void
|
||||
AttributeIterator::DoStartVisitPointerAttribute (Ptr<Object> object, std::string name, Ptr<Object> item)
|
||||
{}
|
||||
{
|
||||
}
|
||||
void
|
||||
AttributeIterator::DoEndVisitPointerAttribute (void)
|
||||
{}
|
||||
{
|
||||
}
|
||||
void
|
||||
AttributeIterator::DoStartVisitArrayAttribute (Ptr<Object> object, std::string name, const ObjectVectorValue &vector)
|
||||
{}
|
||||
{
|
||||
}
|
||||
void
|
||||
AttributeIterator::DoEndVisitArrayAttribute (void)
|
||||
{}
|
||||
{
|
||||
}
|
||||
void
|
||||
AttributeIterator::DoStartVisitArrayItem (const ObjectVectorValue &vector, uint32_t index, Ptr<Object> item)
|
||||
{}
|
||||
{
|
||||
}
|
||||
void
|
||||
AttributeIterator::DoEndVisitArrayItem (void)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
AttributeIterator::VisitAttribute (Ptr<Object> object, std::string name)
|
||||
@@ -174,58 +202,59 @@ AttributeIterator::DoIterate (Ptr<Object> object)
|
||||
{
|
||||
NS_LOG_DEBUG ("store " << tid.GetName ());
|
||||
for (uint32_t i = 0; i < tid.GetAttributeN (); ++i)
|
||||
{
|
||||
Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (i);
|
||||
const PointerChecker *ptrChecker = dynamic_cast<const PointerChecker *> (PeekPointer (checker));
|
||||
if (ptrChecker != 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("pointer attribute " << tid.GetAttributeName (i));
|
||||
PointerValue ptr;
|
||||
object->GetAttribute (tid.GetAttributeName (i), ptr);
|
||||
Ptr<Object> tmp = ptr.Get<Object> ();
|
||||
if (tmp != 0)
|
||||
{
|
||||
StartVisitPointerAttribute (object, tid.GetAttributeName (i), tmp);
|
||||
m_examined.push_back (object);
|
||||
DoIterate (tmp);
|
||||
m_examined.pop_back ();
|
||||
EndVisitPointerAttribute ();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// attempt to cast to an object vector.
|
||||
const ObjectVectorChecker *vectorChecker = dynamic_cast<const ObjectVectorChecker *> (PeekPointer (checker));
|
||||
if (vectorChecker != 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("vector attribute " << tid.GetAttributeName (i));
|
||||
ObjectVectorValue vector;
|
||||
object->GetAttribute (tid.GetAttributeName (i), vector);
|
||||
StartVisitArrayAttribute (object, tid.GetAttributeName (i), vector);
|
||||
for (uint32_t j = 0; j < vector.GetN (); ++j)
|
||||
{
|
||||
NS_LOG_DEBUG ("vector attribute item " << j);
|
||||
Ptr<Object> tmp = vector.Get (j);
|
||||
StartVisitArrayItem (vector, j, tmp);
|
||||
m_examined.push_back (object);
|
||||
DoIterate (tmp);
|
||||
m_examined.pop_back ();
|
||||
EndVisitArrayItem ();
|
||||
}
|
||||
EndVisitArrayAttribute ();
|
||||
continue;
|
||||
}
|
||||
uint32_t flags = tid.GetAttributeFlags (i);
|
||||
Ptr<const AttributeAccessor> accessor = tid.GetAttributeAccessor (i);
|
||||
if ((flags & TypeId::ATTR_GET) && accessor->HasGetter () &&
|
||||
(flags & TypeId::ATTR_SET) && accessor->HasSetter ())
|
||||
{
|
||||
VisitAttribute (object, tid.GetAttributeName (i));
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("could not store " << tid.GetAttributeName (i));
|
||||
}
|
||||
}
|
||||
{
|
||||
Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (i);
|
||||
const PointerChecker *ptrChecker = dynamic_cast<const PointerChecker *> (PeekPointer (checker));
|
||||
if (ptrChecker != 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("pointer attribute " << tid.GetAttributeName (i));
|
||||
PointerValue ptr;
|
||||
object->GetAttribute (tid.GetAttributeName (i), ptr);
|
||||
Ptr<Object> tmp = ptr.Get<Object> ();
|
||||
if (tmp != 0)
|
||||
{
|
||||
StartVisitPointerAttribute (object, tid.GetAttributeName (i),
|
||||
tmp);
|
||||
m_examined.push_back (object);
|
||||
DoIterate (tmp);
|
||||
m_examined.pop_back ();
|
||||
EndVisitPointerAttribute ();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// attempt to cast to an object vector.
|
||||
const ObjectVectorChecker *vectorChecker = dynamic_cast<const ObjectVectorChecker *> (PeekPointer (checker));
|
||||
if (vectorChecker != 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("vector attribute " << tid.GetAttributeName (i));
|
||||
ObjectVectorValue vector;
|
||||
object->GetAttribute (tid.GetAttributeName (i), vector);
|
||||
StartVisitArrayAttribute (object, tid.GetAttributeName (i), vector);
|
||||
for (uint32_t j = 0; j < vector.GetN (); ++j)
|
||||
{
|
||||
NS_LOG_DEBUG ("vector attribute item " << j);
|
||||
Ptr<Object> tmp = vector.Get (j);
|
||||
StartVisitArrayItem (vector, j, tmp);
|
||||
m_examined.push_back (object);
|
||||
DoIterate (tmp);
|
||||
m_examined.pop_back ();
|
||||
EndVisitArrayItem ();
|
||||
}
|
||||
EndVisitArrayAttribute ();
|
||||
continue;
|
||||
}
|
||||
uint32_t flags = tid.GetAttributeFlags (i);
|
||||
Ptr<const AttributeAccessor> accessor = tid.GetAttributeAccessor (i);
|
||||
if ((flags & TypeId::ATTR_GET) && accessor->HasGetter () &&
|
||||
(flags & TypeId::ATTR_SET) && accessor->HasSetter ())
|
||||
{
|
||||
VisitAttribute (object, tid.GetAttributeName (i));
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("could not store " << tid.GetAttributeName (i));
|
||||
}
|
||||
}
|
||||
}
|
||||
Object::AggregateIterator iter = object->GetAggregateIterator ();
|
||||
bool recursiveAggregate = false;
|
||||
@@ -233,22 +262,22 @@ AttributeIterator::DoIterate (Ptr<Object> object)
|
||||
{
|
||||
Ptr<const Object> tmp = iter.Next ();
|
||||
if (IsExamined (tmp))
|
||||
{
|
||||
recursiveAggregate = true;
|
||||
}
|
||||
{
|
||||
recursiveAggregate = true;
|
||||
}
|
||||
}
|
||||
if (!recursiveAggregate)
|
||||
{
|
||||
iter = object->GetAggregateIterator ();
|
||||
while (iter.HasNext ())
|
||||
{
|
||||
Ptr<Object> tmp = const_cast<Object *> (PeekPointer (iter.Next ()));
|
||||
StartVisitObject (tmp);
|
||||
m_examined.push_back (object);
|
||||
DoIterate (tmp);
|
||||
m_examined.pop_back ();
|
||||
EndVisitObject ();
|
||||
}
|
||||
{
|
||||
Ptr<Object> tmp = const_cast<Object *> (PeekPointer (iter.Next ()));
|
||||
StartVisitObject (tmp);
|
||||
m_examined.push_back (object);
|
||||
DoIterate (tmp);
|
||||
m_examined.pop_back ();
|
||||
EndVisitObject ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
#ifndef ATTRIBUTE_ITERATOR_H
|
||||
#define ATTRIBUTE_ITERATOR_H
|
||||
|
||||
|
||||
594
src/contrib/display-functions.cc
Normal file
594
src/contrib/display-functions.cc
Normal file
@@ -0,0 +1,594 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Faker Moatamri <faker.moatamri@sophia.inria.fr>
|
||||
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "display-functions.h"
|
||||
#include "raw-text-config.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/pointer.h"
|
||||
|
||||
namespace ns3 {
|
||||
/**
|
||||
* This function includes the name of the attribute or the editable value
|
||||
* in the second column
|
||||
*/
|
||||
void
|
||||
cell_data_function_col_1 (GtkTreeViewColumn *col, GtkCellRenderer *renderer,
|
||||
GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
|
||||
{
|
||||
ModelNode *node;
|
||||
gtk_tree_model_get (model, iter, COL_NODE, &node, -1);
|
||||
if (node->type == ModelNode::NODE_ATTRIBUTE)
|
||||
{
|
||||
StringValue str;
|
||||
node->object->GetAttribute (node->name, str);
|
||||
g_object_set (renderer, "text", str.Get ().c_str (), (char*) 0);
|
||||
g_object_set (renderer, "editable", TRUE, (char*) 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_set (renderer, "text", "", (char*) 0);
|
||||
g_object_set (renderer, "editable", FALSE, (char*) 0);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This function includes the name of the object, pointer, vector or vector item
|
||||
* in the first column
|
||||
*/
|
||||
void
|
||||
cell_data_function_col_0 (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model,
|
||||
GtkTreeIter *iter, gpointer user_data)
|
||||
{
|
||||
ModelNode *node;
|
||||
gtk_tree_model_get (model, iter, COL_NODE, &node, -1);
|
||||
g_object_set (renderer, "editable", FALSE, (char*) 0);
|
||||
switch (node->type)
|
||||
{
|
||||
case ModelNode::NODE_OBJECT:
|
||||
g_object_set (renderer, "text", node->object->GetInstanceTypeId ().GetName ().c_str (), (char*) 0);
|
||||
break;
|
||||
case ModelNode::NODE_POINTER:
|
||||
g_object_set (renderer, "text", node->name.c_str (), (char*) 0);
|
||||
break;
|
||||
case ModelNode::NODE_VECTOR:
|
||||
g_object_set (renderer, "text", node->name.c_str (), (char*) 0);
|
||||
break;
|
||||
case ModelNode::NODE_VECTOR_ITEM:
|
||||
{
|
||||
std::stringstream oss;
|
||||
oss << node->index;
|
||||
g_object_set (renderer, "text", oss.str ().c_str (), (char*) 0);
|
||||
}
|
||||
break;
|
||||
case ModelNode::NODE_ATTRIBUTE:
|
||||
g_object_set (renderer, "text", node->name.c_str (), (char*) 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the callback called when the value of an attribute is changed
|
||||
*/
|
||||
void
|
||||
cell_edited_callback (GtkCellRendererText *cell, gchar *path_string,
|
||||
gchar *new_text, gpointer user_data)
|
||||
{
|
||||
GtkTreeModel *model = GTK_TREE_MODEL (user_data);
|
||||
GtkTreeIter iter;
|
||||
gtk_tree_model_get_iter_from_string (model, &iter, path_string);
|
||||
ModelNode *node;
|
||||
gtk_tree_model_get (model, &iter, COL_NODE, &node, -1);
|
||||
NS_ASSERT (node->type == ModelNode::NODE_ATTRIBUTE);
|
||||
node->object->SetAttribute (node->name, StringValue (new_text));
|
||||
}
|
||||
|
||||
/**
|
||||
* This function gets the column number 0 or 1 from the mouse
|
||||
* click
|
||||
*/
|
||||
int
|
||||
get_col_number_from_tree_view_column (GtkTreeViewColumn *col)
|
||||
{
|
||||
GList *cols;
|
||||
int num;
|
||||
g_return_val_if_fail (col != 0, -1);
|
||||
g_return_val_if_fail (col->tree_view != 0, -1);
|
||||
cols = gtk_tree_view_get_columns (GTK_TREE_VIEW (col->tree_view));
|
||||
num = g_list_index (cols, (gpointer) col);
|
||||
g_list_free (cols);
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function displays the tooltip for an object, pointer, vector
|
||||
* item or an attribute
|
||||
*/
|
||||
gboolean
|
||||
cell_tooltip_callback (GtkWidget *widget, gint x, gint y, gboolean keyboard_tip,
|
||||
GtkTooltip *tooltip, gpointer user_data)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeViewColumn * column;
|
||||
if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (widget), &x, &y,
|
||||
keyboard_tip, &model, 0, &iter))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget), x, y, 0, &column, 0, 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
int col = get_col_number_from_tree_view_column (column);
|
||||
|
||||
ModelNode *node;
|
||||
gtk_tree_model_get (model, &iter, COL_NODE, &node, -1);
|
||||
|
||||
switch (node->type)
|
||||
{
|
||||
case ModelNode::NODE_OBJECT:
|
||||
if (col == 0)
|
||||
{
|
||||
std::string tip = "This object is of type "
|
||||
+ node->object->GetInstanceTypeId ().GetName ();
|
||||
gtk_tooltip_set_text (tooltip, tip.c_str ());
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case ModelNode::NODE_POINTER:
|
||||
if (col == 0)
|
||||
{
|
||||
PointerValue ptr;
|
||||
node->object->GetAttribute (node->name, ptr);
|
||||
std::string tip = "This object is of type "
|
||||
+ ptr.GetObject ()->GetInstanceTypeId ().GetName ();
|
||||
gtk_tooltip_set_text (tooltip, tip.c_str ());
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case ModelNode::NODE_VECTOR:
|
||||
break;
|
||||
case ModelNode::NODE_VECTOR_ITEM:
|
||||
if (col == 0)
|
||||
{
|
||||
std::string tip = "This object is of type "
|
||||
+ node->object->GetInstanceTypeId ().GetName ();
|
||||
gtk_tooltip_set_text (tooltip, tip.c_str ());
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case ModelNode::NODE_ATTRIBUTE:
|
||||
{
|
||||
uint32_t attrIndex = 0;
|
||||
TypeId tid;
|
||||
for (tid = node->object->GetInstanceTypeId (); tid.HasParent (); tid
|
||||
= tid.GetParent ())
|
||||
{
|
||||
for (uint32_t i = 0; i < tid.GetAttributeN (); ++i)
|
||||
{
|
||||
if (tid.GetAttributeName (i) == node->name)
|
||||
{
|
||||
attrIndex = i;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
out: if (col == 0)
|
||||
{
|
||||
std::string tip = tid.GetAttributeHelp (attrIndex);
|
||||
gtk_tooltip_set_text (tooltip, tip.c_str ());
|
||||
}
|
||||
else
|
||||
{
|
||||
Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (
|
||||
attrIndex);
|
||||
std::string tip;
|
||||
tip = "This attribute is of type " + checker->GetValueTypeName ();
|
||||
if (checker->HasUnderlyingTypeInformation ())
|
||||
{
|
||||
tip += " " + checker->GetUnderlyingTypeInformation ();
|
||||
}
|
||||
gtk_tooltip_set_text (tooltip, tip.c_str ());
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the main view opening the widget, getting tooltips and drawing the
|
||||
* tree of attributes...
|
||||
*/
|
||||
GtkWidget *
|
||||
create_view (GtkTreeStore *model)
|
||||
{
|
||||
GtkTreeViewColumn *col;
|
||||
GtkCellRenderer *renderer;
|
||||
GtkWidget *view;
|
||||
|
||||
view = gtk_tree_view_new ();
|
||||
g_object_set (view, "has-tooltip", TRUE, (char*) 0);
|
||||
g_signal_connect (view, "query-tooltip", (GCallback) cell_tooltip_callback, 0);
|
||||
|
||||
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), GTK_TREE_VIEW_GRID_LINES_BOTH);
|
||||
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view), TRUE);
|
||||
|
||||
col = gtk_tree_view_column_new ();
|
||||
gtk_tree_view_column_set_title (col, "Object Attributes");
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (view), col);
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_column_pack_start (col, renderer, TRUE);
|
||||
gtk_tree_view_column_set_cell_data_func (col, renderer, cell_data_function_col_0, 0, 0);
|
||||
g_object_set (renderer, "editable", FALSE, (char*) 0);
|
||||
|
||||
col = gtk_tree_view_column_new ();
|
||||
gtk_tree_view_column_set_title (col, "Attribute Value");
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (view), col);
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
g_signal_connect (renderer, "edited", (GCallback) cell_edited_callback, model);
|
||||
gtk_tree_view_column_pack_start (col, renderer, TRUE);
|
||||
gtk_tree_view_column_set_cell_data_func (col, renderer, cell_data_function_col_1, 0, 0);
|
||||
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (view), GTK_TREE_MODEL (model));
|
||||
|
||||
g_object_unref (model); /* destroy model automatically with view */
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the action done when the user presses on the save button.
|
||||
* It will save the config to a file.
|
||||
*/
|
||||
void
|
||||
save_clicked (GtkButton *button, gpointer user_data)
|
||||
{
|
||||
GtkWidget *parent_window = GTK_WIDGET (user_data);
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new ("Save File", GTK_WINDOW (parent_window), GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE,
|
||||
GTK_RESPONSE_ACCEPT, (char *) 0);
|
||||
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
|
||||
TRUE);
|
||||
|
||||
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "config.txt");
|
||||
|
||||
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
||||
RawTextConfigSave config;
|
||||
config.SetFilename (filename);
|
||||
config.Attributes ();
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user presses the button load, it will load the config file into memory.
|
||||
*/
|
||||
void
|
||||
load_clicked (GtkButton *button, gpointer user_data)
|
||||
{
|
||||
GtkWidget *parent_window = GTK_WIDGET (user_data);
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new ("Open File", GTK_WINDOW (parent_window), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN,
|
||||
GTK_RESPONSE_ACCEPT, (char *) 0);
|
||||
|
||||
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
||||
RawTextConfigLoad config;
|
||||
config.SetFilename (filename);
|
||||
config.Attributes ();
|
||||
}
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit the window when exit button is pressed
|
||||
*/
|
||||
void
|
||||
exit_clicked_callback (GtkButton *button, gpointer user_data)
|
||||
{
|
||||
gtk_main_quit ();
|
||||
gtk_widget_hide (GTK_WIDGET (user_data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit the application
|
||||
*/
|
||||
gboolean
|
||||
delete_event_callback (GtkWidget *widget, GdkEvent *event, gpointer user_data)
|
||||
{
|
||||
gtk_main_quit ();
|
||||
gtk_widget_hide (GTK_WIDGET (user_data));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the tree model contents
|
||||
*/
|
||||
gboolean
|
||||
clean_model_callback (GtkTreeModel *model, GtkTreePath *path,
|
||||
GtkTreeIter *iter, gpointer data)
|
||||
{
|
||||
ModelNode *node;
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (model), iter, COL_NODE, &node, -1);
|
||||
delete node;
|
||||
gtk_tree_store_set (GTK_TREE_STORE (model), iter, COL_NODE, (ModelNode*) 0,
|
||||
-1);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/************************** display functions used by default configurator **********************/
|
||||
/**
|
||||
* This function writes data in the second column, this data is going to be editable
|
||||
* if it is a NODE_ATTRIBUTE
|
||||
*/
|
||||
void
|
||||
cell_data_function_col_1_config_default (GtkTreeViewColumn *col, GtkCellRenderer *renderer,
|
||||
GtkTreeModel *model, GtkTreeIter *iter,
|
||||
gpointer user_data)
|
||||
{
|
||||
ModelTypeid *node;
|
||||
gtk_tree_model_get (model, iter, COL_TYPEID, &node, -1);
|
||||
if (node->type == ModelTypeid::NODE_ATTRIBUTE)
|
||||
{
|
||||
g_object_set (renderer, "text", node->defaultValue.c_str (), (char*) 0);
|
||||
g_object_set (renderer, "editable", TRUE, (char*) 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_set (renderer, "text", "", (char*) 0);
|
||||
g_object_set (renderer, "editable", FALSE, (char*) 0);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This function writes the attribute or typeid name in the column 0
|
||||
*/
|
||||
void
|
||||
cell_data_function_col_0_config_default (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model,
|
||||
GtkTreeIter *iter, gpointer user_data)
|
||||
{
|
||||
ModelTypeid *node;
|
||||
gtk_tree_model_get (model, iter, COL_NODE, &node, -1);
|
||||
g_object_set (renderer, "editable", FALSE, (char*) 0);
|
||||
switch (node->type)
|
||||
{
|
||||
case ModelTypeid::NODE_TYPEID:
|
||||
g_object_set (renderer, "text", node->tid.GetName ().c_str (), (char*) 0);
|
||||
break;
|
||||
case ModelTypeid::NODE_ATTRIBUTE:
|
||||
g_object_set (renderer, "text", node->name.c_str (), (char*) 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This functions is called whenever there is a change in the value of an attribute
|
||||
* If the input value is ok, it will be updated in the default value and in the
|
||||
* gui, otherwise, it won't be updated in both.
|
||||
*/
|
||||
void
|
||||
cell_edited_callback_config_default (GtkCellRendererText *cell, gchar *path_string,
|
||||
gchar *new_text, gpointer user_data)
|
||||
{
|
||||
GtkTreeModel *model = GTK_TREE_MODEL (user_data);
|
||||
GtkTreeIter iter;
|
||||
gtk_tree_model_get_iter_from_string (model, &iter, path_string);
|
||||
ModelTypeid *node;
|
||||
gtk_tree_model_get (model, &iter, COL_NODE, &node, -1);
|
||||
NS_ASSERT (node->type == ModelTypeid::NODE_ATTRIBUTE);
|
||||
if (Config::SetDefaultFailSafe (node->tid.GetAttributeFullName (node->index),StringValue (new_text)))
|
||||
{
|
||||
node->defaultValue = new_text;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to display a tooltip whenever the user puts the mouse
|
||||
* over a type ID or an attribute. It will give the type and the possible values of
|
||||
* an attribute value and the type of the object for an attribute object or a
|
||||
* typeID object
|
||||
*/
|
||||
gboolean
|
||||
cell_tooltip_callback_config_default (GtkWidget *widget, gint x, gint y,
|
||||
gboolean keyboard_tip, GtkTooltip *tooltip, gpointer user_data)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeViewColumn * column;
|
||||
if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (widget), &x, &y,
|
||||
keyboard_tip, &model, 0, &iter))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget), x, y, 0, &column, 0, 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
int col = get_col_number_from_tree_view_column (column);
|
||||
|
||||
ModelTypeid *node;
|
||||
gtk_tree_model_get (model, &iter, COL_NODE, &node, -1);
|
||||
|
||||
switch (node->type)
|
||||
{
|
||||
case ModelTypeid::NODE_TYPEID:
|
||||
if (col == 0)
|
||||
{
|
||||
std::string tip = "This object is of type " + node->tid.GetName ();
|
||||
gtk_tooltip_set_text (tooltip, tip.c_str ());
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case ModelTypeid::NODE_ATTRIBUTE:
|
||||
{
|
||||
uint32_t attrIndex = node->index;
|
||||
if (col == 0)
|
||||
{
|
||||
std::string tip = node->tid.GetAttributeHelp (attrIndex);
|
||||
gtk_tooltip_set_text (tooltip, tip.c_str ());
|
||||
}
|
||||
else
|
||||
{
|
||||
Ptr<const AttributeChecker> checker = node->tid.GetAttributeChecker (attrIndex);
|
||||
std::string tip;
|
||||
tip = "This attribute is of type " + checker->GetValueTypeName ();
|
||||
if (checker->HasUnderlyingTypeInformation ())
|
||||
{
|
||||
tip += " " + checker->GetUnderlyingTypeInformation ();
|
||||
}
|
||||
gtk_tooltip_set_text (tooltip, tip.c_str ());
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the action done when the user presses on the save button.
|
||||
* It will save the config to a file.
|
||||
*/
|
||||
void
|
||||
save_clicked_default (GtkButton *button, gpointer user_data)
|
||||
{
|
||||
GtkWidget *parent_window = GTK_WIDGET (user_data);
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new ("Save File", GTK_WINDOW (parent_window), GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE,
|
||||
GTK_RESPONSE_ACCEPT, (char *) 0);
|
||||
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
|
||||
TRUE);
|
||||
|
||||
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "config.txt");
|
||||
|
||||
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
||||
RawTextConfigSave config;
|
||||
config.SetFilename (filename);
|
||||
config.Default ();
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user presses the button load, it will load the config file into memory.
|
||||
*/
|
||||
void
|
||||
load_clicked_default (GtkButton *button, gpointer user_data)
|
||||
{
|
||||
GtkWidget *parent_window = GTK_WIDGET (user_data);
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new ("Open File", GTK_WINDOW (parent_window), GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN,
|
||||
GTK_RESPONSE_ACCEPT, (char *) 0);
|
||||
|
||||
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
||||
RawTextConfigLoad config;
|
||||
config.SetFilename (filename);
|
||||
config.Default ();
|
||||
}
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the main view opening the widget, getting tooltips and drawing the
|
||||
* tree of attributes
|
||||
*/
|
||||
GtkWidget *
|
||||
create_view_config_default (GtkTreeStore *model)
|
||||
{
|
||||
GtkTreeViewColumn *col;
|
||||
GtkCellRenderer *renderer;
|
||||
GtkWidget *view;
|
||||
|
||||
view = gtk_tree_view_new ();
|
||||
g_object_set (view, "has-tooltip", TRUE, (char*) 0);
|
||||
g_signal_connect (view, "query-tooltip", (GCallback) cell_tooltip_callback_config_default, 0);
|
||||
|
||||
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), GTK_TREE_VIEW_GRID_LINES_BOTH);
|
||||
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view), TRUE);
|
||||
|
||||
col = gtk_tree_view_column_new ();
|
||||
gtk_tree_view_column_set_title (col, "Object Attributes");
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (view), col);
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_column_pack_start (col, renderer, TRUE);
|
||||
gtk_tree_view_column_set_cell_data_func (col, renderer, cell_data_function_col_0_config_default, 0, 0);
|
||||
g_object_set (renderer, "editable", FALSE, (char*) 0);
|
||||
|
||||
col = gtk_tree_view_column_new ();
|
||||
gtk_tree_view_column_set_title (col, "Attribute Value");
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (view), col);
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
g_signal_connect (renderer, "edited", (GCallback) cell_edited_callback_config_default, model);
|
||||
gtk_tree_view_column_pack_start (col, renderer, TRUE);
|
||||
gtk_tree_view_column_set_cell_data_func (col, renderer, cell_data_function_col_1_config_default, 0, 0);
|
||||
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (view), GTK_TREE_MODEL (model));
|
||||
|
||||
g_object_unref (model); /* destroy model automatically with view */
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the tree model contents
|
||||
*/
|
||||
gboolean
|
||||
clean_model_callback_config_default (GtkTreeModel *model, GtkTreePath *path,
|
||||
GtkTreeIter *iter, gpointer data)
|
||||
{
|
||||
ModelTypeid *node;
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (model), iter, COL_TYPEID, &node, -1);
|
||||
delete node;
|
||||
gtk_tree_store_set (GTK_TREE_STORE (model), iter, COL_TYPEID, (ModelTypeid*) 0, -1);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
}//end ns3 namespace
|
||||
|
||||
150
src/contrib/display-functions.h
Normal file
150
src/contrib/display-functions.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Faker Moatamri <faker.moatamri@sophia.inria.fr>
|
||||
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#ifndef DISPLAY_FUNCTIONS_H
|
||||
#define DISPLAY_FUNCTIONS_H
|
||||
|
||||
#include "model-node-creator.h"
|
||||
#include "model-typeid-creator.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
namespace ns3 {
|
||||
/**
|
||||
* This function includes the name of the attribute or the editable value
|
||||
* in the second column
|
||||
*/
|
||||
void
|
||||
cell_data_function_col_1 (GtkTreeViewColumn *col, GtkCellRenderer *renderer,
|
||||
GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data);
|
||||
/**
|
||||
* This function includes the name of the object, pointer, vector or vector item
|
||||
* in the first column
|
||||
*/
|
||||
void
|
||||
cell_data_function_col_0 (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model,
|
||||
GtkTreeIter *iter, gpointer user_data);
|
||||
/**
|
||||
* This is the callback called when the value of an attribute is changed
|
||||
*/
|
||||
void
|
||||
cell_edited_callback (GtkCellRendererText *cell, gchar *path_string,
|
||||
gchar *new_text, gpointer user_data);
|
||||
/**
|
||||
* This function gets the column number 0 or 1 from the mouse
|
||||
* click
|
||||
*/
|
||||
int
|
||||
get_col_number_from_tree_view_column (GtkTreeViewColumn *col);
|
||||
/**
|
||||
* This function displays the tooltip for an object, pointer, vector
|
||||
* item or an attribute
|
||||
*/
|
||||
gboolean
|
||||
cell_tooltip_callback (GtkWidget *widget, gint x, gint y, gboolean keyboard_tip,
|
||||
GtkTooltip *tooltip, gpointer user_data);
|
||||
/**
|
||||
* This is the main view opening the widget, getting tooltips and drawing the
|
||||
* tree of attributes...
|
||||
*/
|
||||
GtkWidget *
|
||||
create_view (GtkTreeStore *model);
|
||||
/**
|
||||
* This is the action done when the user presses on the save button.
|
||||
* It will save the config to a file.
|
||||
*/
|
||||
void
|
||||
save_clicked (GtkButton *button, gpointer user_data);
|
||||
/**
|
||||
* If the user presses the button load, it will load the config file into memory.
|
||||
*/
|
||||
void
|
||||
load_clicked (GtkButton *button, gpointer user_data);
|
||||
/**
|
||||
* Exit the window when exit button is pressed
|
||||
*/
|
||||
void
|
||||
exit_clicked_callback (GtkButton *button, gpointer user_data);
|
||||
/**
|
||||
* Exit the application
|
||||
*/
|
||||
gboolean
|
||||
delete_event_callback (GtkWidget *widget, GdkEvent *event, gpointer user_data);
|
||||
/**
|
||||
* Delete the tree model contents
|
||||
*/
|
||||
gboolean
|
||||
clean_model_callback (GtkTreeModel *model, GtkTreePath *path,
|
||||
GtkTreeIter *iter, gpointer data);
|
||||
/************************** display functions used by default configurator **********************/
|
||||
/**
|
||||
* This function writes data in the second column, this data is going to be editable
|
||||
* if it is a NODE_ATTRIBUTE
|
||||
*/
|
||||
void
|
||||
cell_data_function_col_1_config_default (GtkTreeViewColumn *col, GtkCellRenderer *renderer,
|
||||
GtkTreeModel *model, GtkTreeIter *iter,
|
||||
gpointer user_data);
|
||||
/**
|
||||
* This function writes the attribute or typeid name in the column 0
|
||||
*/
|
||||
void
|
||||
cell_data_function_col_0_config_default (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model,
|
||||
GtkTreeIter *iter, gpointer user_data);
|
||||
/**
|
||||
* This is the action done when the user presses on the save button.
|
||||
* It will save the config to a file.
|
||||
*/
|
||||
void
|
||||
save_clicked_default (GtkButton *button, gpointer user_data);
|
||||
/**
|
||||
* If the user presses the button load, it will load the config file into memory.
|
||||
*/
|
||||
void
|
||||
load_clicked_default (GtkButton *button, gpointer user_data);
|
||||
/**
|
||||
* This functions is called whenever there is a change in the value of an attribute
|
||||
* If the input value is ok, it will be updated in the default value and in the
|
||||
* gui, otherwise, it won't be updated in both.
|
||||
*/
|
||||
void
|
||||
cell_edited_callback_config_default (GtkCellRendererText *cell, gchar *path_string,
|
||||
gchar *new_text, gpointer user_data);
|
||||
/**
|
||||
* This function is used to display a tooltip whenever the user puts the mouse
|
||||
* over a type ID or an attribute. It will give the type and the possible values of
|
||||
* an attribute value and the type of the object for an attribute object or a
|
||||
* typeID object
|
||||
*/
|
||||
gboolean
|
||||
cell_tooltip_callback_config_default (GtkWidget *widget, gint x, gint y,
|
||||
gboolean keyboard_tip, GtkTooltip *tooltip, gpointer user_data);
|
||||
/**
|
||||
* This is the main view opening the widget, getting tooltips and drawing the
|
||||
* tree of attributes
|
||||
*/
|
||||
GtkWidget *
|
||||
create_view_config_default (GtkTreeStore *model);
|
||||
/**
|
||||
* Delete the tree model contents
|
||||
*/
|
||||
gboolean
|
||||
clean_model_callback_config_default (GtkTreeModel *model, GtkTreePath *path,
|
||||
GtkTreeIter *iter, gpointer data);
|
||||
}//end namespace ns3
|
||||
|
||||
#endif
|
||||
@@ -1,11 +1,26 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Faker Moatamri <faker.moatamri@sophia.inria.fr>
|
||||
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
#include "gtk-config-store.h"
|
||||
#include "attribute-iterator.h"
|
||||
#include "raw-text-config.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/pointer.h"
|
||||
#include "display-functions.h"
|
||||
#include "ns3/log.h"
|
||||
#include <gtk/gtk.h>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
@@ -13,474 +28,61 @@ namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("GtkconfigStore");
|
||||
|
||||
enum {
|
||||
COL_NODE = 0,
|
||||
COL_LAST
|
||||
};
|
||||
|
||||
struct ModelNode
|
||||
{
|
||||
enum {
|
||||
// store object + attribute name
|
||||
NODE_ATTRIBUTE,
|
||||
// store object + attribute name
|
||||
NODE_POINTER,
|
||||
// store object + attribute name
|
||||
NODE_VECTOR,
|
||||
// store index + value (object)
|
||||
NODE_VECTOR_ITEM,
|
||||
// store object
|
||||
NODE_OBJECT
|
||||
} type;
|
||||
std::string name;
|
||||
Ptr<Object> object;
|
||||
uint32_t index;
|
||||
};
|
||||
|
||||
class ModelCreator : public AttributeIterator
|
||||
{
|
||||
public:
|
||||
ModelCreator ();
|
||||
|
||||
void Build (GtkTreeStore *treestore);
|
||||
private:
|
||||
virtual void DoVisitAttribute (Ptr<Object> object, std::string name);
|
||||
virtual void DoStartVisitObject (Ptr<Object> object);
|
||||
virtual void DoEndVisitObject (void);
|
||||
virtual void DoStartVisitPointerAttribute (Ptr<Object> object, std::string name, Ptr<Object> value);
|
||||
virtual void DoEndVisitPointerAttribute (void);
|
||||
virtual void DoStartVisitArrayAttribute (Ptr<Object> object, std::string name, const ObjectVectorValue &vector);
|
||||
virtual void DoEndVisitArrayAttribute (void);
|
||||
virtual void DoStartVisitArrayItem (const ObjectVectorValue &vector, uint32_t index, Ptr<Object> item);
|
||||
virtual void DoEndVisitArrayItem (void);
|
||||
void Add (ModelNode *node);
|
||||
void Remove (void);
|
||||
|
||||
GtkTreeStore *m_treestore;
|
||||
std::vector<GtkTreeIter *> m_iters;
|
||||
};
|
||||
|
||||
ModelCreator::ModelCreator ()
|
||||
{}
|
||||
void
|
||||
ModelCreator::Build (GtkTreeStore *treestore)
|
||||
{
|
||||
m_treestore = treestore;
|
||||
m_iters.push_back (0);
|
||||
Iterate ();
|
||||
NS_ASSERT (m_iters.size () == 1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ModelCreator::Add (ModelNode *node)
|
||||
{
|
||||
GtkTreeIter *parent = m_iters.back ();
|
||||
GtkTreeIter *current = g_new (GtkTreeIter, 1);
|
||||
gtk_tree_store_append (m_treestore, current, parent);
|
||||
gtk_tree_store_set (m_treestore, current,
|
||||
COL_NODE, node,
|
||||
-1);
|
||||
m_iters.push_back (current);
|
||||
}
|
||||
void
|
||||
ModelCreator::Remove (void)
|
||||
{
|
||||
GtkTreeIter *iter = m_iters.back ();
|
||||
g_free (iter);
|
||||
m_iters.pop_back ();
|
||||
}
|
||||
|
||||
void
|
||||
ModelCreator::DoVisitAttribute (Ptr<Object> object, std::string name)
|
||||
{
|
||||
ModelNode *node = new ModelNode ();
|
||||
node->type = ModelNode::NODE_ATTRIBUTE;
|
||||
node->object = object;
|
||||
node->name = name;
|
||||
Add (node);
|
||||
Remove ();
|
||||
}
|
||||
void
|
||||
ModelCreator::DoStartVisitObject (Ptr<Object> object)
|
||||
{
|
||||
ModelNode *node = new ModelNode ();
|
||||
node->type = ModelNode::NODE_OBJECT;
|
||||
node->object = object;
|
||||
Add (node);
|
||||
}
|
||||
void
|
||||
ModelCreator::DoEndVisitObject (void)
|
||||
{
|
||||
Remove ();
|
||||
}
|
||||
void
|
||||
ModelCreator::DoStartVisitPointerAttribute (Ptr<Object> object, std::string name, Ptr<Object> value)
|
||||
{
|
||||
ModelNode *node = new ModelNode ();
|
||||
node->type = ModelNode::NODE_POINTER;
|
||||
node->object = object;
|
||||
node->name = name;
|
||||
Add (node);
|
||||
}
|
||||
void
|
||||
ModelCreator::DoEndVisitPointerAttribute (void)
|
||||
{
|
||||
Remove ();
|
||||
}
|
||||
void
|
||||
ModelCreator::DoStartVisitArrayAttribute (Ptr<Object> object, std::string name, const ObjectVectorValue &vector)
|
||||
{
|
||||
ModelNode *node = new ModelNode ();
|
||||
node->type = ModelNode::NODE_VECTOR;
|
||||
node->object = object;
|
||||
node->name = name;
|
||||
Add (node);
|
||||
}
|
||||
void
|
||||
ModelCreator::DoEndVisitArrayAttribute (void)
|
||||
{
|
||||
Remove ();
|
||||
}
|
||||
void
|
||||
ModelCreator::DoStartVisitArrayItem (const ObjectVectorValue &vector, uint32_t index, Ptr<Object> item)
|
||||
{
|
||||
GtkTreeIter *parent = m_iters.back ();
|
||||
GtkTreeIter *current = g_new (GtkTreeIter, 1);
|
||||
ModelNode *node = new ModelNode ();
|
||||
node->type = ModelNode::NODE_VECTOR_ITEM;
|
||||
node->object = item;
|
||||
node->index = index;
|
||||
gtk_tree_store_append (m_treestore, current, parent);
|
||||
gtk_tree_store_set (m_treestore, current,
|
||||
COL_NODE, node,
|
||||
-1);
|
||||
m_iters.push_back (current);
|
||||
}
|
||||
void
|
||||
ModelCreator::DoEndVisitArrayItem (void)
|
||||
{
|
||||
GtkTreeIter *iter = m_iters.back ();
|
||||
g_free (iter);
|
||||
m_iters.pop_back ();
|
||||
}
|
||||
|
||||
static void
|
||||
cell_data_function_col_1 (GtkTreeViewColumn *col,
|
||||
GtkCellRenderer *renderer,
|
||||
GtkTreeModel *model,
|
||||
GtkTreeIter *iter,
|
||||
gpointer user_data)
|
||||
{
|
||||
ModelNode *node;
|
||||
gtk_tree_model_get (model, iter, COL_NODE, &node, -1);
|
||||
if (node->type == ModelNode::NODE_ATTRIBUTE)
|
||||
{
|
||||
StringValue str;
|
||||
node->object->GetAttribute (node->name, str);
|
||||
g_object_set(renderer, "text", str.Get ().c_str (), (char*)0);
|
||||
g_object_set(renderer, "editable", TRUE, (char*)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_set(renderer, "text", "", (char*)0);
|
||||
g_object_set(renderer, "editable", FALSE, (char*)0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cell_data_function_col_0 (GtkTreeViewColumn *col,
|
||||
GtkCellRenderer *renderer,
|
||||
GtkTreeModel *model,
|
||||
GtkTreeIter *iter,
|
||||
gpointer user_data)
|
||||
{
|
||||
ModelNode *node;
|
||||
gtk_tree_model_get (model, iter, COL_NODE, &node, -1);
|
||||
g_object_set (renderer, "editable", FALSE, (char*)0);
|
||||
switch (node->type) {
|
||||
case ModelNode::NODE_OBJECT:
|
||||
g_object_set(renderer, "text", node->object->GetInstanceTypeId ().GetName ().c_str (), (char*)0);
|
||||
break;
|
||||
case ModelNode::NODE_POINTER:
|
||||
g_object_set(renderer, "text", node->name.c_str (), (char*)0);
|
||||
break;
|
||||
case ModelNode::NODE_VECTOR:
|
||||
g_object_set(renderer, "text", node->name.c_str (), (char*)0);
|
||||
break;
|
||||
case ModelNode::NODE_VECTOR_ITEM: {
|
||||
std::stringstream oss;
|
||||
oss << node->index;
|
||||
g_object_set(renderer, "text", oss.str ().c_str (), (char*)0);
|
||||
} break;
|
||||
case ModelNode::NODE_ATTRIBUTE:
|
||||
g_object_set(renderer, "text", node->name.c_str (), (char*)0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cell_edited_callback (GtkCellRendererText *cell,
|
||||
gchar *path_string,
|
||||
gchar *new_text,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkTreeModel *model = GTK_TREE_MODEL (user_data);
|
||||
GtkTreeIter iter;
|
||||
gtk_tree_model_get_iter_from_string (model, &iter, path_string);
|
||||
ModelNode *node;
|
||||
gtk_tree_model_get (model, &iter, COL_NODE, &node, -1);
|
||||
NS_ASSERT (node->type == ModelNode::NODE_ATTRIBUTE);
|
||||
node->object->SetAttribute (node->name, StringValue (new_text));
|
||||
}
|
||||
|
||||
static int
|
||||
get_col_number_from_tree_view_column (GtkTreeViewColumn *col)
|
||||
{
|
||||
GList *cols;
|
||||
int num;
|
||||
g_return_val_if_fail ( col != 0, -1 );
|
||||
g_return_val_if_fail ( col->tree_view != 0, -1 );
|
||||
cols = gtk_tree_view_get_columns(GTK_TREE_VIEW(col->tree_view));
|
||||
num = g_list_index(cols, (gpointer) col);
|
||||
g_list_free(cols);
|
||||
return num;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cell_tooltip_callback (GtkWidget *widget,
|
||||
gint x,
|
||||
gint y,
|
||||
gboolean keyboard_tip,
|
||||
GtkTooltip *tooltip,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeViewColumn * column;
|
||||
if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (widget),
|
||||
&x, &y, keyboard_tip,
|
||||
&model, 0, &iter))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget),
|
||||
x, y, 0, &column, 0, 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
int col = get_col_number_from_tree_view_column (column);
|
||||
|
||||
ModelNode *node;
|
||||
gtk_tree_model_get (model, &iter, COL_NODE, &node, -1);
|
||||
|
||||
switch (node->type) {
|
||||
case ModelNode::NODE_OBJECT:
|
||||
if (col == 0)
|
||||
{
|
||||
std::string tip = "This object is of type " + node->object->GetInstanceTypeId ().GetName ();
|
||||
gtk_tooltip_set_text (tooltip, tip.c_str ());
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case ModelNode::NODE_POINTER:
|
||||
if (col == 0)
|
||||
{
|
||||
PointerValue ptr;
|
||||
node->object->GetAttribute (node->name, ptr);
|
||||
std::string tip = "This object is of type " + ptr.GetObject ()->GetInstanceTypeId ().GetName ();
|
||||
gtk_tooltip_set_text (tooltip, tip.c_str ());
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case ModelNode::NODE_VECTOR:
|
||||
break;
|
||||
case ModelNode::NODE_VECTOR_ITEM:
|
||||
if (col == 0)
|
||||
{
|
||||
std::string tip = "This object is of type " + node->object->GetInstanceTypeId ().GetName ();
|
||||
gtk_tooltip_set_text (tooltip, tip.c_str ());
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case ModelNode::NODE_ATTRIBUTE: {
|
||||
uint32_t attrIndex = 0;
|
||||
TypeId tid;
|
||||
for (tid = node->object->GetInstanceTypeId (); tid.HasParent (); tid = tid.GetParent ())
|
||||
{
|
||||
for (uint32_t i = 0; i < tid.GetAttributeN (); ++i)
|
||||
{
|
||||
if (tid.GetAttributeName (i) == node->name)
|
||||
{
|
||||
attrIndex = i;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (col == 0)
|
||||
{
|
||||
std::string tip = tid.GetAttributeHelp (attrIndex);
|
||||
gtk_tooltip_set_text (tooltip, tip.c_str ());
|
||||
}
|
||||
else
|
||||
{
|
||||
Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (attrIndex);
|
||||
std::string tip;
|
||||
tip = "This attribute is of type " + checker->GetValueTypeName ();
|
||||
if (checker->HasUnderlyingTypeInformation ())
|
||||
{
|
||||
tip += " " + checker->GetUnderlyingTypeInformation ();
|
||||
}
|
||||
gtk_tooltip_set_text (tooltip, tip.c_str ());
|
||||
}
|
||||
return TRUE;
|
||||
} break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static GtkWidget *
|
||||
create_view (GtkTreeStore *model)
|
||||
{
|
||||
GtkTreeViewColumn *col;
|
||||
GtkCellRenderer *renderer;
|
||||
GtkWidget *view;
|
||||
|
||||
view = gtk_tree_view_new();
|
||||
g_object_set (view, "has-tooltip", TRUE, (char*)0);
|
||||
g_signal_connect (view, "query-tooltip", (GCallback) cell_tooltip_callback, 0);
|
||||
|
||||
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), GTK_TREE_VIEW_GRID_LINES_BOTH);
|
||||
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view), TRUE);
|
||||
|
||||
col = gtk_tree_view_column_new();
|
||||
gtk_tree_view_column_set_title(col, "Object Attributes");
|
||||
gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_column_pack_start(col, renderer, TRUE);
|
||||
gtk_tree_view_column_set_cell_data_func(col, renderer, cell_data_function_col_0, 0, 0);
|
||||
g_object_set(renderer, "editable", FALSE, (char*)0);
|
||||
|
||||
col = gtk_tree_view_column_new();
|
||||
gtk_tree_view_column_set_title(col, "Attribute Value");
|
||||
gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
|
||||
renderer = gtk_cell_renderer_text_new();
|
||||
g_signal_connect(renderer, "edited", (GCallback) cell_edited_callback, model);
|
||||
gtk_tree_view_column_pack_start(col, renderer, TRUE);
|
||||
gtk_tree_view_column_set_cell_data_func(col, renderer, cell_data_function_col_1, 0, 0);
|
||||
|
||||
|
||||
gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL (model));
|
||||
|
||||
g_object_unref(model); /* destroy model automatically with view */
|
||||
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
static void
|
||||
save_clicked (GtkButton *button,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkWidget *parent_window = GTK_WIDGET (user_data);
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new ("Save File",
|
||||
GTK_WINDOW (parent_window),
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
|
||||
(char *)0);
|
||||
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
|
||||
|
||||
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "config.txt");
|
||||
|
||||
|
||||
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
||||
RawTextConfigSave config;
|
||||
config.SetFilename (filename);
|
||||
config.Attributes ();
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
load_clicked (GtkButton *button,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkWidget *parent_window = GTK_WIDGET (user_data);
|
||||
GtkWidget *dialog;
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new ("Open File",
|
||||
GTK_WINDOW (parent_window),
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
(char *)0);
|
||||
|
||||
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
|
||||
RawTextConfigLoad config;
|
||||
config.SetFilename (filename);
|
||||
config.Attributes ();
|
||||
}
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
exit_clicked_callback (GtkButton *button,
|
||||
gpointer user_data)
|
||||
{
|
||||
gtk_main_quit ();
|
||||
gtk_widget_hide (GTK_WIDGET (user_data));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
delete_event_callback (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
gtk_main_quit ();
|
||||
gtk_widget_hide (GTK_WIDGET (user_data));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clean_model_callback (GtkTreeModel *model,
|
||||
GtkTreePath *path,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
ModelNode *node;
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
|
||||
COL_NODE, &node,
|
||||
-1);
|
||||
delete node;
|
||||
gtk_tree_store_set (GTK_TREE_STORE (model), iter,
|
||||
COL_NODE, (ModelNode*)0,
|
||||
-1);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GtkConfigStore::GtkConfigStore ()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
GtkConfigStore::ConfigureDefaults (void)
|
||||
{}
|
||||
{
|
||||
//this function should be called before running the script to enable the user
|
||||
//to configure the default values for the objects he wants to use
|
||||
GtkWidget *window;
|
||||
GtkWidget *view;
|
||||
GtkWidget *scroll;
|
||||
|
||||
gtk_init (0, 0);
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "ns-3 Default attributes.");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 600);
|
||||
|
||||
g_signal_connect (window, "delete_event", (GCallback)delete_event_callback, window);
|
||||
GtkTreeStore *model = gtk_tree_store_new (COL_LAST, G_TYPE_POINTER);
|
||||
ModelTypeidCreator creator;
|
||||
creator.Build (model);
|
||||
|
||||
view = create_view_config_default (model);
|
||||
scroll = gtk_scrolled_window_new (0, 0);
|
||||
gtk_container_add (GTK_CONTAINER (scroll), view);
|
||||
|
||||
GtkWidget *vbox = gtk_vbox_new (FALSE, 5);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 0);
|
||||
gtk_box_pack_end (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
|
||||
GtkWidget *hbox = gtk_hbox_new (FALSE, 5);
|
||||
gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
GtkWidget *save = gtk_button_new_with_label ("Save");
|
||||
g_signal_connect (save, "clicked", (GCallback) save_clicked_default, window);
|
||||
gtk_box_pack_end (GTK_BOX (hbox), save, FALSE, FALSE, 0);
|
||||
GtkWidget *load = gtk_button_new_with_label ("Load");
|
||||
g_signal_connect (load, "clicked", (GCallback) load_clicked_default, window);
|
||||
gtk_box_pack_end (GTK_BOX (hbox), load, FALSE, FALSE, 0);
|
||||
GtkWidget *exit = gtk_button_new_with_label ("Run Simulation");
|
||||
g_signal_connect (exit, "clicked", (GCallback) exit_clicked_callback, window);
|
||||
gtk_box_pack_end (GTK_BOX (hbox), exit, FALSE, FALSE, 0);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
gtk_widget_show_all (window);
|
||||
|
||||
gtk_main ();
|
||||
|
||||
gtk_tree_model_foreach (GTK_TREE_MODEL (model),
|
||||
clean_model_callback_config_default,
|
||||
0);
|
||||
|
||||
gtk_widget_destroy (window);
|
||||
}
|
||||
|
||||
void
|
||||
GtkConfigStore::ConfigureAttributes (void)
|
||||
@@ -494,7 +96,7 @@ GtkConfigStore::ConfigureAttributes (void)
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "ns-3 Object attributes.");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 600);
|
||||
|
||||
|
||||
g_signal_connect (window, "delete_event", (GCallback)delete_event_callback, window);
|
||||
|
||||
|
||||
@@ -528,8 +130,8 @@ GtkConfigStore::ConfigureAttributes (void)
|
||||
gtk_main ();
|
||||
|
||||
gtk_tree_model_foreach (GTK_TREE_MODEL (model),
|
||||
clean_model_callback,
|
||||
0);
|
||||
clean_model_callback,
|
||||
0);
|
||||
|
||||
gtk_widget_destroy (window);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Faker Moatamri <faker.moatamri@sophia.inria.fr>
|
||||
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
#ifndef GTK_CONFIG_STORE_H
|
||||
#define GTK_CONFIG_STORE_H
|
||||
|
||||
|
||||
130
src/contrib/model-node-creator.cc
Normal file
130
src/contrib/model-node-creator.cc
Normal file
@@ -0,0 +1,130 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Faker Moatamri <faker.moatamri@sophia.inria.fr>
|
||||
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
#include "model-node-creator.h"
|
||||
namespace ns3 {
|
||||
|
||||
ModelCreator::ModelCreator ()
|
||||
{
|
||||
}
|
||||
void
|
||||
|
||||
ModelCreator::Build (GtkTreeStore *treestore)
|
||||
{
|
||||
m_treestore = treestore;
|
||||
m_iters.push_back (0);
|
||||
//this function will go through all the objects and call on them
|
||||
//DoStartVisitObject, DoIterate and DoEndVisitObject
|
||||
Iterate ();
|
||||
NS_ASSERT (m_iters.size () == 1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ModelCreator::Add (ModelNode *node)
|
||||
{
|
||||
GtkTreeIter *parent = m_iters.back ();
|
||||
GtkTreeIter *current = g_new (GtkTreeIter, 1);
|
||||
gtk_tree_store_append (m_treestore, current, parent);
|
||||
gtk_tree_store_set (m_treestore, current,
|
||||
COL_NODE, node, -1);
|
||||
m_iters.push_back (current);
|
||||
}
|
||||
void
|
||||
ModelCreator::Remove (void)
|
||||
{
|
||||
GtkTreeIter *iter = m_iters.back ();
|
||||
g_free (iter);
|
||||
m_iters.pop_back ();
|
||||
}
|
||||
|
||||
void
|
||||
ModelCreator::DoVisitAttribute (Ptr<Object> object, std::string name)
|
||||
{
|
||||
ModelNode *node = new ModelNode ();
|
||||
node->type = ModelNode::NODE_ATTRIBUTE;
|
||||
node->object = object;
|
||||
node->name = name;
|
||||
Add (node);
|
||||
Remove ();
|
||||
}
|
||||
void
|
||||
ModelCreator::DoStartVisitObject (Ptr<Object> object)
|
||||
{
|
||||
ModelNode *node = new ModelNode ();
|
||||
node->type = ModelNode::NODE_OBJECT;
|
||||
node->object = object;
|
||||
Add (node);
|
||||
}
|
||||
void
|
||||
ModelCreator::DoEndVisitObject (void)
|
||||
{
|
||||
Remove ();
|
||||
}
|
||||
void
|
||||
ModelCreator::DoStartVisitPointerAttribute (Ptr<Object> object, std::string name, Ptr<Object> value)
|
||||
{
|
||||
ModelNode *node = new ModelNode ();
|
||||
node->type = ModelNode::NODE_POINTER;
|
||||
node->object = object;
|
||||
node->name = name;
|
||||
Add (node);
|
||||
}
|
||||
void
|
||||
ModelCreator::DoEndVisitPointerAttribute (void)
|
||||
{
|
||||
Remove ();
|
||||
}
|
||||
void
|
||||
ModelCreator::DoStartVisitArrayAttribute (Ptr<Object> object, std::string name, const ObjectVectorValue &vector)
|
||||
{
|
||||
ModelNode *node = new ModelNode ();
|
||||
node->type = ModelNode::NODE_VECTOR;
|
||||
node->object = object;
|
||||
node->name = name;
|
||||
Add (node);
|
||||
}
|
||||
void
|
||||
ModelCreator::DoEndVisitArrayAttribute (void)
|
||||
{
|
||||
Remove ();
|
||||
}
|
||||
void
|
||||
ModelCreator::DoStartVisitArrayItem (const ObjectVectorValue &vector, uint32_t index, Ptr<Object> item)
|
||||
{
|
||||
GtkTreeIter *parent = m_iters.back ();
|
||||
GtkTreeIter *current = g_new (GtkTreeIter, 1);
|
||||
ModelNode *node = new ModelNode ();
|
||||
node->type = ModelNode::NODE_VECTOR_ITEM;
|
||||
node->object = item;
|
||||
node->index = index;
|
||||
gtk_tree_store_append (m_treestore, current, parent);
|
||||
gtk_tree_store_set (m_treestore, current,
|
||||
COL_NODE, node,
|
||||
-1);
|
||||
m_iters.push_back (current);
|
||||
}
|
||||
void
|
||||
ModelCreator::DoEndVisitArrayItem (void)
|
||||
{
|
||||
GtkTreeIter *iter = m_iters.back ();
|
||||
g_free (iter);
|
||||
m_iters.pop_back ();
|
||||
}
|
||||
}//end namespace ns3
|
||||
73
src/contrib/model-node-creator.h
Normal file
73
src/contrib/model-node-creator.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Faker Moatamri <faker.moatamri@sophia.inria.fr>
|
||||
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
#include "attribute-iterator.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
COL_NODE = 0, COL_LAST
|
||||
};
|
||||
|
||||
struct ModelNode
|
||||
{
|
||||
enum
|
||||
{
|
||||
// store object + attribute name
|
||||
NODE_ATTRIBUTE,
|
||||
// store object + attribute name
|
||||
NODE_POINTER,
|
||||
// store object + attribute name
|
||||
NODE_VECTOR,
|
||||
// store index + value (object)
|
||||
NODE_VECTOR_ITEM,
|
||||
// store object
|
||||
NODE_OBJECT
|
||||
} type;
|
||||
std::string name;
|
||||
Ptr<Object> object;
|
||||
uint32_t index;
|
||||
};
|
||||
class ModelCreator : public AttributeIterator
|
||||
{
|
||||
public:
|
||||
ModelCreator ();
|
||||
|
||||
void Build (GtkTreeStore *treestore);
|
||||
private:
|
||||
virtual void DoVisitAttribute (Ptr<Object> object, std::string name);
|
||||
virtual void DoStartVisitObject (Ptr<Object> object);
|
||||
virtual void DoEndVisitObject (void);
|
||||
virtual void DoStartVisitPointerAttribute (Ptr<Object> object, std::string name, Ptr<Object> value);
|
||||
virtual void DoEndVisitPointerAttribute (void);
|
||||
virtual void DoStartVisitArrayAttribute (Ptr<Object> object, std::string name, const ObjectVectorValue &vector);
|
||||
virtual void DoEndVisitArrayAttribute (void);
|
||||
virtual void DoStartVisitArrayItem (const ObjectVectorValue &vector,
|
||||
uint32_t index, Ptr<Object> item);
|
||||
virtual void DoEndVisitArrayItem (void);
|
||||
void Add (ModelNode *node);
|
||||
void Remove (void);
|
||||
|
||||
GtkTreeStore *m_treestore;
|
||||
std::vector<GtkTreeIter *> m_iters;
|
||||
};
|
||||
}
|
||||
81
src/contrib/model-typeid-creator.cc
Normal file
81
src/contrib/model-typeid-creator.cc
Normal file
@@ -0,0 +1,81 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Faker Moatamri <faker.moatamri@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
#include "model-typeid-creator.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
ModelTypeidCreator::ModelTypeidCreator ()
|
||||
{
|
||||
}
|
||||
void
|
||||
|
||||
ModelTypeidCreator::Build (GtkTreeStore *treestore)
|
||||
{
|
||||
m_treestore = treestore;
|
||||
m_iters.push_back (0);
|
||||
Iterate ();
|
||||
NS_ASSERT (m_iters.size () == 1);
|
||||
}
|
||||
|
||||
void
|
||||
ModelTypeidCreator::Add (ModelTypeid *node)
|
||||
{
|
||||
GtkTreeIter *parent = m_iters.back ();
|
||||
GtkTreeIter *current = g_new (GtkTreeIter, 1);
|
||||
gtk_tree_store_append (m_treestore, current, parent);
|
||||
gtk_tree_store_set (m_treestore, current, COL_TYPEID, node, -1);
|
||||
m_iters.push_back (current);
|
||||
}
|
||||
|
||||
void
|
||||
ModelTypeidCreator::Remove (void)
|
||||
{
|
||||
GtkTreeIter *iter = m_iters.back ();
|
||||
g_free (iter);
|
||||
m_iters.pop_back ();
|
||||
}
|
||||
|
||||
void
|
||||
ModelTypeidCreator::VisitAttribute (TypeId tid, std::string name, std::string defaultValue, uint32_t index)
|
||||
{
|
||||
ModelTypeid *node = new ModelTypeid ();
|
||||
node->type = ModelTypeid::NODE_ATTRIBUTE;
|
||||
node->tid = tid;
|
||||
node->name = name;
|
||||
node->defaultValue = defaultValue;
|
||||
node->index = index;
|
||||
Add (node);
|
||||
Remove ();
|
||||
}
|
||||
|
||||
void
|
||||
ModelTypeidCreator::StartVisitTypeId (std::string name)
|
||||
{
|
||||
ModelTypeid *node = new ModelTypeid ();
|
||||
node->type = ModelTypeid::NODE_TYPEID;
|
||||
node->tid = TypeId::LookupByName (name);
|
||||
Add (node);
|
||||
}
|
||||
|
||||
void
|
||||
ModelTypeidCreator::EndVisitTypeId (void)
|
||||
{
|
||||
Remove ();
|
||||
}
|
||||
}//end namespace ns3
|
||||
82
src/contrib/model-typeid-creator.h
Normal file
82
src/contrib/model-typeid-creator.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Moatamri Faker <faker.moatamri@sophia.inria.fr>
|
||||
*/
|
||||
|
||||
#include "attribute-default-iterator.h"
|
||||
#include "ns3/type-id.h"
|
||||
#include <gtk/gtk.h>
|
||||
#include <vector>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
enum
|
||||
{
|
||||
COL_TYPEID = 0, COL_LASTID
|
||||
};
|
||||
|
||||
struct ModelTypeid
|
||||
{
|
||||
enum
|
||||
{
|
||||
// store TypeId + attribute name +defaultValue and index
|
||||
NODE_ATTRIBUTE,
|
||||
// store TypeId
|
||||
NODE_TYPEID
|
||||
} type;
|
||||
std::string name;
|
||||
std::string defaultValue;
|
||||
//The TypeId object and if it is an attribute, it's the TypeId object of the attribute
|
||||
TypeId tid;
|
||||
//stores the index of the attribute in list of attributes for a given TypeId
|
||||
uint32_t index;
|
||||
};
|
||||
class ModelTypeidCreator : public AttributeDefaultIterator
|
||||
{
|
||||
public:
|
||||
ModelTypeidCreator ();
|
||||
/**
|
||||
* \brief This method will iterate on typeIds having default attributes and create a model
|
||||
* for them, this model will be used by the view.
|
||||
*/
|
||||
void Build (GtkTreeStore *treestore);
|
||||
private:
|
||||
/**
|
||||
* \brief This method will add a ModelTypeid to the GtkTreeIterator
|
||||
*/
|
||||
virtual void VisitAttribute (TypeId tid, std::string name, std::string defaultValue, uint32_t index);
|
||||
/**
|
||||
* \brief Add a node for the new TypeId object
|
||||
*/
|
||||
virtual void StartVisitTypeId (std::string name);
|
||||
/**
|
||||
* \brief Remove the last gtk tree iterator
|
||||
*/
|
||||
virtual void EndVisitTypeId (void);
|
||||
/**
|
||||
* \brief Adds a treestore iterator to m_treestore model
|
||||
*/
|
||||
void Add (ModelTypeid *node);
|
||||
/**
|
||||
* Removes the last GtkTreeIterator from m_iters
|
||||
*/
|
||||
void Remove (void);
|
||||
//this is the TreeStore model corresponding to the view
|
||||
GtkTreeStore *m_treestore;
|
||||
//This contains a vector of iterators used to build the TreeStore
|
||||
std::vector<GtkTreeIter *> m_iters;
|
||||
};
|
||||
}
|
||||
@@ -41,7 +41,7 @@ RawTextConfigSave::Default (void)
|
||||
virtual void StartVisitTypeId (std::string name) {
|
||||
m_typeId = name;
|
||||
}
|
||||
virtual void VisitAttribute (std::string name, std::string defaultValue) {
|
||||
virtual void DoVisitAttribute (std::string name, std::string defaultValue) {
|
||||
*m_os << "default " << m_typeId << "::" << name << " \"" << defaultValue << "\"" << std::endl;
|
||||
}
|
||||
std::string m_typeId;
|
||||
|
||||
@@ -47,7 +47,11 @@ def build(bld):
|
||||
|
||||
if bld.env['ENABLE_GTK_CONFIG_STORE']:
|
||||
headers.source.append ('gtk-config-store.h')
|
||||
module.source.append ('gtk-config-store.cc')
|
||||
module.source.extend (['gtk-config-store.cc',
|
||||
'model-node-creator.cc',
|
||||
'model-typeid-creator.cc',
|
||||
'display-functions.cc',
|
||||
])
|
||||
module.uselib = 'GTK_CONFIG_STORE'
|
||||
|
||||
if bld.env['ENABLE_LIBXML2']:
|
||||
|
||||
@@ -90,7 +90,7 @@ XmlConfigSave::Default (void)
|
||||
virtual void StartVisitTypeId (std::string name) {
|
||||
m_typeid = name;
|
||||
}
|
||||
virtual void VisitAttribute (std::string name, std::string defaultValue) {
|
||||
virtual void DoVisitAttribute (std::string name, std::string defaultValue) {
|
||||
int rc;
|
||||
rc = xmlTextWriterStartElement(m_writer, BAD_CAST "default");
|
||||
if (rc < 0)
|
||||
|
||||
@@ -272,6 +272,14 @@ EmuNetDevice::StartDevice (void)
|
||||
Ptr<RealtimeSimulatorImpl> impl = DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ());
|
||||
m_rtImpl = GetPointer (impl);
|
||||
|
||||
//
|
||||
// A similar story exists for the node ID. We can't just naively do a
|
||||
// GetNode ()->GetId () since GetNode is going to give us a Ptr<Node> which
|
||||
// is reference counted. We need to stash away the node ID for use in the
|
||||
// read thread.
|
||||
//
|
||||
m_nodeId = GetNode ()->GetId ();
|
||||
|
||||
NS_LOG_LOGIC ("Creating socket");
|
||||
|
||||
//
|
||||
@@ -757,10 +765,10 @@ EmuNetDevice::ReadThread (void)
|
||||
return;
|
||||
}
|
||||
|
||||
NS_LOG_INFO ("EmuNetDevice::ReadThread(): Received packet");
|
||||
NS_LOG_INFO ("EmuNetDevice::EmuNetDevice(): Received packet on node " << m_nodeId);
|
||||
NS_LOG_INFO ("EmuNetDevice::ReadThread(): Scheduling handler");
|
||||
NS_ASSERT_MSG (m_rtImpl, "EmuNetDevice::ReadThread(): Realtime simulator implementation pointer not set");
|
||||
m_rtImpl->ScheduleRealtimeNowWithContext (GetNode ()->GetId (), MakeEvent (&EmuNetDevice::ForwardUp, this, buf, len));
|
||||
m_rtImpl->ScheduleRealtimeNowWithContext (m_nodeId, MakeEvent (&EmuNetDevice::ForwardUp, this, buf, len));
|
||||
buf = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -513,6 +513,13 @@ private:
|
||||
* Never free this pointer!
|
||||
*/
|
||||
RealtimeSimulatorImpl *m_rtImpl;
|
||||
|
||||
/*
|
||||
* a copy of the node id so the read thread doesn't have to GetNode() in
|
||||
* in order to find the node ID. Thread unsafe reference counting in
|
||||
* multithreaded apps is not a good thing.
|
||||
*/
|
||||
uint32_t m_nodeId;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -205,6 +205,14 @@ TapBridge::StartTapDevice (void)
|
||||
Ptr<RealtimeSimulatorImpl> impl = DynamicCast<RealtimeSimulatorImpl> (Simulator::GetImplementation ());
|
||||
m_rtImpl = GetPointer (impl);
|
||||
|
||||
//
|
||||
// A similar story exists for the node ID. We can't just naively do a
|
||||
// GetNode ()->GetId () since GetNode is going to give us a Ptr<Node> which
|
||||
// is reference counted. We need to stash away the node ID for use in the
|
||||
// read thread.
|
||||
//
|
||||
m_nodeId = GetNode ()->GetId ();
|
||||
|
||||
//
|
||||
// Spin up the tap bridge and start receiving packets.
|
||||
//
|
||||
@@ -648,11 +656,10 @@ TapBridge::ReadThread (void)
|
||||
return;
|
||||
}
|
||||
|
||||
NS_LOG_INFO ("TapBridge::ReadThread(): Received packet on node " << m_node->GetId ());
|
||||
NS_LOG_INFO ("TapBridge::ReadThread(): Received packet on node " << m_nodeId);
|
||||
NS_LOG_INFO ("TapBridge::ReadThread(): Scheduling handler");
|
||||
NS_ASSERT_MSG (m_rtImpl, "EmuNetDevice::ReadThread(): Realtime simulator implementation pointer not set");
|
||||
m_rtImpl->ScheduleRealtimeNowWithContext (GetNode ()->GetId (),
|
||||
MakeEvent (&TapBridge::ForwardToBridgedDevice, this, buf, len));
|
||||
m_rtImpl->ScheduleRealtimeNowWithContext (m_nodeId, MakeEvent (&TapBridge::ForwardToBridgedDevice, this, buf, len));
|
||||
buf = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,6 +457,13 @@ private:
|
||||
* Never free this pointer!
|
||||
*/
|
||||
RealtimeSimulatorImpl *m_rtImpl;
|
||||
|
||||
/*
|
||||
* a copy of the node id so the read thread doesn't have to GetNode() in
|
||||
* in order to find the node ID. Thread unsafe reference counting in
|
||||
* multithreaded apps is not a good thing.
|
||||
*/
|
||||
uint32_t m_nodeId;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -109,6 +109,7 @@ public:
|
||||
/**
|
||||
* \param packet Packet to store.
|
||||
* \param hdr 802.11 header for packet.
|
||||
* \param tStamp time stamp for packet
|
||||
*
|
||||
* Stores <i>packet</i> for a possible future retransmission. Retransmission occurs
|
||||
* if the packet, in a block ack frame, is indicated by recipient as not received.
|
||||
@@ -156,6 +157,7 @@ public:
|
||||
/**
|
||||
* \param recipient Address of peer station involved in block ack mechanism.
|
||||
* \param tid Traffic ID of transmitted packet.
|
||||
* \param startingSeq starting sequence field
|
||||
*
|
||||
* Puts corresponding agreement in established state and updates number of packets
|
||||
* and starting sequence field. Invoked typically after a block ack refresh.
|
||||
@@ -205,7 +207,8 @@ public:
|
||||
*/
|
||||
void TearDownBlockAck (Mac48Address recipient, uint8_t tid);
|
||||
/**
|
||||
* \param Sequence number of the packet which fragment is part of.
|
||||
* \param sequenceNumber Sequence number of the packet which fragment is
|
||||
* part of.
|
||||
*
|
||||
* Returns true if another fragment with sequence number <i>sequenceNumber</i> is scheduled
|
||||
* for retransmission.
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
NS_LOG_COMPONENT_DEFINE ("DcaTxop");
|
||||
|
||||
#undef NS_LOG_APPEND_CONTEXT
|
||||
#define NS_LOG_APPEND_CONTEXT std::clog << "[mac=" << m_low->GetAddress () << "] ";
|
||||
#define NS_LOG_APPEND_CONTEXT if (m_low != 0) {std::clog << "[mac=" << m_low->GetAddress () << "] ";}
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
NS_LOG_COMPONENT_DEFINE ("EdcaTxopN");
|
||||
|
||||
#undef NS_LOG_APPEND_CONTEXT
|
||||
#define NS_LOG_APPEND_CONTEXT std::clog << "[mac=" << m_low->GetAddress () << "] ";
|
||||
#define NS_LOG_APPEND_CONTEXT if (m_low != 0) {std::clog << "[mac=" << m_low->GetAddress () << "] ";}
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
MsduStandardAggregator ();
|
||||
~MsduStandardAggregator ();
|
||||
/**
|
||||
* \param packet Packet we have to insert into </i>aggregatedPacket</i>.
|
||||
* \param packet Packet we have to insert into <i>aggregatedPacket</i>.
|
||||
* \param aggregatedPacket Packet that will contain <i>packet</i>, if aggregation is possible,
|
||||
* \param src Source address of <i>packet</i>.
|
||||
* \param dest Destination address of <i>packet</i>.
|
||||
|
||||
@@ -137,7 +137,7 @@ public:
|
||||
* \param lrx lower right x value
|
||||
* \param lry lower right y value
|
||||
*/
|
||||
void BoundingBox (double, double, double, double);
|
||||
void BoundingBox (double ulx, double uly, double lrx, double lry);
|
||||
|
||||
private:
|
||||
NodeContainer m_leftLeaf;
|
||||
|
||||
@@ -90,6 +90,7 @@ public:
|
||||
* \param daddr The destination Ipv4Address
|
||||
* \param sport The source port number
|
||||
* \param dport The destination port number
|
||||
* \param oif The output interface bound. Defaults to null (unspecified).
|
||||
*/
|
||||
void Send (Ptr<Packet> packet,
|
||||
Ipv4Address saddr, Ipv4Address daddr,
|
||||
|
||||
@@ -35,8 +35,8 @@ class Waypoint
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \param _time time of waypoint.
|
||||
* \param _position position of waypoint corresponding to the given time.
|
||||
* \param waypointTime time of waypoint.
|
||||
* \param waypointPosition position of waypoint corresponding to the given time.
|
||||
*
|
||||
* Create a waypoint.
|
||||
*/
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
|
||||
/**
|
||||
* \brief Specify application start time
|
||||
* \param startTime Start time for this application,
|
||||
* \param start Start time for this application,
|
||||
* relative to the current simulation time.
|
||||
*
|
||||
* Applications start at various times in the simulation scenario.
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
|
||||
/**
|
||||
* \brief Specify application stop time
|
||||
* \param stopTime Stop time for this application, relative to the
|
||||
* \param stop Stop time for this application, relative to the
|
||||
* current simulation time.
|
||||
*
|
||||
* Once an application has started, it is sometimes useful
|
||||
|
||||
@@ -529,7 +529,7 @@ public:
|
||||
* is also possible to bind to mismatching device and address, even if
|
||||
* the socket can not receive any packets as a result.
|
||||
*
|
||||
* \param Netdevice Pointer to Netdevice of desired interface
|
||||
* \param netdevice Pointer to Netdevice of desired interface
|
||||
* \returns nothing
|
||||
*/
|
||||
virtual void BindToNetDevice (Ptr<NetDevice> netdevice);
|
||||
|
||||
@@ -39,10 +39,19 @@ TypeHeader::TypeHeader (MessageType t) :
|
||||
{
|
||||
}
|
||||
|
||||
TypeId
|
||||
TypeHeader::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::aodv::TypeHeader")
|
||||
.SetParent<Header> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId
|
||||
TypeHeader::GetInstanceTypeId () const
|
||||
{
|
||||
return TypeId ();
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -134,10 +143,20 @@ RreqHeader::RreqHeader (uint8_t flags, uint8_t reserved, uint8_t hopCount, uint3
|
||||
{
|
||||
}
|
||||
|
||||
TypeId
|
||||
RreqHeader::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::aodv::RreqHeader")
|
||||
.SetParent<Header> ()
|
||||
.AddConstructor<RreqHeader> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId
|
||||
RreqHeader::GetInstanceTypeId () const
|
||||
{
|
||||
return TypeId ();
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -261,10 +280,20 @@ RrepHeader::RrepHeader (uint8_t prefixSize, uint8_t hopCount, Ipv4Address dst,
|
||||
m_lifeTime = uint32_t (lifeTime.GetMilliSeconds ());
|
||||
}
|
||||
|
||||
TypeId
|
||||
RrepHeader::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::aodv::RrepHeader")
|
||||
.SetParent<Header> ()
|
||||
.AddConstructor<RrepHeader> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId
|
||||
RrepHeader::GetInstanceTypeId () const
|
||||
{
|
||||
return TypeId ();
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -392,10 +421,20 @@ RrepAckHeader::RrepAckHeader () :
|
||||
{
|
||||
}
|
||||
|
||||
TypeId
|
||||
RrepAckHeader::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::aodv::RrepAckHeader")
|
||||
.SetParent<Header> ()
|
||||
.AddConstructor<RrepAckHeader> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId
|
||||
RrepAckHeader::GetInstanceTypeId () const
|
||||
{
|
||||
return TypeId ();
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -446,10 +485,20 @@ RerrHeader::RerrHeader () :
|
||||
{
|
||||
}
|
||||
|
||||
TypeId
|
||||
RerrHeader::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::aodv::RerrHeader")
|
||||
.SetParent<Header> ()
|
||||
.AddConstructor<RerrHeader> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId
|
||||
RerrHeader::GetInstanceTypeId () const
|
||||
{
|
||||
return TypeId ();
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
||||
@@ -58,6 +58,7 @@ public:
|
||||
|
||||
///\name Header serialization/deserialization
|
||||
//\{
|
||||
static TypeId GetTypeId ();
|
||||
TypeId GetInstanceTypeId () const;
|
||||
uint32_t GetSerializedSize () const;
|
||||
void Serialize (Buffer::Iterator start) const;
|
||||
@@ -109,6 +110,7 @@ public:
|
||||
|
||||
///\name Header serialization/deserialization
|
||||
//\{
|
||||
static TypeId GetTypeId ();
|
||||
TypeId GetInstanceTypeId () const;
|
||||
uint32_t GetSerializedSize () const;
|
||||
void Serialize (Buffer::Iterator start) const;
|
||||
@@ -184,6 +186,7 @@ public:
|
||||
Ipv4Address (), Time lifetime = MilliSeconds (0));
|
||||
///\name Header serialization/deserialization
|
||||
//\{
|
||||
static TypeId GetTypeId ();
|
||||
TypeId GetInstanceTypeId () const;
|
||||
uint32_t GetSerializedSize () const;
|
||||
void Serialize (Buffer::Iterator start) const;
|
||||
@@ -248,6 +251,7 @@ public:
|
||||
|
||||
///\name Header serialization/deserialization
|
||||
//\{
|
||||
static TypeId GetTypeId ();
|
||||
TypeId GetInstanceTypeId () const;
|
||||
uint32_t GetSerializedSize () const;
|
||||
void Serialize (Buffer::Iterator start) const;
|
||||
@@ -289,6 +293,7 @@ public:
|
||||
|
||||
///\name Header serialization/deserialization
|
||||
//\{
|
||||
static TypeId GetTypeId ();
|
||||
TypeId GetInstanceTypeId () const;
|
||||
uint32_t GetSerializedSize () const;
|
||||
void Serialize (Buffer::Iterator i) const;
|
||||
|
||||
@@ -53,7 +53,7 @@ class Ipv4NixVectorRouting : public Ipv4RoutingProtocol
|
||||
*
|
||||
* @param node Node pointer
|
||||
*/
|
||||
void SetNode (Ptr<Node>);
|
||||
void SetNode (Ptr<Node> node);
|
||||
|
||||
/**
|
||||
* @brief Called when run-time link topology change occurs
|
||||
|
||||
@@ -336,7 +336,6 @@ Simulator::GetMaximumSimulationTime (void)
|
||||
uint32_t
|
||||
Simulator::GetContext (void)
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
return GetImpl ()->GetContext ();
|
||||
}
|
||||
|
||||
|
||||
@@ -85,13 +85,14 @@ def configure(conf):
|
||||
|
||||
|
||||
def create_ns3_module(bld, name, dependencies=()):
|
||||
module = bld.new_task_gen('cxx')
|
||||
module = bld.new_task_gen('cxx', 'cc')
|
||||
module.name = 'ns3-' + name
|
||||
module.target = module.name
|
||||
module.add_objects = ['ns3-' + dep for dep in dependencies]
|
||||
module.module_deps = list(dependencies)
|
||||
if not module.env['ENABLE_STATIC_NS3']:
|
||||
module.env.append_value('CXXFLAGS', module.env['shlib_CXXFLAGS'])
|
||||
module.env.append_value('CCFLAGS', module.env['shlib_CXXFLAGS'])
|
||||
elif module.env['CXX_NAME'] in ['gcc', 'icc'] and \
|
||||
os.uname()[4] == 'x86_64' and \
|
||||
module.env['ENABLE_PYTHON_BINDINGS']:
|
||||
@@ -99,8 +100,10 @@ def create_ns3_module(bld, name, dependencies=()):
|
||||
# when gcc is present and only when we want python bindings
|
||||
# (it's more efficient to not use this option if we can avoid it)
|
||||
module.env.append_value('CXXFLAGS', '-mcmodel=large')
|
||||
module.env.append_value('CCFLAGS', '-mcmodel=large')
|
||||
|
||||
module.env.append_value('CXXDEFINES', "NS3_MODULE_COMPILATION")
|
||||
module.env.append_value('CCDEFINES', "NS3_MODULE_COMPILATION")
|
||||
return module
|
||||
|
||||
def create_obj(bld, *args):
|
||||
|
||||
@@ -31,6 +31,17 @@ if sys.platform == 'win32':
|
||||
else:
|
||||
dev_null = open("/dev/null", "w")
|
||||
|
||||
fcntl = fd = fl = None
|
||||
try:
|
||||
import fcntl
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
fd = dev_null.fileno()
|
||||
fl = fcntl.fcntl(fd, fcntl.F_GETFD)
|
||||
fcntl.fcntl(fd, fcntl.F_SETFD, fl | fcntl.FD_CLOEXEC)
|
||||
del fcntl, fd, fl
|
||||
|
||||
def _open_out_file(filename):
|
||||
if filename in ['NUL:', '/dev/null']:
|
||||
return dev_null
|
||||
|
||||
8
wscript
8
wscript
@@ -112,6 +112,7 @@ def dist_hook():
|
||||
|
||||
def set_options(opt):
|
||||
# options provided by the modules
|
||||
opt.tool_options('compiler_cc')
|
||||
opt.tool_options('compiler_cxx')
|
||||
opt.tool_options('cflags')
|
||||
|
||||
@@ -236,6 +237,7 @@ def configure(conf):
|
||||
conf.env['NS3_OPTIONAL_FEATURES'] = []
|
||||
|
||||
conf.env['NS3_BUILDDIR'] = conf.blddir
|
||||
conf.check_tool('compiler_cc')
|
||||
conf.check_tool('compiler_cxx')
|
||||
conf.check_tool('cflags')
|
||||
try:
|
||||
@@ -277,8 +279,6 @@ def configure(conf):
|
||||
conf.setenv(variant_name)
|
||||
env = variant_env
|
||||
|
||||
env.append_value('CXXDEFINES', 'RUN_SELF_TESTS')
|
||||
|
||||
if env['COMPILER_CXX'] == 'g++' and 'CXXFLAGS' not in os.environ:
|
||||
if conf.check_compilation_flag('-Wno-error=deprecated-declarations'):
|
||||
env.append_value('CXXFLAGS', '-Wno-error=deprecated-declarations')
|
||||
@@ -388,6 +388,10 @@ def configure(conf):
|
||||
conf.env.append_value('CXXDEFINES', "ENABLE_GSL")
|
||||
conf.env.append_value('CCDEFINES', "ENABLE_GSL")
|
||||
|
||||
# for compiling C code, copy over the CXX* flags
|
||||
conf.env.append_value('CCFLAGS', conf.env['CXXFLAGS'])
|
||||
conf.env.append_value('CCDEFINES', conf.env['CXXDEFINES'])
|
||||
|
||||
# append user defined flags after all our ones
|
||||
for (confvar, envvar) in [['CCFLAGS', 'CCFLAGS_EXTRA'],
|
||||
['CXXFLAGS', 'CXXFLAGS_EXTRA'],
|
||||
|
||||
Reference in New Issue
Block a user