Commit f309591fa35f7da9583c67cbe5aba15ebb362075

Authored by Steve Greedy
1 parent b8958cac

Update to SW1

1. Bug fix: Corrected memory allocation issue affecting certain platforms.
2. SACAMOS version checking
3. Additional Looging
GUI/SW1/SRC/ABOUT.cpp
... ... @@ -123,6 +123,8 @@ void ABOUT::DisplayLicenseFile()
123 123 TextCtrl1->SetValue(text);
124 124 }
125 125  
  126 + LicenseFile.Close();
  127 +
126 128 }
127 129  
128 130 void ABOUT::DisplayBuildFile()
... ... @@ -140,8 +142,9 @@ void ABOUT::DisplayBuildFile()
140 142 text = text + "\n";
141 143 }
142 144 TextCtrl2->SetValue(text);
143   -
144 145 }
  146 +
  147 + BuildFile.Close();
145 148 }
146 149  
147 150 void ABOUT::OnInit(wxInitDialogEvent& event)
... ...
GUI/SW1/SRC/LOGGER.cpp 0 → 100644
... ... @@ -0,0 +1,74 @@
  1 +// Logger.cpp
  2 +// Implementation of a multithread safe singleton logger class
  3 +#include <stdexcept>
  4 +#include "logger.h"
  5 +
  6 +using namespace std;
  7 +
  8 +const string Logger::kLogLevelHeader = "HEADER";
  9 +const string Logger::kLogLevelDebug = "DEBUG";
  10 +const string Logger::kLogLevelInfo = "INFO";
  11 +const string Logger::kLogLevelError = "ERROR";
  12 +
  13 +const char* const Logger::kLogFileName = "log.out";
  14 +
  15 +Logger* Logger::pInstance = nullptr;
  16 +
  17 +mutex Logger::sMutex;
  18 +
  19 +Logger& Logger::instance()
  20 +{
  21 + static Cleanup cleanup;
  22 +
  23 + lock_guard<mutex> guard(sMutex);
  24 + if (pInstance == nullptr)
  25 + pInstance = new Logger();
  26 + return *pInstance;
  27 +}
  28 +
  29 +Logger::Cleanup::~Cleanup()
  30 +{
  31 + lock_guard<mutex> guard(Logger::sMutex);
  32 + delete Logger::pInstance;
  33 + Logger::pInstance = nullptr;
  34 +}
  35 +
  36 +Logger::~Logger()
  37 +{
  38 + mOutputStream.close();
  39 +}
  40 +
  41 +Logger::Logger()
  42 +{
  43 + mOutputStream.open(kLogFileName, ios_base::app);
  44 + if (!mOutputStream.good()) {
  45 + throw runtime_error("Unable to initialize the Logger!");
  46 + }
  47 +}
  48 +
  49 +void Logger::log(const string& inMessage, const string& inLogLevel)
  50 +{
  51 + lock_guard<mutex> guard(sMutex);
  52 + logHelper(inMessage, inLogLevel);
  53 +}
  54 +
  55 +void Logger::log(const vector<string>& inMessages, const string& inLogLevel)
  56 +{
  57 + lock_guard<mutex> guard(sMutex);
  58 + for (size_t i = 0; i < inMessages.size(); i++) {
  59 + logHelper(inMessages[i], inLogLevel);
  60 + }
  61 +}
  62 +
  63 +void Logger::logHelper(const std::string& inMessage, const std::string& inLogLevel)
  64 +{
  65 + char tCurrentTime [80];
  66 +
  67 + time (&tTimeRaw);
  68 + tTimeNow = localtime (&tTimeRaw);
  69 +
  70 + strftime (tCurrentTime,80,"%X",tTimeNow);
  71 +
  72 + mOutputStream << tCurrentTime <<"\t";
  73 + mOutputStream << inLogLevel << ": \t" << inMessage << endl;
  74 +}
