Commit f309591fa35f7da9583c67cbe5aba15ebb362075
1 parent
b8958cac
Exists in
master
and in
3 other branches
Update to SW1
1. Bug fix: Corrected memory allocation issue affecting certain platforms. 2. SACAMOS version checking 3. Additional Looging
Showing
7 changed files
with
328 additions
and
16 deletions
Show diff stats
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) | ... | ... |
... | ... | @@ -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 | +} | ... | ... |
... | ... | @@ -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& 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& 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; | ... | ... |