GTK - How to update gtktextview/gtkentry? #C - gtk

i am creating a basic GROUND CONTROL STATION for a CubeSat, dividing it in two parts: COMMANDS (with no problems) and TELEMETRY. I am using C code and GTK; in the telemetry windowt I need to show some info everytime a telemetry packet is received so I've tried to use a gtkview/gtkentry for each info, but I don't know, how to update the message shown in them.
In particular, an example is:
//View PACKET NUMBER
view = gtk_text_view_new();
frame = gtk_frame_new("Packet number");
gtk_container_add(GTK_CONTAINER(frame), view);
gtk_text_view_set_editable(GTK_TEXT_VIEW(view),FALSE);
gtk_table_attach(GTK_TABLE(table2),frame,0,1,0,1,GTK_FILL,GTK_FILL,5,5);
buff = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
gtk_text_buffer_get_iter_at_offset(buff, &iter, 0);
gtk_text_buffer_insert(buff, &iter,"waiting", -1);
so, first there is the text "WAITING", then when a packet is received I want to update that text: how can I do this?
I've tried repeating this code but changing "waiting" with a variable referring to "packet number", but I obtain core dump
I've also tried with this code, but I have always same problem.
viewprova = gtk_entry_new();
frameprova = gtk_frame_new("Packet number");
gtk_container_add(GTK_CONTAINER(frameprova), viewprova);
gtk_entry_set_editable(GTK_ENTRY(viewprova),FALSE);
gtk_table_attach(GTK_TABLE(table2),frameprova,0,1,0,1,GTK_FILL,GTK_FILL,5,5);
gtk_entry_set_text(GTK_ENTRY(viewprova),"waiting");
frameprova = gtk_frame_new("Packet number");
viewprova = gtk_label_new ("waiting");
gtk_container_add(GTK_CONTAINER(frameprova), viewprova);
gtk_table_attach(GTK_TABLE(table2),frameprova,0,1,0,1,GTK_FILL,GTK_FILL,5,5);
Thanks for the help!

A function such as gtk_label_new() that accepts a C string can't take an integer instead, C functions are not polymorphic. You need to build a string representation and pass that, for instance using snprintf() to format the number into a string buffer.