... ...
GUI/SW1/SRC/LOGGER.h 0 → 100644
... ... @@ -0,0 +1,69 @@
  1 +#ifndef LOGGER_H_
  2 +#define LOGGER_H_
  3 +
  4 +// Logger.h
  5 +#include <iostream>
  6 +#include <iomanip>
  7 +#include <fstream>
  8 +#include <vector>
  9 +#include <string>
  10 +#include <mutex>
  11 +#include <ctime>
  12 +
  13 +// Definition of a multithread safe singleton logger class
  14 +class Logger
  15 +{
  16 +public:
  17 + static const std::string kLogLevelHeader;
  18 + static const std::string kLogLevelDebug;
  19 + static const std::string kLogLevelInfo;
  20 + static const std::string kLogLevelError;
  21 +
  22 + // Returns a reference to the singleton Logger object
  23 + static Logger& instance();
  24 +
  25 + // Logs a single message at the given log level
  26 + void log(const std::string& inMessage,
  27 + const std::string& inLogLevel);
  28 +
  29 + // Logs a vector of messages at the given log level
  30 + void log(const std::vector<std::string>& inMessages,
  31 + const std::string& inLogLevel);
  32 +
  33 +protected:
  34 + // Static variable for the one-and-only instance
  35 + static Logger* pInstance;
  36 +
  37 + // Constant for the filename
  38 + static const char* const kLogFileName;
  39 +
  40 + // Data member for the output stream
  41 + std::ofstream mOutputStream;
  42 +
  43 + // Data type for acquiring current time
  44 + std::time_t tTimeRaw;
  45 + std::tm* tTimeNow;
  46 +
  47 + // Embedded class to make sure the single Logger
  48 + // instance gets deleted on program shutdown.
  49 + friend class Cleanup;
  50 + class Cleanup
  51 + {
  52 + public:
  53 + ~Cleanup();
  54 + };
  55 +
  56 + // Logs message. The thread should own a lock on sMutex
  57 + // before calling this function.
  58 + void logHelper(const std::string& inMessage,
  59 + const std::string& inLogLevel);
  60 +
  61 +private:
  62 + Logger();
  63 + virtual ~Logger();
  64 + Logger(const Logger&);
  65 + Logger& operator=(const Logger&);
  66 + static std::mutex sMutex;
  67 +};
  68 +
  69 +#endif // LOGGER_H_
... ...
GUI/SW1/SRC/SW1_GUIApp.cpp
... ... @@ -32,7 +32,7 @@
32 32 // NAME
33 33 // SW1_GUIApp.cpp
34 34 //
35   -// DESCRIPTION
  35 +// DESCRIPTIONbre
