summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Moore <timoore@redhat.com>2009-12-09 22:09:39 +0100
committerTim Moore <timoore@redhat.com>2009-12-09 22:09:39 +0100
commit3e1613e1f7ab589089e8ed5a504330bb9cb128db (patch)
treecc2a639738801467b52dad823d2eb4e2b187bf4e
parentf4ba7c13533b7e99edd0e66a0f6ccd6c0f55ec38 (diff)
downloadsystemtap-steved-3e1613e1f7ab589089e8ed5a504330bb9cb128db.tar.gz
systemtap-steved-3e1613e1f7ab589089e8ed5a504330bb9cb128db.tar.xz
systemtap-steved-3e1613e1f7ab589089e8ed5a504330bb9cb128db.zip
show the status of stap processes in the process window
Also, the "kill" button now works. * grapher/StapParser.hxx (_ioConnection, _errIoConnection): new members for sigc connections. (initIo): New function (parsers, parserListChangedSignal): new variables * grapher/StapParser.cxx (ioCallback): disconnect signals when child dies (initIo): new function * grapher/grapher.cxx (StapLauncher): eliminate death callback in favor of childDied signal. Use global parsers list (ProcWindow::_listSelection): new member (ProcWindow::show, hide, onParserListChanged, onSelectionChanged, onKill): new functions (ProcWindow::ProcWindow): Set up cell renderer for status icon * grapher/processwindow.glade: labels for display script and stap arguments
-rw-r--r--grapher/StapParser.cxx338
-rw-r--r--grapher/StapParser.hxx8
-rw-r--r--grapher/grapher.cxx167
-rw-r--r--grapher/processwindow.glade132
4 files changed, 418 insertions, 227 deletions
diff --git a/grapher/StapParser.cxx b/grapher/StapParser.cxx
index b82cc024..a9a5109a 100644
--- a/grapher/StapParser.cxx
+++ b/grapher/StapParser.cxx
@@ -30,7 +30,15 @@ namespace systemtap
static sigc::signal<void, pid_t> deathSignal;
return deathSignal;
}
-
+
+ ParserList parsers;
+
+ sigc::signal<void>& parserListChangedSignal()
+ {
+ static sigc::signal<void> listChangedSignal;
+ return listChangedSignal;
+ }
+
vector<string> commaSplit(const boost::sub_range<Glib::ustring>& range)
{
using namespace boost;
@@ -72,171 +80,173 @@ vector<string> commaSplit(const boost::sub_range<Glib::ustring>& range)
}
bool StapParser::ioCallback(Glib::IOCondition ioCondition)
- {
- using namespace std;
- using std::tr1::shared_ptr;
- using namespace boost;
- if (ioCondition & Glib::IO_HUP)
- {
- childDiedSignal().emit(getPid());
- return true;
- }
- if ((ioCondition & Glib::IO_IN) == 0)
+ {
+ using namespace std;
+ using std::tr1::shared_ptr;
+ using namespace boost;
+ if (ioCondition & Glib::IO_HUP)
+ {
+ childDiedSignal().emit(getPid());
+ _ioConnection.disconnect();
+ _errIoConnection.disconnect();
+ return true;
+ }
+ if ((ioCondition & Glib::IO_IN) == 0)
+ return true;
+ char buf[256];
+ ssize_t bytes_read = 0;
+ bytes_read = read(_inFd, buf, sizeof(buf) - 1);
+ if (bytes_read <= 0)
+ {
+ childDiedSignal().emit(getPid());
return true;
- char buf[256];
- ssize_t bytes_read = 0;
- bytes_read = read(_inFd, buf, sizeof(buf) - 1);
- if (bytes_read <= 0)
- {
- childDiedSignal().emit(getPid());
- return true;
- }
- _buffer.append(buf, bytes_read);
- string::size_type ret = string::npos;
- while ((ret = _buffer.find(_lineEndChar)) != string::npos)
- {
- Glib::ustring dataString(_buffer, 0, ret);
- // %DataSet and %CSV declare a data set; all other
- // statements begin with the name of a data set.
- // Except %LineEnd :)
- sub_range<Glib::ustring> found;
- if (dataString[0] == '%')
- {
- if ((found = find_first(dataString, "%DataSet:")))
- {
- string setName;
- int hexColor;
- double scale;
- string style;
- istringstream stream(Glib::ustring(found.end(),
- dataString.end()));
- stream >> setName >> scale >> std::hex >> hexColor
- >> style;
- if (style == "bar" || style == "dot")
- {
- std::tr1::shared_ptr<GraphData<double> >
- dataSet(new GraphData<double>);
- dataSet->name = setName;
- if (style == "dot")
- dataSet->style = &GraphStyleDot::instance;
- dataSet->color[0] = (hexColor >> 16) / 255.0;
- dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0;
- dataSet->color[2] = (hexColor & 0xff) / 255.0;
- dataSet->scale = scale;
- _dataSets.insert(std::make_pair(setName, dataSet));
- getGraphData().push_back(dataSet);
- graphDataSignal().emit();
- }
- else if (style == "discreet")
- {
- std::tr1::shared_ptr<GraphData<string> >
- dataSet(new GraphData<string>);
- dataSet->name = setName;
- dataSet->style = &GraphStyleEvent::instance;
- dataSet->color[0] = (hexColor >> 16) / 255.0;
- dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0;
- dataSet->color[2] = (hexColor & 0xff) / 255.0;
- dataSet->scale = scale;
- _dataSets.insert(std::make_pair(setName, dataSet));
- getGraphData().push_back(dataSet);
- graphDataSignal().emit();
- }
- }
- else if ((found = find_first(dataString, "%CSV:")))
- {
- vector<string> tokens
- = commaSplit(sub_range<Glib::ustring>(found.end(),
- dataString.end()));
- for (vector<string>::iterator tokIter = tokens.begin(),
- e = tokens.end();
- tokIter != e;
- ++tokIter)
- {
- DataMap::iterator setIter = _dataSets.find(*tokIter);
- if (setIter != _dataSets.end())
- _csv.elements
- .push_back(CSVData::Element(*tokIter,
- setIter->second));
- }
- }
- else if ((found = find_first(dataString, "%LineEnd:")))
- {
- istringstream stream(Glib::ustring(found.end(),
- dataString.end()));
- int charAsInt = 0;
- // parse hex and octal numbers too
- stream >> std::setbase(0) >> charAsInt;
- _lineEndChar = static_cast<char>(charAsInt);
- }
- else
- {
- cerr << "Unknown declaration " << dataString << endl;
- }
- }
- else
- {
- std::istringstream stream(dataString);
- string setName;
- stream >> setName;
- DataMap::iterator itr = _dataSets.find(setName);
- if (itr != _dataSets.end())
- {
- shared_ptr<GraphDataBase> gdata = itr->second;
- string decl;
- // Hack: scan from the beginning of dataString again
- if (findTaggedValue(dataString, "%Title:", decl))
- {
- gdata->title = decl;
- }
- else if (findTaggedValue(dataString, "%XAxisTitle:", decl))
- {
- gdata->xAxisText = decl;
- }
- else if (findTaggedValue(dataString, "%YAxisTitle:", decl))
- {
- gdata->yAxisText = decl;
- }
- else if ((found = find_first(dataString, "%YMax:")))
- {
- double ymax;
- std::istringstream
- stream(Glib::ustring(found.end(), dataString.end()));
- stream >> ymax;
- gdata->scale = ymax;
- }
- else
+ }
+ _buffer.append(buf, bytes_read);
+ string::size_type ret = string::npos;
+ while ((ret = _buffer.find(_lineEndChar)) != string::npos)
+ {
+ Glib::ustring dataString(_buffer, 0, ret);
+ // %DataSet and %CSV declare a data set; all other
+ // statements begin with the name of a data set.
+ // Except %LineEnd :)
+ sub_range<Glib::ustring> found;
+ if (dataString[0] == '%')
+ {
+ if ((found = find_first(dataString, "%DataSet:")))
+ {
+ string setName;
+ int hexColor;
+ double scale;
+ string style;
+ istringstream stream(Glib::ustring(found.end(),
+ dataString.end()));
+ stream >> setName >> scale >> std::hex >> hexColor
+ >> style;
+ if (style == "bar" || style == "dot")
+ {
+ std::tr1::shared_ptr<GraphData<double> >
+ dataSet(new GraphData<double>);
+ dataSet->name = setName;
+ if (style == "dot")
+ dataSet->style = &GraphStyleDot::instance;
+ dataSet->color[0] = (hexColor >> 16) / 255.0;
+ dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0;
+ dataSet->color[2] = (hexColor & 0xff) / 255.0;
+ dataSet->scale = scale;
+ _dataSets.insert(std::make_pair(setName, dataSet));
+ getGraphData().push_back(dataSet);
+ graphDataSignal().emit();
+ }
+ else if (style == "discreet")
{
- if (!_csv.elements.empty())
+ std::tr1::shared_ptr<GraphData<string> >
+ dataSet(new GraphData<string>);
+ dataSet->name = setName;
+ dataSet->style = &GraphStyleEvent::instance;
+ dataSet->color[0] = (hexColor >> 16) / 255.0;
+ dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0;
+ dataSet->color[2] = (hexColor & 0xff) / 255.0;
+ dataSet->scale = scale;
+ _dataSets.insert(std::make_pair(setName, dataSet));
+ getGraphData().push_back(dataSet);
+ graphDataSignal().emit();
+ }
+ }
+ else if ((found = find_first(dataString, "%CSV:")))
+ {
+ vector<string> tokens
+ = commaSplit(sub_range<Glib::ustring>(found.end(),
+ dataString.end()));
+ for (vector<string>::iterator tokIter = tokens.begin(),
+ e = tokens.end();
+ tokIter != e;
+ ++tokIter)
+ {
+ DataMap::iterator setIter = _dataSets.find(*tokIter);
+ if (setIter != _dataSets.end())
+ _csv.elements
+ .push_back(CSVData::Element(*tokIter,
+ setIter->second));
+ }
+ }
+ else if ((found = find_first(dataString, "%LineEnd:")))
+ {
+ istringstream stream(Glib::ustring(found.end(),
+ dataString.end()));
+ int charAsInt = 0;
+ // parse hex and octal numbers too
+ stream >> std::setbase(0) >> charAsInt;
+ _lineEndChar = static_cast<char>(charAsInt);
+ }
+ else
+ {
+ cerr << "Unknown declaration " << dataString << endl;
+ }
+ }
+ else
+ {
+ std::istringstream stream(dataString);
+ string setName;
+ stream >> setName;
+ DataMap::iterator itr = _dataSets.find(setName);
+ if (itr != _dataSets.end())
+ {
+ shared_ptr<GraphDataBase> gdata = itr->second;
+ string decl;
+ // Hack: scan from the beginning of dataString again
+ if (findTaggedValue(dataString, "%Title:", decl))
+ {
+ gdata->title = decl;
+ }
+ else if (findTaggedValue(dataString, "%XAxisTitle:", decl))
+ {
+ gdata->xAxisText = decl;
+ }
+ else if (findTaggedValue(dataString, "%YAxisTitle:", decl))
+ {
+ gdata->yAxisText = decl;
+ }
+ else if ((found = find_first(dataString, "%YMax:")))
+ {
+ double ymax;
+ std::istringstream
+ stream(Glib::ustring(found.end(), dataString.end()));
+ stream >> ymax;
+ gdata->scale = ymax;
+ }
+ else
+ {
+ if (!_csv.elements.empty())
{
- vector<string> tokens = commaSplit(dataString);
- int i = 0;
- int64_t time;
- vector<string>::iterator tokIter = tokens.begin();
- std::istringstream timeStream(*tokIter++);
- timeStream >> time;
- for (vector<string>::iterator e = tokens.end();
- tokIter != e;
- ++tokIter, ++i)
+ vector<string> tokens = commaSplit(dataString);
+ int i = 0;
+ int64_t time;
+ vector<string>::iterator tokIter = tokens.begin();
+ std::istringstream timeStream(*tokIter++);
+ timeStream >> time;
+ for (vector<string>::iterator e = tokens.end();
+ tokIter != e;
+ ++tokIter, ++i)
{
- parseData(_csv.elements[i].second, time,
- *tokIter);
+ parseData(_csv.elements[i].second, time,
+ *tokIter);
}
}
- else
+ else
{
- int64_t time;
- stringbuf data;
- stream >> time;
- stream.get(data, _lineEndChar);
- parseData(itr->second, time, data.str());
+ int64_t time;
+ stringbuf data;
+ stream >> time;
+ stream.get(data, _lineEndChar);
+ parseData(itr->second, time, data.str());
}
}
- }
- }
- _buffer.erase(0, ret + 1);
- }
- return true;
- }
+ }
+ }
+ _buffer.erase(0, ret + 1);
+ }
+ return true;
+ }
bool StapParser::errIoCallback(Glib::IOCondition ioCondition)
{
@@ -255,4 +265,18 @@ vector<string> commaSplit(const boost::sub_range<Glib::ustring>& range)
;
return true;
}
+
+ void StapParser::initIo(int inFd, int errFd)
+ {
+ _inFd = inFd;
+ _errFd = errFd;
+ _ioConnection = Glib::signal_io()
+ .connect(sigc::mem_fun(*this, &StapParser::errIoCallback),
+ _errFd,
+ Glib::IO_IN);
+ _errIoConnection = Glib::signal_io()
+ .connect(sigc::mem_fun(*this, &StapParser::ioCallback),
+ _inFd,
+ Glib::IO_IN | Glib::IO_HUP);
+ }
}
diff --git a/grapher/StapParser.hxx b/grapher/StapParser.hxx
index cfb807a8..4dd711e6 100644
--- a/grapher/StapParser.hxx
+++ b/grapher/StapParser.hxx
@@ -38,6 +38,8 @@ namespace systemtap
int _inFd;
unsigned char _lineEndChar;
std::tr1::shared_ptr<StapProcess> _process;
+ sigc::connection _ioConnection;
+ sigc::connection _errIoConnection;
public:
StapParser()
: _errFd(-1), _inFd(-1), _lineEndChar('\n')
@@ -63,7 +65,13 @@ namespace systemtap
{
_process = process;
}
+ void initIo(int inFd, int errFd);
};
sigc::signal<void, pid_t>& childDiedSignal();
+
+ typedef std::vector<std::tr1::shared_ptr<StapParser> > ParserList;
+ extern ParserList parsers;
+
+ sigc::signal<void>& parserListChangedSignal();
}
diff --git a/grapher/grapher.cxx b/grapher/grapher.cxx
index 2a9a617b..00670fe0 100644
--- a/grapher/grapher.cxx
+++ b/grapher/grapher.cxx
@@ -106,14 +106,14 @@ private:
class StapLauncher : public ChildDeathReader
{
public:
- StapLauncher() : _argv(0), _childPid(-1), _deathCallback(0) {}
+ StapLauncher() : _argv(0), _childPid(-1) {}
StapLauncher(char** argv)
- : _argv(argv), _childPid(-1), _deathCallback(0)
+ : _argv(argv), _childPid(-1)
{
}
StapLauncher(const string& stapArgs, const string& script,
const string& scriptArgs)
- : _childPid(-1), _deathCallback(0), _win(0), _widget(0)
+ : _childPid(-1), _win(0), _widget(0)
{
setArgs(stapArgs, script, scriptArgs);
}
@@ -149,10 +149,7 @@ public:
_script.clear();
_scriptArgs.clear();
}
- void setDeathCallback(ChildDeathReader::Callback* callback)
- {
- _deathCallback = callback;
- }
+
void setWinParams(Gtk::Window* win, GraphWidget* widget)
{
_win = win;
@@ -163,7 +160,8 @@ public:
shared_ptr<StapParser> makeStapParser()
{
shared_ptr<StapParser> result(new StapParser);
- _parsers.push_back(result);
+ parsers.push_back(result);
+ parserListChangedSignal().emit();
return result;
}
private:
@@ -184,14 +182,22 @@ public:
if (pid < 0)
return pid;
ParserList::iterator itr
- = find_if(_parsers.begin(), _parsers.end(), pidPred(pid));
- if (itr != _parsers.end())
- (*itr)->setProcess(tr1::shared_ptr<StapProcess>());
+ = find_if(parsers.begin(), parsers.end(), pidPred(pid));
+ if (itr != parsers.end())
+ {
+ tr1::shared_ptr<StapProcess> sp = (*itr)->getProcess();
+ if (sp)
+ {
+ sp->pid = -1;
+ parserListChangedSignal().emit();
+ }
+ }
+ childDiedSignal().emit(pid);
return pid;
}
void killAll()
{
- for (ParserList::iterator itr = _parsers.begin(), end = _parsers.end();
+ for (ParserList::iterator itr = parsers.begin(), end = parsers.end();
itr != end;
++itr)
{
@@ -199,15 +205,12 @@ public:
kill((*itr)->getPid(), SIGTERM);
}
}
- typedef vector<shared_ptr<StapParser> > ParserList;
- ParserList _parsers;
protected:
char** _argv;
string _stapArgs;
string _script;
string _scriptArgs;
int _childPid;
- ChildDeathReader::Callback* _deathCallback;
Gtk::Window* _win;
GraphWidget* _widget;
};
@@ -287,17 +290,9 @@ int StapLauncher::launch()
proc->scriptArgs = _scriptArgs;
}
sp->setProcess(proc);
- _parsers.push_back(sp);
- sp->setErrFd(pipefd[2]);
- sp->setInFd(pipefd[0]);
- Glib::signal_io().connect(sigc::mem_fun(sp.get(),
- &StapParser::errIoCallback),
- pipefd[2],
- Glib::IO_IN);
- Glib::signal_io().connect(sigc::mem_fun(sp.get(),
- &StapParser::ioCallback),
- pipefd[0],
- Glib::IO_IN | Glib::IO_HUP);
+ parsers.push_back(sp);
+ parserListChangedSignal().emit();
+ sp->initIo(pipefd[0], pipefd[2]);
return childPid;
}
@@ -313,7 +308,7 @@ void StapLauncher::cleanUp()
char buf;
while (read(signalPipe[0], &buf, 1) > 0)
reap();
- for (ParserList::iterator itr = _parsers.begin(), end = _parsers.end();
+ for (ParserList::iterator itr = parsers.begin(), end = parsers.end();
itr != end;
++itr)
{
@@ -331,8 +326,10 @@ void StapLauncher::cleanUp()
std::cerr << "wait: killed Pid " << killedPid << " != child Pid "
<< childPid << "\n";
}
- else if (_deathCallback)
- _deathCallback->childDied(childPid);
+ else
+ {
+ childDiedSignal().emit(childPid);
+ }
}
}
@@ -356,13 +353,16 @@ class ProcModelColumns : public Gtk::TreeModelColumnRecord
public:
ProcModelColumns()
{
+ add(_iconName);
add(_scriptName);
add(_proc);
}
+ Gtk::TreeModelColumn<Glib::ustring> _iconName;
Gtk::TreeModelColumn<Glib::ustring> _scriptName;
Gtk::TreeModelColumn<shared_ptr<StapProcess> > _proc;
};
+// This should probably be a Gtk window, with the appropriate glade magic
class ProcWindow
{
public:
@@ -372,10 +372,20 @@ public:
Gtk::Window* _window;
Gtk::TreeView* _dataTreeView;
Glib::RefPtr<Gtk::ListStore> _listStore;
+ Glib::RefPtr<Gtk::TreeSelection> _listSelection;
void onClose();
+ void show();
+ void hide();
+ void onParserListChanged();
+ void onSelectionChanged();
+ void onKill();
+private:
+ bool _open;
+ void refresh();
};
ProcWindow::ProcWindow()
+ : _open(false)
{
try
{
@@ -390,12 +400,27 @@ ProcWindow::ProcWindow()
throw;
}
_listStore = Gtk::ListStore::create(_modelColumns);
- _dataTreeView->set_model(_listStore);
+ _dataTreeView->set_model(_listStore);
+ // Display a nice icon for the state of the process
+ Gtk::CellRendererPixbuf* cell = Gtk::manage(new Gtk::CellRendererPixbuf);
+ _dataTreeView->append_column("State", *cell);
+ Gtk::TreeViewColumn* column = _dataTreeView->get_column(0);
+ if (column)
+ column->add_attribute(cell->property_icon_name(), _modelColumns._iconName);
_dataTreeView->append_column("Script", _modelColumns._scriptName);
Gtk::Button* button = 0;
_xml->get_widget("button5", button);
button->signal_clicked().connect(sigc::mem_fun(*this, &ProcWindow::onClose),
false);
+ _xml->get_widget("button1", button);
+ button->signal_clicked().connect(sigc::mem_fun(*this, &ProcWindow::onKill),
+ false);
+ parserListChangedSignal()
+ .connect(sigc::mem_fun(*this, &ProcWindow::onParserListChanged));
+ _listSelection = _dataTreeView->get_selection();
+ _listSelection->signal_changed()
+ .connect(sigc::mem_fun(*this, &ProcWindow::onSelectionChanged));
+
}
void ProcWindow::onClose()
@@ -403,6 +428,63 @@ void ProcWindow::onClose()
_window->hide();
}
+void ProcWindow::show()
+{
+ _open = true;
+ refresh();
+ _window->show();
+
+}
+
+void ProcWindow::hide()
+{
+ _open = false;
+ _window->hide();
+}
+
+void ProcWindow::refresh()
+{
+ _listStore->clear();
+ for (ParserList::iterator spitr = parsers.begin(), end = parsers.end();
+ spitr != end;
+ ++spitr)
+ {
+ shared_ptr<StapProcess> sp = (*spitr)->getProcess();
+ if (sp)
+ {
+ Gtk::TreeModel::iterator litr = _listStore->append();
+ Gtk::TreeModel::Row row = *litr;
+ row[_modelColumns._iconName] = sp->pid >= 0 ? "gtk-yes" : "gtk-no";
+ row[_modelColumns._scriptName] = sp->script;
+ row[_modelColumns._proc] = sp;
+ }
+ }
+}
+
+void ProcWindow::onParserListChanged()
+{
+ if (_open)
+ {
+ refresh();
+ _window->queue_draw();
+ }
+}
+
+void ProcWindow::onSelectionChanged()
+{
+}
+
+void ProcWindow::onKill()
+{
+ Gtk::TreeModel::iterator itr = _listSelection->get_selected();
+ if (!itr)
+ return;
+ Gtk::TreeModel::Row row = *itr;
+ shared_ptr<StapProcess> proc = row[_modelColumns._proc];
+ if (proc->pid >= 0)
+ kill(proc->pid, SIGTERM);
+}
+
class GrapherWindow : public Gtk::Window, public ChildDeathReader::Callback
{
public:
@@ -411,7 +493,6 @@ public:
Gtk::VBox m_Box;
Gtk::ScrolledWindow scrolled;
GraphWidget w;
- void childDied(int pid);
void setGraphicalLauncher(GraphicalStapLauncher* launcher)
{
_graphicalLauncher = launcher;
@@ -505,30 +586,9 @@ void GrapherWindow::on_menu_script_start()
void GrapherWindow::on_menu_proc_window()
{
- _procWindow->_listStore->clear();
- for (StapLauncher::ParserList::iterator spitr
- = _graphicalLauncher->_parsers.begin(),
- end = _graphicalLauncher->_parsers.end();
- spitr != end;
- ++spitr)
- {
- shared_ptr<StapProcess> sp = (*spitr)->getProcess();
- Gtk::TreeModel::iterator litr = _procWindow->_listStore->append();
- Gtk::TreeModel::Row row = *litr;
- if (sp)
- row[_procWindow->_modelColumns._scriptName] = sp->script;
- }
- _procWindow->_window->show();
+ _procWindow->show();
}
-void GrapherWindow::childDied(int pid)
-{
- hide();
-}
-
-
-
-
int main(int argc, char** argv)
{
Gtk::Main app(argc, argv);
@@ -553,7 +613,6 @@ int main(int argc, char** argv)
else if (argc > 1)
{
launcher.setArgv(argv + 1);
- launcher.setDeathCallback(&win);
launcher.launch();
}
Gtk::Main::run(win);
diff --git a/grapher/processwindow.glade b/grapher/processwindow.glade
index ad1bdd14..3886cb34 100644
--- a/grapher/processwindow.glade
+++ b/grapher/processwindow.glade
@@ -263,23 +263,60 @@
<property name="spacing">0</property>
<child>
- <widget class="GtkLabel" id="label1">
- <property name="height_request">17</property>
+ <widget class="GtkHBox" id="hbox5">
<property name="visible">True</property>
- <property name="label" translatable="yes">label1</property>
- <property name="use_underline">False</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">stap arguments: </property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="padding">0</property>
@@ -289,6 +326,69 @@
</child>
<child>
+ <widget class="GtkHBox" id="hbox6">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">script arguments: </property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
<widget class="GtkScrolledWindow" id="scrolledwindow2">
<property name="visible">True</property>
<property name="can_focus">True</property>