From f309591fa35f7da9583c67cbe5aba15ebb362075 Mon Sep 17 00:00:00 2001 From: steve.greedy Date: Fri, 21 Sep 2018 15:15:53 +0100 Subject: [PATCH] Update to SW1 --- GUI/SW1/SRC/ABOUT.cpp | 5 ++++- GUI/SW1/SRC/LOGGER.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ GUI/SW1/SRC/LOGGER.h | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ GUI/SW1/SRC/SW1_GUIApp.cpp | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- GUI/SW1/SRC/SW1_GUIApp.h | 20 ++++++++++++++++++++ GUI/SW1/SRC/SW1_GUIMain.cpp | 40 +++++++++++++++++++++++++++------------- GUI/SW1/SRC/SW1_GUIMain.h | 2 +- 7 files changed, 328 insertions(+), 16 deletions(-) create mode 100644 GUI/SW1/SRC/LOGGER.cpp create mode 100644 GUI/SW1/SRC/LOGGER.h diff --git a/GUI/SW1/SRC/ABOUT.cpp b/GUI/SW1/SRC/ABOUT.cpp index 8efb36d..7103ba9 100644 --- a/GUI/SW1/SRC/ABOUT.cpp +++ b/GUI/SW1/SRC/ABOUT.cpp @@ -123,6 +123,8 @@ void ABOUT::DisplayLicenseFile() TextCtrl1->SetValue(text); } + LicenseFile.Close(); + } void ABOUT::DisplayBuildFile() @@ -140,8 +142,9 @@ void ABOUT::DisplayBuildFile() text = text + "\n"; } TextCtrl2->SetValue(text); - } + + BuildFile.Close(); } void ABOUT::OnInit(wxInitDialogEvent& event) diff --git a/GUI/SW1/SRC/LOGGER.cpp b/GUI/SW1/SRC/LOGGER.cpp new file mode 100644 index 0000000..1ca1918 --- /dev/null +++ b/GUI/SW1/SRC/LOGGER.cpp @@ -0,0 +1,74 @@ +// Logger.cpp +// Implementation of a multithread safe singleton logger class +#include +#include "logger.h" + +using namespace std; + +const string Logger::kLogLevelHeader = "HEADER"; +const string Logger::kLogLevelDebug = "DEBUG"; +const string Logger::kLogLevelInfo = "INFO"; +const string Logger::kLogLevelError = "ERROR"; + +const char* const Logger::kLogFileName = "log.out"; + +Logger* Logger::pInstance = nullptr; + +mutex Logger::sMutex; + +Logger& Logger::instance() +{ + static Cleanup cleanup; + + lock_guard guard(sMutex); + if (pInstance == nullptr) + pInstance = new Logger(); + return *pInstance; +} + +Logger::Cleanup::~Cleanup() +{ + lock_guard guard(Logger::sMutex); + delete Logger::pInstance; + Logger::pInstance = nullptr; +} + +Logger::~Logger() +{ + mOutputStream.close(); +} + +Logger::Logger() +{ + mOutputStream.open(kLogFileName, ios_base::app); + if (!mOutputStream.good()) { + throw runtime_error("Unable to initialize the Logger!"); + } +} + +void Logger::log(const string& inMessage, const string& inLogLevel) +{ + lock_guard guard(sMutex); + logHelper(inMessage, inLogLevel); +} + +void Logger::log(const vector& inMessages, const string& inLogLevel) +{ + lock_guard guard(sMutex); + for (size_t i = 0; i < inMessages.size(); i++) { + logHelper(inMessages[i], inLogLevel); + } +} + +void Logger::logHelper(const std::string& inMessage, const std::string& inLogLevel) +{ + char tCurrentTime [80]; + + time (&tTimeRaw); + tTimeNow = localtime (&tTimeRaw); + + strftime (tCurrentTime,80,"%X",tTimeNow); + + mOutputStream << tCurrentTime <<"\t"; + mOutputStream << inLogLevel << ": \t" << inMessage << endl; +} diff --git a/GUI/SW1/SRC/LOGGER.h b/GUI/SW1/SRC/LOGGER.h new file mode 100644 index 0000000..0fe28de --- /dev/null +++ b/GUI/SW1/SRC/LOGGER.h @@ -0,0 +1,69 @@ +#ifndef LOGGER_H_ +#define LOGGER_H_ + +// Logger.h +#include +#include +#include +#include +#include +#include +#include + +// Definition of a multithread safe singleton logger class +class Logger +{ +public: + static const std::string kLogLevelHeader; + static const std::string kLogLevelDebug; + static const std::string kLogLevelInfo; + static const std::string kLogLevelError; + + // Returns a reference to the singleton Logger object + static Logger& instance(); + + // Logs a single message at the given log level + void log(const std::string& inMessage, + const std::string& inLogLevel); + + // Logs a vector of messages at the given log level + void log(const std::vector& inMessages, + const std::string& inLogLevel); + +protected: + // Static variable for the one-and-only instance + static Logger* pInstance; + + // Constant for the filename + static const char* const kLogFileName; + + // Data member for the output stream + std::ofstream mOutputStream; + + // Data type for acquiring current time + std::time_t tTimeRaw; + std::tm* tTimeNow; + + // Embedded class to make sure the single Logger + // instance gets deleted on program shutdown. + friend class Cleanup; + class Cleanup + { + public: + ~Cleanup(); + }; + + // Logs message. The thread should own a lock on sMutex + // before calling this function. + void logHelper(const std::string& inMessage, + const std::string& inLogLevel); + +private: + Logger(); + virtual ~Logger(); + Logger(const Logger&); + Logger& operator=(const Logger&); + static std::mutex sMutex; +}; + +#endif // LOGGER_H_ diff --git a/GUI/SW1/SRC/SW1_GUIApp.cpp b/GUI/SW1/SRC/SW1_GUIApp.cpp index a5b2c59..f84d84f 100644 --- a/GUI/SW1/SRC/SW1_GUIApp.cpp +++ b/GUI/SW1/SRC/SW1_GUIApp.cpp @@ -32,7 +32,7 @@ // NAME // SW1_GUIApp.cpp // -// DESCRIPTION +// DESCRIPTIONbre // Main application GUI for SACAMOS // // AUTHOR(S) @@ -51,9 +51,140 @@ IMPLEMENT_APP(SW1_GUIApp); bool SW1_GUIApp::OnInit() { + + wxTextFile BuildFile; + + wxString systeminfo, buildtext, guiversion, cmdversion; + + wxDateTime DateToday = wxDateTime::Now(); + + wxString str = DateToday.Format(wxT("%d-%m-%y"), wxDateTime::Local ); + + string Date = str.ToStdString(); + + string updatemessage; + + + Logger::instance().log(Date, Logger::kLogLevelHeader); + Logger::instance().log("", Logger::kLogLevelHeader); + Logger::instance().log("SACAMOS STARTED", Logger::kLogLevelHeader); + Logger::instance().log("===============", Logger::kLogLevelHeader); + + Logger::instance().log("Host Information:", Logger::kLogLevelHeader); + Logger::instance().log("", Logger::kLogLevelHeader); + + systeminfo = wxGetHostName(); + Logger::instance().log(systeminfo.ToStdString(), Logger::kLogLevelHeader); + + systeminfo = wxPlatformInfo::Get().GetOperatingSystemDescription(); + Logger::instance().log(systeminfo.ToStdString(), Logger::kLogLevelHeader); + + Logger::instance().log("", Logger::kLogLevelHeader); + Logger::instance().log("SACAMOS Build:", Logger::kLogLevelHeader); + + if (BuildFile.Open("resources/Build")) + { + for (int i = 0; i<8; i++) + { + buildtext = BuildFile[i]; + + if (i==1) guiversion = BuildFile[i]; + + if (i==5) cmdversion = BuildFile[i]; + + Logger::instance().log(buildtext.ToStdString(), Logger::kLogLevelHeader); + } + } + + BuildFile.Close(); + + // Compare current version against latest release version + Logger::instance().log("Checking for Software Update...", Logger::kLogLevelHeader); + + wxHTTP checkupdate; + + wxInputStream *latest_versioninfo; + + wxString version_temp = ""; + + wxStringOutputStream out_stream(&version_temp); + + checkupdate.SetHeader(_T("Content-type"), _T("text/html; charset=utf-8")); + + std::string latest_version,latest_version_number, latest_version_date; + std::string current_version,current_version_number, current_version_date; + + if (checkupdate.Connect(_T("128.243.70.77"))) // only the server, no pages here yet ... + { + Logger::instance().log("Connected to SACAMOS Repository", Logger::kLogLevelInfo); + + latest_versioninfo = checkupdate.GetInputStream(_T("/UoN/SACAMOS/raw/master/version_information.inc")); + + latest_versioninfo->Read(out_stream); + + latest_version = version_temp.ToStdString(); + + wxDELETE(latest_versioninfo); + } + else + { + //fail silently & log event + Logger::instance().log("Could not connect to SACAMOS Repository", Logger::kLogLevelError); + } + + checkupdate.Close(); + + std::istringstream stream{latest_version}; + + if (latest_version != "") + { + std::getline(stream, latest_version_number); + + if (latest_version_number != SACAMOS_V_NUMBER) + { + size_t pos; + + string latest_version_number_trimmed; + pos = latest_version_number.find("="); + latest_version_number_trimmed = latest_version_number.substr(pos+2); + latest_version_number_trimmed = latest_version_number_trimmed.substr(0,latest_version_number_trimmed.size()-1); + + string current_version_number_trimmed; + pos = SACAMOS_V_NUMBER.find("="); + current_version_number_trimmed = SACAMOS_V_NUMBER.substr(pos+2); + current_version_number_trimmed = current_version_number_trimmed.substr(0,latest_version_number_trimmed.size()); + + updatemessage = "You are running SACAMOS " + current_version_number_trimmed + "\n\n"; + updatemessage+= "The latest version is " + latest_version_number_trimmed + "\n\n"; + updatemessage+= "Please visit www.sacamos.org to download the latest version."; + + wxString myString(updatemessage); + wxMessageBox(updatemessage,"Please Update"); + + } + } + + // Display splash screen + wxBitmap splashimage; + + wxImage::AddHandler(new wxPNGHandler); + + splashimage.LoadFile(_T("resources/Sacamos_About.png"), wxBITMAP_TYPE_PNG); + + wxSplashScreen *splashscrn = new wxSplashScreen(splashimage, + wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT, + 0, NULL, -1, wxDefaultPosition, wxDefaultSize, + wxSIMPLE_BORDER|wxSTAY_ON_TOP); + + wxYield(); + wxSleep(2); + splashscrn->Destroy(); + //(*AppInitialize bool wxsOK = true; wxInitAllImageHandlers(); + + if ( wxsOK ) { SW1_GUIFrame* Frame = new SW1_GUIFrame(0); @@ -61,6 +192,7 @@ bool SW1_GUIApp::OnInit() SetTopWindow(Frame); } //*) + return wxsOK; } diff --git a/GUI/SW1/SRC/SW1_GUIApp.h b/GUI/SW1/SRC/SW1_GUIApp.h index ce819b2..b530c15 100644 --- a/GUI/SW1/SRC/SW1_GUIApp.h +++ b/GUI/SW1/SRC/SW1_GUIApp.h @@ -45,10 +45,30 @@ #include +// Additional wxWidgets Includes +#include +#include +#include +#include +#include +#include + +// Application Includes +#include "LOGGER.h" + +// Standard Library Header File +#include + + class SW1_GUIApp : public wxApp { public: virtual bool OnInit(); + + std::string SACAMOS_V_NUMBER = "SPICE_CABLE_MODEL_BUILDER_version=\"v2.1.0\""; + std::string SACAMOS_V_DATE = "SPICE_CABLE_MODEL_BUILDER_date=\"16th April 2018\""; + + //SPICE_CABLE_MODEL_BUILDER_date="16th April 2018" }; #endif // SW1_GUIAPP_H diff --git a/GUI/SW1/SRC/SW1_GUIMain.cpp b/GUI/SW1/SRC/SW1_GUIMain.cpp index 90c38ce..8b427e4 100644 --- a/GUI/SW1/SRC/SW1_GUIMain.cpp +++ b/GUI/SW1/SRC/SW1_GUIMain.cpp @@ -47,6 +47,9 @@ #include #include #include +#include +#include +#include //*) #define debug 0 @@ -121,8 +124,18 @@ SW1_GUIFrame::SW1_GUIFrame(wxWindow* parent,wxWindowID id) wxMenu* Menu2; Create(parent, wxID_ANY, _("SACAMOS"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("wxID_ANY")); +// { +// wxIcon FrameIcon; +// FrameIcon.CopyFromBitmap(wxBitmap(wxImage(_T("resources/spacewire_schematic_64x64.ico")))); +// SetIcon(FrameIcon); +// } + + + FlexGridSizer1 = new wxFlexGridSizer(1, 2, 0, 5); - FlexGridSizer1->AddGrowableCol(0); + + //FlexGridSizer1->AddGrowableCol(0); + FlexGridSizer1->AddGrowableCol(1); FlexGridSizer1->AddGrowableRow(0); StaticBoxSizer1 = new wxStaticBoxSizer(wxVERTICAL, this, _("MOD Browser")); @@ -133,7 +146,13 @@ SW1_GUIFrame::SW1_GUIFrame(wxWindow* parent,wxWindowID id) Panel2 = new wxPanel(this, ID_PANEL2, wxDefaultPosition, wxSize(600,600), wxSIMPLE_BORDER|wxTAB_TRAVERSAL|wxFULL_REPAINT_ON_RESIZE, _T("ID_PANEL2")); Panel2->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION)); Panel2->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + + + //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")); StaticBitmap1 = new wxStaticBitmap(Panel2, ID_STATICBITMAP1, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxFULL_REPAINT_ON_RESIZE, _T("ID_STATICBITMAP1")); + + + StaticBoxSizer2->Add(Panel2, 1, wxALL|wxEXPAND, 5); FlexGridSizer1->Add(StaticBoxSizer2, 2, wxALL|wxEXPAND, 5); SetSizer(FlexGridSizer1); @@ -273,6 +292,8 @@ void SW1_GUIFrame::OnSelectMOD(wxCommandEvent& event) PopulateTheDirectoryTree (SelectedFile); } + + dirDialog->Destroy(); wxString separator(wxFileName::GetPathSeparator()); @@ -342,7 +363,9 @@ void SW1_GUIFrame::PopulateTheDirectoryTree ( wxString RootFolder) { int size_h, size_v; - if (tree != NULL) + Panel1->GetSize(&size_h, &size_v ); + + if (tree != NULL ) { Disconnect(tree->GetTreeCtrl()->GetId(),wxEVT_COMMAND_TREE_SEL_CHANGED , (wxObjectEventFunction) (wxEventFunction)(wxCommandEventFunction) &SW1_GUIFrame::OnTreeSelection); 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) tree -> Destroy(); } - - tree = (wxSpecificDirCtrl *) NULL; - - Panel1->GetSize(&size_h, &size_v ); - tree = new wxSpecificDirCtrl (Panel1, -1, RootFolder, wxDefaultPosition, - wxSize(-1,-1), + wxSize(size_h,size_v), wxSIMPLE_BORDER, "*.cable_spec;*.bundle_spec;*.spice_model_spec", 0, _T("Directory Listing")); @@ -653,11 +671,7 @@ void SW1_GUIFrame::OnEXPORTSPICE(wxCommandEvent& event) void SW1_GUIFrame::OnPanel1Paint(wxPaintEvent& event) { - if (tree != NULL){ - int size_h, size_v; - Panel1->GetSize(&size_h, &size_v ); - tree->SetSize(size_h,size_v); - } + } void SW1_GUIFrame::OnPanel2Paint(wxPaintEvent& event) diff --git a/GUI/SW1/SRC/SW1_GUIMain.h b/GUI/SW1/SRC/SW1_GUIMain.h index 7309a93..5d0f81e 100644 --- a/GUI/SW1/SRC/SW1_GUIMain.h +++ b/GUI/SW1/SRC/SW1_GUIMain.h @@ -102,7 +102,7 @@ class SW1_GUIFrame: public wxFrame void OnTreeSelection ( wxTreeEvent& evt ); void CreateCable (wxString, wxString, bool); - wxSpecificDirCtrl *tree; + wxSpecificDirCtrl *tree = NULL; //NULL used to remain consistent with wxWidgets use of the standard NULL macro wxString PathToMOD; wxString SelectedFile; -- libgit2 0.21.2