> 
> Well I think self.data is some kind of container with a pickled string, 
> given the code to unpickle it is:
> 
Exactly!  This is what the C++ file 'pickle.h' creates to send to the
Python GUI:


/**
 * A pickled Python dictionary. Used to pass stuff to the UI.
 */
class pickle
{

public:

   /**
    * pickle constructor.
    *
    * \param frame_body A const_bit_queue representing the frame body.
    */
   pickle();

   /**
    * pickle virtual destructor.
    */
   ~pickle();

   /**
    * Add a key/value pair to the pickled dictionary
    */
   void add(std::string key, std::string value);

   /**
    * Returns a string describing the Data Unit ID (DUID).
    */
   std::string to_string() const;

private:

   typedef std::map<std::string, std::string> stringmap;

   stringmap map_;

};

#endif /* INCLUDED_PICKLE_H */

I am pretty sure that it sends a C++ map of strings in a form that
Python understands as a pickle.  I put the code you gave me into the
file so ill have to wait and see.
meanwhile can you please take a look at this update() and tell me if you
see something wrong because ever sense I tried using the array for
logging the values from the TextCtrls the program is not updating
meaning when the program receives the c++ map, or the pickle, I get
nothing in the UI and I get nothing in the log.  There got to be
something wrong with the loop that I can not see.  I attached the file
so its not too much code here.  I am pretty sure the problem is in the
update(0) starts at line 210.


#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  op25_traffic_panel.py
#  
#  Copyright 2013 Balint Seeber <balint@crawfish>
#  
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#  
#  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., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#  
#  
#  MyVersion 1.2
#  the import statements; very similar to #include in c++ 
from time import localtime, strftime
import os
import wx
import cPickle as pickle
import gnuradio.gr.gr_threading as _threading

#  wx is the gui class. it implements a version of "events" -- objects that sit and wait for some data to change, and call a specified function when the change happens
wxDATA_EVENT = wx.NewEventType()

# this is a function that *sets* what happens when the event is triggered. it takes in an event (win) and a function (func)
def EVT_DATA_EVENT(win, func):
    win.Connect(-1, -1, wxDATA_EVENT, func)
    
# the dataevent class -- stores the data that gets transmitted when the event occurs. 
#it is the data in text fields, stored in self.data as a dictionary, which is basically a c++ map
#One of these classes gets created whenever an event occurs. 
class DataEvent(wx.PyEvent):
    # the values of the text fields get passed into the constructor inside of data
    def __init__(self, data):
        wx.PyEvent.__init__(self)
        # this line *binds* this class to a certain type of event, wxDATA_EVENT
        self.SetEventType (wxDATA_EVENT)
        # and this is the actual data
        self.data = data 
        with open('mypicklelog.txt','ab') as log: # open in binary mode
            pickle.dump(pickle.loads(self.data.to_string()), log) # serialize data and write to file

        
    # clone is a python function to make a "deep" copy of an object
    def Clone (self):
        self.__class__ (self.GetId())
        
# thread that waits for new data to be received 
# when event is triggered new data is passed along 
# this class inherits from the standard Python class _threading.Thread
class traffic_watcher_thread(_threading.Thread):
    def __init__(self, rcvd_pktq, event_receiver):
        ## variables are standard values required to set up a thread
        _threading.Thread.__init__(self)
        self.setDaemon(1)
        self.rcvd_pktq = rcvd_pktq
        self.event_receiver = event_receiver
        self.keep_running = True
        self.start()
        
    def stop(self):
        self.keep_running = False
        
    def run(self):
        while self.keep_running:
            msg = self.rcvd_pktq.delete_head()
            ## once data is received, an event is "Posted" with PostEvent. 
            ## This is where the DataEvent object gets created
            de = DataEvent (msg)
            wx.PostEvent (self.event_receiver, de)
            del de
            