Ok, so if I understood you correctly, you know how to setup your text displaying widgets, but not, how to fill them with new contents, correct? Look at your code, and at what you're doing. First, you're creating a text widget. Then you fill it with initial text. This second part is the one you repeat:
In case of GtkEntry, gtk_entry_set_text(GTK_ENTRY(viewprova), "My new text");
In case of GtkTextView (actually you're using the underlying TextBuffer), gtk_text_buffer_set_text(buff, "My new text", -1);

Related

How to emit socket io variable instead "\"text\"" text notation

Hi
I'm learning to use websocket client in arduino ESP32 board. I can receive and emit text in this form, ""text"" as i can show here.
socketIO.emit("emitevent", "\"this is a message from the client\"");
or
char* Name = "\"Carlos\"";
webSocket.emit("newEmitEvent", Name);
I would like to charge a variable String to send it but i cant find the way. For example,
String Values;
Values = 00:a3:45;
webSocket.emit("newEmitEvent", Values);
But I can't see how to do it,
Can you help me,
please?
Thanks
I've solved with,
Values += """\"";
Values += 00:a3:45;
Values += "," // if i'm in a loop
Values += "\"";
But, it is a clean solution?
Thanks,

Retrieving gdcm DataElement values as strings

I am basically trying to read out all or most attribute values from a DICOM file, using the gdcm C++ library. I am having hard time to get out any non-string values. The gdcm examples generally assume I know the group/element numbers beforehand so I can use the Attribute template classes, but I have no need or interest in them, I just have to report all attribute names and values. Actually the values should go into an XML so I need a string representation. What I currently have is something like:
for (gdcm::DataSet::ConstIterator it = ds.Begin(); it!=ds.End(); ++it) {
const gdcm::DataElement& elem = *it;
if (elem.GetVR() != gdcm::VR::SQ) {
const gdcm::Tag& tag = elem.GetTag();
std::cout << dict.GetDictEntry(tag).GetKeyword() << ": ";
std::cout << elem.GetValue() << "\n";
}
}
It seems for numeric values like UL the output is something like "Loaded:4", presumably meaning that the library has loaded 4 bytes of data (an unsigned long). This is not helpful at all, how to get the actual value? I must be certainly overlooking something obvious.
From the examples it seems there is a gdcm::StringFilter class which is able to do that, but it seems it wants to search each element by itself in the DICOM file, which would make the algorithm complexity quadratic, this is certainly something I would like to avoid.
TIA
Paavo
Have you looked at gdcmdump? You can use it to output the DICOM file as text or XML. You can also look at the source to see how it does this.
I ended up with extracting parts of gdcm::StringFilter::ToStringPair() into a separate function. Seems to work well for simpler DCM files at least...
You could also start by reading the FAQ, in particular How do I convert an attribute value to a string ?
As explained there, you simply need to use gdcm::StringFilter:
sf = gdcm.StringFilter()
sf.SetFile(r.GetFile())
print sf.ToStringPair(gdcm.Tag(0x0028,0x0010))
Try something like this:
gdcm::Reader reader;
reader.SetFileName( absSlicePath.c_str() );
if( !_reader.Read() )
{
return;
}
gdcm::File file = reader.GetFile();
gdcm::DataSet ds = file.GetDataSet();
std::stringstream strm;
strm << ds;
you get a stringstream containing all the DICOM tags-values.
Actually, most of the DICOM classes (DataElement, DataSet, etc) have the std::ostream & operator<< (std::ostream &_os, const *Some_Class* &_val) overloaded. So you can just expand the for loop and use operator<< to put the values into the stringstream, and then into the string.
For example, if you are using QT :
ui->pTagsTxt->append(QString(strm.str().c_str()));

Getting line locations with iText

How can one find where are lines located in a document with iText?
Suppose say I have a table in a PDF document, and want to read its contents; I would like to find where exactly the cells are located. In order to do that I thought I might find the intersections of lines.
I think your only option using iText will be to parse the PDF tokens manually. Before doing that I would have a copy of the PDF spec handy.
(I'm a .Net guy so I use iTextSharp but other than some capitalization differences and property declarations they're almost 100% the same.)
You can get the individual tokens using the PRTokeniser object which you feed bytes into from calling getPageContent(pageNum) on your PdfReader.
//Get bytes for page 1
byte[] pageBytes = reader.getPageContent(1);
//Get the tokens for page 1
PRTokeniser tokeniser = new PRTokeniser(pageBytes);
Then just loop through the PRTokeniser:
PRTokeniser.TokType tokenType;
string tokenValue;
while (tokeniser.nextToken()) {
tokenType = tokeniser.tokenType;
tokenValue = tokeniser.stringValue;
//...check tokenValue, do something with it
}
As far a tokenValue, you'd want to probably look for re and l values for rectangle and line. If you see an re then you want to look at the previous 4 values and if you see an l then previous 2 values. This also means that you need to store each tokenValue in an array so you can look back later.
Depending on what you used to create the PDF with you might get some interesting results. For instance, I created a 4 cell table with Microsoft Word and saved as a PDF. For some reason there are two sets of 10 rectangles with many duplicates, but the general idea still works.
Below is C# code targeting iTextSharp 5.1.1.0. You should be able to convert it to Java and iText very easily, I noted the one line that has .Net-specific code that needs to be adjusted from a Generic List (List<string>) to a Java equivalent, probably an ArrayList. You'll also need to adjust some casing, .Net uses Object.Method() whereas Java uses Object.method(). Lastly, .Net accesses properties without gets and sets, so Object.Property is both the getter and setter compared to Java's Object.getProperty and Object.setProperty.
Hopefully this gets you started at least!
//Source file to read from
string sourceFile = "c:\\Hello.pdf";
//Bind a reader to our PDF
PdfReader reader = new PdfReader(sourceFile);
//Create our buffer for previous token values. For Java users, List<string> is a generic list, probably most similar to an ArrayList
List<string> buf = new List<string>();
//Get the raw bytes for the page
byte[] pageBytes = reader.GetPageContent(1);
//Get the raw tokens from the bytes
PRTokeniser tokeniser = new PRTokeniser(pageBytes);
//Create some variables to set later
PRTokeniser.TokType tokenType;
string tokenValue;
//Loop through each token
while (tokeniser.NextToken()) {
//Get the types and value
tokenType = tokeniser.TokenType;
tokenValue = tokeniser.StringValue;
//If the type is a numeric type
if (tokenType == PRTokeniser.TokType.NUMBER) {
//Store it in our buffer for later user
buf.Add(tokenValue);
//Otherwise we only care about raw commands which are categorized as "OTHER"
} else if (tokenType == PRTokeniser.TokType.OTHER) {
//Look for a rectangle token
if (tokenValue == "re") {
//Sanity check, make sure we have enough items in the buffer
if (buf.Count < 4) throw new Exception("Not enough elements in buffer for a rectangle");
//Read and convert the values
float x = float.Parse(buf[buf.Count - 4]);
float y = float.Parse(buf[buf.Count - 3]);
float w = float.Parse(buf[buf.Count - 2]);
float h = float.Parse(buf[buf.Count - 1]);
//..do something with them here
}
}
}

Gtk, check if GtkTreeView is empty

I have following code to find if row is selected, which is selected and which text is in row of GtkTreeView. Code is in key-release event handler.
char *ntext;
if (gtk_tree_selection_get_selected(treeselen, &modelen ,&iteren))
{
gtk_tree_model_get(modelen, &iteren, cEng, &ntext, -1);
... etc...
This works ok when my view is not empty. But when list is empty I get "segmentation fault".
I think that before this is needed to check if GtkTreeView is empty.
How to do that?
Actually, later I find if list is partially filled with clicking on unfilled area segfault happens too. So I need solution for that too.
From your description, it appears when you say GtkTreeView is empty you mean in model (GtkTreeModel which is implemented by GtkListStore or GtkTreeStore associated with your GtkTreeView) the data rows are added but are empty i.e. data is not set. In that case you need to check the value returned by gtk_tree_model_get (assuming cEng is valid otherwise you will get a warning message while running the program). Problem mostly is in ...etc.... Just add a NULL check to ntext before operating on it.
char *ntext;
if (gtk_tree_selection_get_selected(treeselen, &modelen ,&iteren))
{
gtk_tree_model_get(modelen, &iteren, cEng, &ntext, -1);
if( ntext == NULL )
{
printf("Data is NULL!\n");
/* Handle this case */
}
else
{
.... etc ....
}
}
This could also be the case in you button-press or release callback as well.
Hope this helps!

NodeJS: What is the proper way to handling TCP socket streams ? Which delimiter should I use?

From what I understood here, "V8 has a generational garbage collector. Moves objects aound randomly. Node can’t get a pointer to raw string data to write to socket." so I shouldn't store data that comes from a TCP stream in a string, specially if that string becomes bigger than Math.pow(2,16) bytes. (hope I'm right till now..)
What is then the best way to handle all the data that's comming from a TCP socket ? So far I've been trying to use _:_:_ as a delimiter because I think it's somehow unique and won't mess around other things.
A sample of the data that would come would be something_:_:_maybe a large text_:_:_ maybe tons of lines_:_:_more and more data
This is what I tried to do:
net = require('net');
var server = net.createServer(function (socket) {
socket.on('connect',function() {
console.log('someone connected');
buf = new Buffer(Math.pow(2,16)); //new buffer with size 2^16
socket.on('data',function(data) {
if (data.toString().search('_:_:_') === -1) { // If there's no separator in the data that just arrived...
buf.write(data.toString()); // ... write it on the buffer. it's part of another message that will come.
} else { // if there is a separator in the data that arrived
parts = data.toString().split('_:_:_'); // the first part is the end of a previous message, the last part is the start of a message to be completed in the future. Parts between separators are independent messages
if (parts.length == 2) {
msg = buf.toString('utf-8',0,4) + parts[0];
console.log('MSG: '+ msg);
buf = (new Buffer(Math.pow(2,16))).write(parts[1]);
} else {
msg = buf.toString() + parts[0];
for (var i = 1; i <= parts.length -1; i++) {
if (i !== parts.length-1) {
msg = parts[i];
console.log('MSG: '+msg);
} else {
buf.write(parts[i]);
}
}
}
}
});
});
});
server.listen(9999);
Whenever I try to console.log('MSG' + msg), it will print out the whole buffer, so it's useless to see if something worked.
How can I handle this data the proper way ? Would the lazy module work, even if this data is not line oriented ? Is there some other module to handle streams that are not line oriented ?
It has indeed been said that there's extra work going on because Node has to take that buffer and then push it into v8/cast it to a string. However, doing a toString() on the buffer isn't any better. There's no good solution to this right now, as far as I know, especially if your end goal is to get a string and fool around with it. Its one of the things Ryan mentioned # nodeconf as an area where work needs to be done.
As for delimiter, you can choose whatever you want. A lot of binary protocols choose to include a fixed header, such that you can put things in a normal structure, which a lot of times includes a length. In this way, you slice apart a known header and get information about the rest of the data without having to iterate over the entire buffer. With a scheme like that, one can use a tool like:
node-buffer - https://github.com/substack/node-binary
node-ctype - https://github.com/rmustacc/node-ctype
As an aside, buffers can be accessed via array syntax, and they can also be sliced apart with .slice().
Lastly, check here: https://github.com/joyent/node/wiki/modules -- find a module that parses a simple tcp protocol and seems to do it well, and read some code.
You should use the new stream2 api. http://nodejs.org/api/stream.html
Here are some very useful examples: https://github.com/substack/stream-handbook
https://github.com/lvgithub/stick