36 36 // Main application GUI for SACAMOS
37 37 //
38 38 // AUTHOR(S)
... ... @@ -51,9 +51,140 @@ IMPLEMENT_APP(SW1_GUIApp);
51 51  
52 52 bool SW1_GUIApp::OnInit()
53 53 {
  54 +
  55 + wxTextFile BuildFile;
  56 +
  57 + wxString systeminfo, buildtext, guiversion, cmdversion;
  58 +
  59 + wxDateTime DateToday = wxDateTime::Now();
  60 +
  61 + wxString str = DateToday.Format(wxT("%d-%m-%y"), wxDateTime::Local );
  62 +
  63 + string Date = str.ToStdString();
  64 +
  65 + string updatemessage;
  66 +
  67 +
  68 + Logger::instance().log(Date, Logger::kLogLevelHeader);
  69 + Logger::instance().log("", Logger::kLogLevelHeader);
  70 + Logger::instance().log("SACAMOS STARTED", Logger::kLogLevelHeader);
  71 + Logger::instance().log("===============", Logger::kLogLevelHeader);
  72 +
  73 + Logger::instance().log("Host Information:", Logger::kLogLevelHeader);
  74 + Logger::instance().log("", Logger::kLogLevelHeader);
  75 +
  76 + systeminfo = wxGetHostName();
  77 + Logger::instance().log(systeminfo.ToStdString(), Logger::kLogLevelHeader);
  78 +
  79 + systeminfo = wxPlatformInfo::Get().GetOperatingSystemDescription();
  80 + Logger::instance().log(systeminfo.ToStdString(), Logger::kLogLevelHeader);
  81 +
  82 + Logger::instance().log("", Logger::kLogLevelHeader);
  83 + Logger::instance().log("SACAMOS Build:", Logger::kLogLevelHeader);
  84 +
  85 + if (BuildFile.Open("resources/Build"))
  86 + {
  87 + for (int i = 0; i<8; i++)
  88 + {
  89 + buildtext = BuildFile[i];
  90 +
  91 + if (i==1) guiversion = BuildFile[i];
  92 +
  93 + if (i==5) cmdversion = BuildFile[i];
  94 +
  95 + Logger::instance().log(buildtext.ToStdString(), Logger::kLogLevelHeader);
  96 + }
  97 + }
  98 +
  99 + BuildFile.Close();
  100 +
  101 + // Compare current version against latest release version
  102 + Logger::instance().log("Checking for Software Update...", Logger::kLogLevelHeader);
  103 +
  104 + wxHTTP checkupdate;
  105 +
  106 + wxInputStream *latest_versioninfo;
  107 +
  108 + wxString version_temp = "";
  109 +
  110 + wxStringOutputStream out_stream(&version_temp);
  111 +
  112 + checkupdate.SetHeader(_T("Content-type"), _T("text/html; charset=utf-8"));
  113 +
  114 + std::string latest_version,latest_version_number, latest_version_date;
  115 + std::string current_version,current_version_number, current_version_date;
  116 +
  117 + if (checkupdate.Connect(_T("128.243.70.77"))) // only the server, no pages here yet ...
  118 + {
  119 + Logger::instance().log("Connected to SACAMOS Repository", Logger::kLogLevelInfo);
  120 +
  121 + latest_versioninfo = checkupdate.GetInputStream(_T("/UoN/SACAMOS/raw/master/version_information.inc"));
  122 +
  123 + latest_versioninfo->Read(out_stream);
  124 +
  125 + latest_version = version_temp.ToStdString();
  126 +
  127 + wxDELETE(latest_versioninfo);
  128 + }
  129 + else
  130 + {
  131 + //fail silently & log event
  132 + Logger::instance().log("Could not connect to SACAMOS Repository", Logger::kLogLevelError);
  133 + }
  134 +
  135 + checkupdate.Close();
  136 +
  137 + std::istringstream stream{latest_version};
  138 +
  139 + if (latest_version != "")
  140 + {
  141 + std::getline(stream, latest_version_number);
  142 +
  143 + if (latest_version_number != SACAMOS_V_NUMBER)
  144 + {
  145 + size_t pos;
  146 +
  147 + string latest_version_number_trimmed;
  148 + pos = latest_version_number.find("=");
  149 + latest_version_number_trimmed = latest_version_number.substr(pos+2);
  150 + latest_version_number_trimmed = latest_version_number_trimmed.substr(0,latest_version_number_trimmed.size()-1);
  151 +
  152 + string current_version_number_trimmed;
  153 + pos = SACAMOS_V_NUMBER.find("=");
  154 + current_version_number_trimmed = SACAMOS_V_NUMBER.substr(pos+2);
  155 + current_version_number_trimmed = current_version_number_trimmed.substr(0,latest_version_number_trimmed.size());
  156 +
  157 + updatemessage = "You are running SACAMOS " + current_version_number_trimmed + "\n\n";
  158 + updatemessage+= "The latest version is " + latest_version_number_trimmed + "\n\n";
  159 + updatemessage+= "Please visit www.sacamos.org to download the latest version.";
  160 +
  161 + wxString myString(updatemessage);
  162 + wxMessageBox(updatemessage,"Please Update");
  163 +
  164 + }
  165 + }
  166 +
  167 + // Display splash screen
  168 + wxBitmap splashimage;
  169 +
  170 + wxImage::AddHandler(new wxPNGHandler);
  171 +
  172 + splashimage.LoadFile(_T("resources/Sacamos_About.png"), wxBITMAP_TYPE_PNG);
  173 +
  174 + wxSplashScreen *splashscrn = new wxSplashScreen(splashimage,
  175 + wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT,
  176 + 0, NULL, -1, wxDefaultPosition, wxDefaultSize,
  177 + wxSIMPLE_BORDER|wxSTAY_ON_TOP);
  178 +
  179 + wxYield();
  180 + wxSleep(2);
  181 + splashscrn->Destroy();
  182 +
54 183 //(*AppInitialize
55 184 bool wxsOK = true;
56 185 wxInitAllImageHandlers();
  186 +
  187 +
57 188 if ( wxsOK )
58 189 {
59 190 SW1_GUIFrame* Frame = new SW1_GUIFrame(0);
... ... @@ -61,6 +192,7 @@ bool SW1_GUIApp::OnInit()
61 192 SetTopWindow(Frame);
62 193 }
63 194 //*)
  195 +
64 196 return wxsOK;
65 197  
66 198 }
... ...
GUI/SW1/SRC/SW1_GUIApp.h
... ... @@ -45,10 +45,30 @@
45 45  
46 46 #include <wx/app.h>
47 47  
  48 +// Additional wxWidgets Includes
  49 +#include <wx/statbmp.h>
  50 +#include <wx/splash.h>
  51 +#include <wx/utils.h>
  52 +#include <wx/sstream.h>
  53 +#include <wx/protocol/http.h>
  54 +#include <wx/platform.h>
  55 +
  56 +// Application Includes
  57 +#include "LOGGER.h"
  58 +
  59 +// Standard Library Header File
  60 +#include <string>
  61 +
  62 +
