When I read the WxWidgets documentation, I get the impression that the developers wrote it just for themselves, just to remember what they did 20 years ago.
Regardless, I figured out how to send log messages to a file:
wxLog::SetActiveTarget(new wxLogStderr(fopen(logPath "/wxApp.log", "w ")));
and also I figured out how to change the format of the log messages:
wxLog::GetActiveTarget()->SetFormatter(new MyLogger);
But I didn't understand anything else.
So I want to ask my question here.
I want to make a log for my application.
Moreover, I want:
- all log messages to be written to a file
- at the same time some of these messages are displayed on the screen using wxTextCtrl.
So I want to filter the log messages that are displayed on the screen, depending on the logging level:
for example, I want to display in wxTextCtrl only log messages with "wxLOG_Info" and "wxLOG_Error" levels.
How can this be done in Windows and Linux in C ? It's best to show a code example.
CodePudding user response:
I may be missing something but this seems very simple?
For example, this could be the simplest possible log target which logs some messages into a wxTextCtrl
and all of them into a wxFFile
.
#include <wx/wx.h>
#include <wx/ffile.h>
class MyLogTarget : public wxLog
{
public:
// textCtrl must have longer lifetime than MyLogTarget
MyLogTarget(wxTextCtrl* textCtrl, const wxString& fileName)
: m_textCtrl(textCtrl), m_file(fileName, "a")
{}
protected:
void DoLogTextAtLevel(wxLogLevel level, const wxString& msg) override
{
// preserve debug logging
if ( level == wxLOG_Debug || level == wxLOG_Trace )
wxLog::DoLogTextAtLevel(level, msg);
if ( level == wxLOG_Info || level == wxLOG_Error )
m_textCtrl->AppendText(msg "\n");
if ( m_file.IsOpened() )
m_file.Write(msg "\n");
}
private:
wxTextCtrl* m_textCtrl;
wxFFile m_file;
};
class MyFrame : public wxFrame
{
public:
MyFrame(wxWindow* parent = nullptr) : wxFrame(parent, wxID_ANY, "Test")
{
wxTextCtrl* logCtrl = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2);
wxLog::SetActiveTarget(new MyLogTarget(logCtrl, "log.txt"));
wxLogDebug("Debug test");
wxLogMessage("Message test");
wxLogInfo("Info test");
wxLogError("Error test");
}
~MyFrame()
{
delete wxLog::SetActiveTarget(nullptr);
}
};
class MyApp : public wxApp
{
public:
bool OnInit() override
{
(new MyFrame())->Show();
return true;
}
}; wxIMPLEMENT_APP(MyApp);
Please notice that this would have to be extended to be usable in a real application, for example, handle the file encoding / flushing / cleaning / error handling (without getting into the endless logging loop), use the full path for the file (e.g., obtained with wxStandardPaths
), use a log chain to preserve (some of?) the default wxWidgets logging...
If you want to use separate log targets for logging into a text control and a file, it is still very simple except that you have to chain the log targets, as explained in the docs.