# A snapshot of important fields in current traffic
# this inherits from the gui class Panel (required for all gui programs)
class TrafficPane(wx.Panel):
    # Initializer; class constructor
    # 
    def __init__(self, parent, msgq):
        wx.Panel.__init__(self, parent)
        
        self.msgq = msgq
        #with open('msgqlog.txt','a') as log:
            #log.write(self.msgq) 
       
        
        #name array to put traffic data in
        self.log_array = []
       
        #layout of the panel. 10 px gap on each side of TextCtrls. panel is a grid, 
        #texctrls and lables are placed at grid positions like (1,1), (2,1) etc. 
        sizer = wx.GridBagSizer(hgap=10, vgap=10)
        # defines a dictionary ({} = empty dictionary), to hold the text control values
        self.fields = {}
        
        #TextCtrl recipe:
        label = wx.StaticText(self, -1, "DUID:")
        sizer.Add(label, pos=(1,1))        
        field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY)
        sizer.Add(field, pos=(1,2))        
        self.fields["duid"] = field;
        
        label = wx.StaticText(self, -1, "NAC:")
        sizer.Add(label, pos=(2,1))
        field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY)
        sizer.Add(field, pos=(2,2))
        self.fields["nac"] = field;
        
        label = wx.StaticText(self, -1, "Source:")
        sizer.Add(label, pos=(3,1))
        field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY)
        sizer.Add(field, pos=(3,2))
        self.fields["source"] = field;
        
        label = wx.StaticText(self, -1, "Destination:")
        sizer.Add(label, pos=(4,1))
        field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY)
        sizer.Add(field, pos=(4,2))
        self.fields["dest"] = field;
        
        label = wx.StaticText(self, -1, "MFID:")
        sizer.Add(label, pos=(1,4))
        field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY)
        sizer.Add(field, pos=(1,5))
        self.fields["mfid"] = field;
        
        label = wx.StaticText(self, -1, "ALGID:")
        sizer.Add(label, pos=(2,4))
        field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY)
        sizer.Add(field, pos=(2,5))
        self.fields["algid"] = field;
        
        label = wx.StaticText(self, -1, "KID:")
        sizer.Add(label, pos=(3,4))
        field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY)
        sizer.Add(field, pos=(3,5))
        self.fields["kid"] = field;
        
        label = wx.StaticText(self, -1, "MI:")
        sizer.Add(label, pos=(4,4))
        field = wx.TextCtrl(self, -1, "", size=(216, -1), style=wx.TE_READONLY)
        sizer.Add(field, pos=(4,5))
        self.fields["mi"] = field;
        
        label = wx.StaticText(self, -1, "TGID:")
        sizer.Add(label, pos=(5,4))
        field = wx.TextCtrl(self, -1, "", size=(144, -1), style=wx.TE_READONLY)
        sizer.Add(field, pos=(5,5))
        self.fields["tgid"] = field;
        
        # Open file button click event binded to openfile 
        btn = wx.Button(self, -1, "Choose Log File") 
        sizer.Add(btn, pos=(7,2)) 
        btn.Bind(wx.EVT_BUTTON, self.openFile)  
           
        #set the panel layout
        self.SetSizer(sizer)
        
        #makes the gui system fit all the controls onto the panel
        self.Layout()
        self.Fit()
        
        EVT_DATA_EVENT(self, self.display_data)
        self.watcher = traffic_watcher_thread(self.msgq, self)
        
    # openfile defined to start FileDialog and write the traffic log to the file
    def openFile(self, evt):
        with wx.FileDialog(self, "Choose a file", os.getcwd(), "", "*.txt*", wx.OPEN) as dlg:
            if dlg.ShowModal() == wx.ID_OK:
                path = dlg.GetPath()
                mypath = os.path.basename(path)
                with open(mypath, "a") as f:
                    f.writelines(self.log_array)
   
    # Clear the field values
    #
    def clear(self):
        #loops through each value in the dictionary
        #values are actually text control objects
        for v in self.fields.values():
            # clear the text control value
            v.Clear()
            
    # Display the values on the UI
    def display_data(self,event):
        #gets the "message" into the event object
        #message is equal to the "data" parameter in the "DataEvent" class
        message = event.data
       
        # unpickle the string
        pickled_dict = message.to_string()
       
        #separate the string into values for each text control (attrs is a pickle object)
        attrs = pickle.loads(pickled_dict)
       
        #pass this pickle object into update
        self.update(attrs)
        
    # Update the field values
    # put values in array
    def update(self, field_values):
        next_line = ""
        next_line += strftime("%Y-%m-%d %H:%M:%S") 
        next_line +=  ','.join( field_values[k] for k in self.fields.keys() if k in field_values ) 
        self.log_array.append(next_line)
                
        #if the field 'duid' == 'hdu', then clear all the fields
        if field_values['duid'] == 'hdu':
            self.clear()
        #loop through all TextCtrl fields storing the key/value pairs in k, v
        for k,v in self.fields.items():        
            # get the pickle value for this TextCtrl
            f = field_values.get(k, None)            
            # if the value is empty then set the new value
            if f:
                v.SetValue(f)
                
                
if __name__ == '__main__':
    import wx.lib.mixins.inspection as inspect
    # when running it press ctrl-alt-i to help in sizer debug and more
    # this is often refered to as the WIT - Widget Inspection Tool - see the wiki
    app = inspect.InspectableApp(redirect=False)
    f = wx.Frame(None)
    f.p = TrafficPane(f, "")
    f.Fit()
    
    f.Show()
    
    app.MainLoop()

_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor

Reply via email to