48 63 class SW1_GUIApp : public wxApp
49 64 {
50 65 public:
51 66 virtual bool OnInit();
  67 +
  68 + std::string SACAMOS_V_NUMBER = "SPICE_CABLE_MODEL_BUILDER_version=\"v2.1.0\"";
  69 + std::string SACAMOS_V_DATE = "SPICE_CABLE_MODEL_BUILDER_date=\"16th April 2018\"";
  70 +
  71 + //SPICE_CABLE_MODEL_BUILDER_date="16th April 2018"
52 72 };
53 73  
54 74 #endif // SW1_GUIAPP_H
... ...
GUI/SW1/SRC/SW1_GUIMain.cpp
... ... @@ -47,6 +47,9 @@
47 47 #include <wx/settings.h>
48 48 #include <wx/intl.h>
49 49 #include <wx/string.h>
  50 +#include <wx/bitmap.h>
  51 +#include <wx/icon.h>
  52 +#include <wx/image.h>
50 53 //*)
51 54  
52 55 #define debug 0
... ... @@ -121,8 +124,18 @@ SW1_GUIFrame::SW1_GUIFrame(wxWindow* parent,wxWindowID id)
121 124 wxMenu* Menu2;
122 125  
123 126 Create(parent, wxID_ANY, _("SACAMOS"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("wxID_ANY"));
  127 +// {
  128 +// wxIcon FrameIcon;
  129 +// FrameIcon.CopyFromBitmap(wxBitmap(wxImage(_T("resources/spacewire_schematic_64x64.ico"))));
  130 +// SetIcon(FrameIcon);
  131 +// }
  132 +
  133 +
  134 +
124 135 FlexGridSizer1 = new wxFlexGridSizer(1, 2, 0, 5);
125   - FlexGridSizer1->AddGrowableCol(0);
  136 +
  137 + //FlexGridSizer1->AddGrowableCol(0);
  138 +
126 139 FlexGridSizer1->AddGrowableCol(1);
127 140 FlexGridSizer1->AddGrowableRow(0);
128 141 StaticBoxSizer1 = new wxStaticBoxSizer(wxVERTICAL, this, _("MOD Browser"));
... ... @@ -133,7 +146,13 @@ SW1_GUIFrame::SW1_GUIFrame(wxWindow* parent,wxWindowID id)
133 146 Panel2 = new wxPanel(this, ID_PANEL2, wxDefaultPosition, wxSize(600,600), wxSIMPLE_BORDER|wxTAB_TRAVERSAL|wxFULL_REPAINT_ON_RESIZE, _T("ID_PANEL2"));
134 147 Panel2->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION));
135 148 Panel2->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
  149 +
  150 +
  151 + //StaticBitmap1 = new wxStaticBitmap(Panel2, ID_STATICBITMAP1, wxBitmap(wxImage(_T("resources/Sacamos_Logo_v2.png"))), wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxFULL_REPAINT_ON_RESIZE, _T("ID_STATICBITMAP1"));
