On Linux it is impossible to see long messages in the build log because the scrollbar doesn't extend far enough
// create warnings/errors log
wxArrayString titles;
wxArrayInt widths;
titles.Add(_("File"));
titles.Add(_("Line"));
titles.Add(_("Message"));
widths.Add(128);
widths.Add(48);
widths.Add(640);
m_pListLog = new CompilerMessages(titles, widths);
m_pListLog->SetCompilerErrors(&m_Errors);
m_ListPageIndex = msgMan->SetLog(m_pListLog);
msgMan->Slot(m_ListPageIndex).title = _("Build messages");
class CompilerMessages : public ListCtrlLogger, public wxEvtHandler
{
public:
CompilerMessages(const wxArrayString& titles, const wxArrayInt& widths);
virtual ~CompilerMessages();
virtual void SetCompilerErrors(CompilerErrors* errors){ m_pErrors = errors; }
virtual void FocusError(int nr);
virtual wxWindow* CreateControl(wxWindow* parent);
private:
void OnClick(wxCommandEvent& event);
void OnDoubleClick(wxCommandEvent& event);
CompilerErrors* m_pErrors;
DECLARE_EVENT_TABLE()
};
wxListCtrl::SetColumnWidth
bool SetColumnWidth(int col, int width)
Sets the column width.
width can be a width in pixels or wxLIST_AUTOSIZE (-1) or wxLIST_AUTOSIZE_USEHEADER (-2). wxLIST_AUTOSIZE will resize the column to the length of its longest item. wxLIST_AUTOSIZE_USEHEADER will resize the column to the length of the header (Win32) or 80 pixels (other platforms).
In small or normal icon view, col must be -1, and the column width is set for all columns.
void CompilerGCC::LogWarningOrError(CompilerLineType lt, cbProject* prj, const wxString& filename, const wxString& line, const wxString& msg)
{
// add build message
wxArrayString errors;
errors.Add(filename);
errors.Add(line);
errors.Add(msg);
Logger::level lv = Logger::info;
if (lt == cltError)
lv = Logger::error;
else if (lt == cltWarning)
lv = Logger::warning;
m_pListLog->Append(errors, lv);
// m_pListLog->GetListControl()->SetColumnWidth(2, wxLIST_AUTOSIZE);
// add to error keeping struct
m_Errors.AddError(lt, prj, filename, line.IsEmpty() ? 0 : atoi(wxSafeConvertWX2MB(line)), msg);
}
wxLIST_AUTOSIZE should be used. :D
wxLIST_AUTOSIZE should be used. :D
Thanks, I've added that suggestion to the bug report I created :D
When/if I have time, I'll try and fix some of these.
# EVT_HEADER_SEPARATOR_DCLICK(id, func):
Separator to the right of the specified column was double clicked (this action is commonly used to resize the column to fit its contents width and the control provides UpdateColumnWidthToFit() method to make implementing this easier).
It's interesting that it's been commented out. Does anyone know why?My explanation is that if every GCC Error or Warning would cause this function calling , it will slow down it's performance.
Delete key does not work in the project tree and in the watch window (I should fix them, but the laziness wins every time I think of doing it :( )
OK, I ran the example, and double clicking the separator does nothing. The log output just says:
09:55:15: OnColBeginDrag: column 1 (width = 0 or 37).
09:55:15: OnColDragging: column 1 (width = 0 or 37).
09:55:15: OnColEndDrag: column 1 (width = 0 or 37).
So I guess it's a wxWidgets thing. I think that after compilation completes (and anywhere else that outputs to the log in a batch), setColumnWidth(2, wxLIST_AUTOSIZE) should be called once to resize everything.
void CompilerGCC::OnJobEnd(size_t procIndex, int exitCode)
{
// Manager::Get()->GetMessageManager()->Log(m_PageIndex, _T("JobDone: index=%u, exitCode=%d"), procIndex, exitCode));
m_timerIdleWakeUp.Stop();
m_Pid[procIndex] = 0;
m_Processes[procIndex] = 0;
m_LastExitCode = exitCode;
if (exitCode == 0 && !m_ProcessOutputFiles[procIndex].IsEmpty())
{
#if wxCHECK_VERSION(2, 9, 0)
wxFFile f(m_ProcessOutputFiles[procIndex].wx_str(), _T("r"));
#else
wxFFile f(m_ProcessOutputFiles[procIndex].c_str(), _T("r"));
#endif
if (f.IsOpened())
{
size_t size = f.Length();
f.Close();
float displaySize;
wxString units;
if (size < 1024)
{
displaySize = (float)size;
units = _("bytes");
}
else if (size < 1048576)
{
displaySize = (float)size / 1024.0f;
units = _("KB");
}
else
{
displaySize = (float)size / 1048576.0f;
units = _("MB");
}
wxString msg;
#if wxCHECK_VERSION(2, 9, 0)
msg.Printf(_("Output size is %.2f %s"), displaySize, units.wx_str());
#else
msg.Printf(_("Output size is %.2f %s"), displaySize, units.c_str());
#endif
LogMessage(msg, cltNormal);
}
}
if (m_CommandQueue.GetCount() != 0 && exitCode == 0)
{
// continue running commands while last exit code was 0.
DoRunQueue();
}
else
{
if (exitCode == 0)
{
if (IsProcessRunning())
{
DoRunQueue();
return;
}
while (1)
{
BuildStateManagement();
if (m_CommandQueue.GetCount())
{
DoRunQueue();
return;
}
if (m_BuildState == bsNone && m_NextBuildState == bsNone)
break;
}
}
m_CommandQueue.Clear();
ResetBuildState();
// clear any remaining jobs (e.g. in case of build errors)
while (!m_BuildJobTargetsList.empty())
m_BuildJobTargetsList.pop();
// long int elapsed = wxGetElapsedTime() / 1000;
wxLongLong localTime = wxGetLocalTimeMillis();
wxLongLong duration = localTime - m_StartTimer;
long int elapsed = duration.ToLong();
elapsed /= 1000;
int mins = elapsed / 60;
int secs = (elapsed % 60);
wxString msg = wxString::Format(_("Process terminated with status %d (%d minutes, %d seconds)"), exitCode, mins, secs);
LogMessage(msg, exitCode == 0 ? cltWarning : cltError, ltAll, exitCode != 0);
if (!m_CommandQueue.LastCommandWasRun())
{
wxString msg = wxString::Format(_("%d errors, %d warnings"), m_Errors.GetCount(cltError), m_Errors.GetCount(cltWarning));
LogMessage(msg, exitCode == 0 ? cltWarning : cltError, ltAll, exitCode != 0);
#if wxCHECK_VERSION(2, 9, 0)
LogWarningOrError(cltNormal, 0, wxEmptyString, wxEmptyString, wxString::Format(_("=== Build finished: %s ==="), msg.wx_str()));
#else
LogWarningOrError(cltNormal, 0, wxEmptyString, wxEmptyString, wxString::Format(_("=== Build finished: %s ==="), msg.c_str()));
#endif
SaveBuildLog();
}
else
{
// last command was "Run"
// force exit code to zero (0) or else debugger will think build failed if last run returned non-zero...
// TODO (mandrav##): Maybe create and use GetLastRunExitCode()? Is it needed?
m_LastExitCode = 0;
}
Manager::Get()->GetLogManager()->Log(_T(" "), m_PageIndex); // blank line
NotifyJobDone();
if (!Manager::IsBatchBuild() && m_Errors.GetCount(cltError))
{
if (Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/auto_show_build_errors"), true))
{
CodeBlocksLogEvent evtShow(cbEVT_SHOW_LOG_MANAGER);
Manager::Get()->ProcessEvent(evtShow);
}
CodeBlocksLogEvent evtSwitch(cbEVT_SWITCH_TO_LOG_WINDOW, m_pListLog);
Manager::Get()->ProcessEvent(evtSwitch);
m_pListLog->FocusError(m_Errors.GetFirstError());
// Build is not completed, so clear the progress bar
if (m_Log->progress)
m_Log->progress->SetValue(0);
}
else
{
if (m_RunAfterCompile)
{
m_RunAfterCompile = false;
if (Run() == 0)
DoRunQueue();
}
else if (!Manager::IsBatchBuild())
{
// don't close the message manager (if auto-hiding), if warnings are required to keep it open
if (m_Errors.GetCount(cltWarning) &&
Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/auto_show_build_warnings"), true))
{
CodeBlocksLogEvent evtShow(cbEVT_SHOW_LOG_MANAGER);
Manager::Get()->ProcessEvent(evtShow);
CodeBlocksLogEvent evtSwitch(cbEVT_SWITCH_TO_LOG_WINDOW, m_pListLog);
Manager::Get()->ProcessEvent(evtSwitch);
}
else // if message manager is auto-hiding, unlock it (i.e. close it)
{
CodeBlocksLogEvent evtShow(cbEVT_HIDE_LOG_MANAGER);
Manager::Get()->ProcessEvent(evtShow);
}
}
}
m_RunAfterCompile = false;
// no matter what happened with the build, return the focus to the active editor
cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinEditor(Manager::Get()->GetEditorManager()->GetActiveEditor());
if (ed)
ed->GetControl()->SetFocus();
}
}
wxString Quoted = message;
Quoted.Replace(_T("‘"), _T("\""), true);
Quoted.Replace(_T("’"), _T("\""), true);
m_BuildLogContents << Quoted;
Yes, the generic wxListCtrl version simply doesn't implement this (see
wxListHeaderWindow::OnMouse()). It shouldn't be difficult to add but
personally I'd prefer to replace wxListHeaderWindow with wxHeaderCtrl if we
modify this code at all as it has other advantages.
Regards,
VZ
Index: compilergcc.cpp
===================================================================
--- compilergcc.cpp (revision 5679)
+++ compilergcc.cpp (working copy)
@@ -3715,6 +3715,7 @@
#else
LogWarningOrError(cltNormal, 0, wxEmptyString, wxEmptyString, wxString::Format(_("=== Build finished: %s ==="), msg.c_str()));
#endif
+ m_pListLog->GetListControl()->SetColumnWidth(2, wxLIST_AUTOSIZE);
SaveBuildLog();
}
else
Index: compilermessages.h
===================================================================
--- compilermessages.h (revision 5679)
+++ compilermessages.h (working copy)
@@ -21,6 +21,7 @@
virtual void FocusError(int nr);
virtual wxWindow* CreateControl(wxWindow* parent);
+ wxListCtrl* GetListControl(){ return control ; }
private:
void OnClick(wxCommandEvent& event);
void OnDoubleClick(wxCommandEvent& event);
That link is borken!...What do you really want to express?
That link is borken!...What do you really want to express?
one has to read the displayed warning thouggh, and click on "I understand the risk".If this is paranoid or even MS-like, I won't state any opinion on that ... ;)That's only half of the story, though. You need to click on "I understand the risk" then on another button, then a window pops up which has "install permanently" selected by default and a built-in 2 second delay before the UI can be accessed. Seriously, if the browser tells you "Warning! Great danger ahead, do not proceed, don't trust that site!" then why in the name of all that is holy would you want to permanently install that certificate? This is just a flipping stupid preset.