136 152 StaticBitmap1 = new wxStaticBitmap(Panel2, ID_STATICBITMAP1, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxFULL_REPAINT_ON_RESIZE, _T("ID_STATICBITMAP1"));
  153 +
  154 +
  155 +
137 156 StaticBoxSizer2->Add(Panel2, 1, wxALL|wxEXPAND, 5);
138 157 FlexGridSizer1->Add(StaticBoxSizer2, 2, wxALL|wxEXPAND, 5);
139 158 SetSizer(FlexGridSizer1);
... ... @@ -273,6 +292,8 @@ void SW1_GUIFrame::OnSelectMOD(wxCommandEvent&amp; event)
273 292  
274 293 PopulateTheDirectoryTree (SelectedFile);
275 294 }
  295 +
  296 +
276 297 dirDialog->Destroy();
277 298  
278 299 wxString separator(wxFileName::GetPathSeparator());
... ... @@ -342,7 +363,9 @@ void SW1_GUIFrame::PopulateTheDirectoryTree ( wxString RootFolder)
342 363 {
343 364 int size_h, size_v;
344 365  
345   - if (tree != NULL)
  366 + Panel1->GetSize(&size_h, &size_v );
  367 +
  368 + if (tree != NULL )
346 369 {
347 370 Disconnect(tree->GetTreeCtrl()->GetId(),wxEVT_COMMAND_TREE_SEL_CHANGED , (wxObjectEventFunction) (wxEventFunction)(wxCommandEventFunction) &SW1_GUIFrame::OnTreeSelection);
348 371 Disconnect(tree->GetTreeCtrl()->GetId(),wxEVT_COMMAND_TREE_ITEM_ACTIVATED, (wxObjectEventFunction) (wxEventFunction)(wxCommandEventFunction) &SW1_GUIFrame::OnTreeSelectionChanged);
... ... @@ -350,14 +373,9 @@ void SW1_GUIFrame::PopulateTheDirectoryTree ( wxString RootFolder)
350 373 tree -> Destroy();
351 374 }
352 375  
353   -
354   - tree = (wxSpecificDirCtrl *) NULL;
355   -
356   - Panel1->GetSize(&size_h, &size_v );
357   -
358 376 tree = new wxSpecificDirCtrl (Panel1, -1, RootFolder,
359 377 wxDefaultPosition,
360   - wxSize(-1,-1),
  378 + wxSize(size_h,size_v),
361 379 wxSIMPLE_BORDER,
362 380 "*.cable_spec;*.bundle_spec;*.spice_model_spec", 0,
363 381 _T("Directory Listing"));
... ... @@ -653,11 +671,7 @@ void SW1_GUIFrame::OnEXPORTSPICE(wxCommandEvent&amp; event)
653 671  
654 672 void SW1_GUIFrame::OnPanel1Paint(wxPaintEvent& event)
655 673 {
656   - if (tree != NULL){
657   - int size_h, size_v;
658   - Panel1->GetSize(&size_h, &size_v );
659   - tree->SetSize(size_h,size_v);
660   - }
  674 +
661 675 }
662 676  
663 677 void SW1_GUIFrame::OnPanel2Paint(wxPaintEvent& event)
... ...
GUI/SW1/SRC/SW1_GUIMain.h
... ... @@ -102,7 +102,7 @@ class SW1_GUIFrame: public wxFrame
102 102 void OnTreeSelection ( wxTreeEvent& evt );
103 103 void CreateCable (wxString, wxString, bool);
104 104  
105   - wxSpecificDirCtrl *tree;
  105 + wxSpecificDirCtrl *tree = NULL; //NULL used to remain consistent with wxWidgets use of the standard NULL macro
106 106  
107 107 wxString PathToMOD;
108 108 wxString SelectedFile;
... ...