From 0fbcb061f8068403c22f1ef3a3b2d1389de7674b Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Wed, 30 Jan 2013 19:10:21 +0000 Subject: [PATCH] try #2 to implement what we discussed with Francois and Ruth w.r.t. to error notifications: - never open the message console automatically, it's just to annoying and very slow when there are many errors - indicate that there's been an error in the status bar - make it easy to show/hide the messages by a single clic on the status bar - report the first (not the last) error in the status bar if the messages are not shown Feedback is welcome... (We can always revert to the old way if necessary ;-) --- Common/GmshMessage.cpp | 46 +++++++++++++++++------------------------- Common/GmshMessage.h | 5 +++-- Common/OpenFile.cpp | 3 +++ Common/Options.cpp | 4 +--- Fltk/FlGui.cpp | 20 ++++++++++++------ Fltk/FlGui.h | 9 +++++---- Fltk/graphicWindow.cpp | 26 +++++++++++++++++++----- Fltk/onelabGroup.cpp | 14 ++++++------- Fltk/optionWindow.cpp | 4 ++-- 9 files changed, 73 insertions(+), 58 deletions(-) diff --git a/Common/GmshMessage.cpp b/Common/GmshMessage.cpp index 4ef053ac4e..10376dcfac 100644 --- a/Common/GmshMessage.cpp +++ b/Common/GmshMessage.cpp @@ -49,6 +49,7 @@ int Msg::_progressMeterCurrent = 0; std::map<std::string, double> Msg::_timers; int Msg::_warningCount = 0; int Msg::_errorCount = 0; +std::string Msg::_firstError; GmshMessage *Msg::_callback = 0; std::string Msg::_commandLine; std::string Msg::_launchDate; @@ -222,7 +223,8 @@ void Msg::Fatal(const char *fmt, ...) FlGui::instance()->check(); std::string tmp = std::string("@C1@.") + "Fatal : " + str; FlGui::instance()->addMessage(tmp.c_str()); - FlGui::instance()->showMessages(); + if(_firstError.empty()) _firstError = str; + FlGui::instance()->setLastStatus(FL_DARK_RED); FlGui::instance()->saveMessages ((CTX::instance()->homeDir + CTX::instance()->errorFileName).c_str()); fl_alert("A fatal error has occurred which will force Gmsh to abort.\n" @@ -267,7 +269,8 @@ void Msg::Error(const char *fmt, ...) FlGui::instance()->check(); std::string tmp = std::string("@C1@.") + "Error : " + str; FlGui::instance()->addMessage(tmp.c_str()); - FlGui::instance()->showMessages(); + if(_firstError.empty()) _firstError = str; + FlGui::instance()->setLastStatus(FL_DARK_RED); } #endif @@ -357,19 +360,6 @@ void Msg::Direct(const char *fmt, ...) vsnprintf(str, sizeof(str), fmt, args); va_end(args); - Direct(3, str); -} - -void Msg::Direct(int level, const char *fmt, ...) -{ - if(_commRank || _verbosity < level) return; - - char str[5000]; - va_list args; - va_start(args, fmt); - vsnprintf(str, sizeof(str), fmt, args); - va_end(args); - if(_callback) (*_callback)("Direct", str); if(_client) _client->Info(str); @@ -378,16 +368,8 @@ void Msg::Direct(int level, const char *fmt, ...) { if(FlGui::available()){ FlGui::instance()->check(); - std::string tmp; - if(level < 2) - tmp = std::string("@C1@.") + str; - else if(level < 3) - tmp = std::string("@C5@.") + str; - else - tmp = std::string("@C4@.") + str; + std::string tmp = std::string("@C4@.") + str; FlGui::instance()->addMessage(tmp.c_str()); - if(level == 1) - FlGui::instance()->showMessages(); } } #endif @@ -536,6 +518,17 @@ void Msg::PrintTimers() } } +void Msg::ResetErrorCounter() +{ + _warningCount = 0; _errorCount = 0; + _firstError.clear(); +#if defined(HAVE_FLTK) + if(FlGui::available()){ + FlGui::instance()->setLastStatus(); + } +#endif +} + void Msg::PrintErrorCounter(const char *title) { if(_commRank || _verbosity < 1) return; @@ -557,10 +550,7 @@ void Msg::PrintErrorCounter(const char *title) FlGui::instance()->addMessage((red + prefix + err).c_str()); FlGui::instance()->addMessage((red + prefix + help).c_str()); FlGui::instance()->addMessage((red + prefix + line).c_str()); - if(_errorCount){ - FlGui::instance()->showMessages(); - fl_beep(); - } + if(_errorCount) fl_beep(); } #endif diff --git a/Common/GmshMessage.h b/Common/GmshMessage.h index a5b8f7a337..b9fee7d6d8 100644 --- a/Common/GmshMessage.h +++ b/Common/GmshMessage.h @@ -36,6 +36,7 @@ class Msg { static std::map<std::string, double> _timers; // counters static int _warningCount, _errorCount; + static std::string _firstError; // callback static GmshMessage *_callback; // command-line and startup time @@ -68,7 +69,6 @@ class Msg { static void Warning(const char *fmt, ...); static void Info(const char *fmt, ...); static void Direct(const char *fmt, ...); - static void Direct(int level, const char *fmt, ...); static void StatusBar(bool log, const char *fmt, ...); static void StatusGl(const char *fmt, ...); static void Debug(const char *fmt, ...); @@ -78,8 +78,9 @@ class Msg { static void ResetProgressMeter(){ if(!_commRank) _progressMeterCurrent = 0; } static double &Timer(std::string str){ return _timers[str]; } static void PrintTimers(); - static void ResetErrorCounter(){ _warningCount = 0; _errorCount = 0; } + static void ResetErrorCounter(); static int GetErrorCount(){ return _errorCount; } + static std::string GetFirstError(){ return _firstError; } static void PrintErrorCounter(const char *title); static double GetValue(const char *text, double defaultval); static std::string GetString(const char *text, std::string defaultval); diff --git a/Common/OpenFile.cpp b/Common/OpenFile.cpp index 431ed9ff48..bbfd091acb 100644 --- a/Common/OpenFile.cpp +++ b/Common/OpenFile.cpp @@ -583,6 +583,7 @@ void ClearProject() GModel::current()->setSelection(0); } #endif + Msg::ResetErrorCounter(); } void OpenProject(const std::string &fileName) @@ -593,6 +594,8 @@ void OpenProject(const std::string &fileName) } CTX::instance()->lock = 1; + Msg::ResetErrorCounter(); + if(GModel::current()->empty()){ // if the current model is empty, make sure it's reaaally // cleaned-up, and reuse it (don't clear the parser variables: if diff --git a/Common/Options.cpp b/Common/Options.cpp index 5d2b22ecb9..5b3028919a 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -129,12 +129,10 @@ static void PrintStringOptions(int num, int level, int diff, int help, // remove \n, \t, \r for(unsigned int i = 0; i < strlen(tmp); i++) if(tmp[i] == '\n' || tmp[i] == '\t' || tmp[i] == '\r') tmp[i] = ' '; - // Warning: must call Msg::Direct(level, ...) here, because - // we cannot use tmp as a format string (it can contain %s!) if(vec) vec->push_back(std::string(tmp) + '\0' + "string"); else - Msg::Direct(3, "%s", tmp); + Msg::Direct("%s", tmp); } } } diff --git a/Fltk/FlGui.cpp b/Fltk/FlGui.cpp index b369ea6a8d..e01f8c4764 100644 --- a/Fltk/FlGui.cpp +++ b/Fltk/FlGui.cpp @@ -793,8 +793,11 @@ char FlGui::selectEntity(int type) void FlGui::setStatus(const std::string &msg, bool opengl) { if(!opengl){ + _lastStatus = msg; static char buff[1024]; std::string tmp = std::string(" ") + msg; + if(Msg::GetFirstError().size() && graph[0]->getMessageHeight() < FL_NORMAL_SIZE) + tmp += " - Click to show messages [ ... " + Msg::GetFirstError() + " ... ]"; strncpy(buff, tmp.c_str(), sizeof(buff) - 1); buff[sizeof(buff) - 1] = '\0'; for(unsigned int i = 0; i < graph.size(); i++){ @@ -818,6 +821,17 @@ void FlGui::setStatus(const std::string &msg, bool opengl) } } +void FlGui::setLastStatus(int col) +{ + for(unsigned int i = 0; i < graph.size(); i++){ + if(col >= 0) + graph[i]->getProgress()->labelcolor(col); + else + graph[i]->getProgress()->labelcolor(FL_FOREGROUND_COLOR); + } + setStatus(_lastStatus); +} + void FlGui::setProgress(const std::string &msg, double val, double min, double max) { for(unsigned int i = 0; i < FlGui::instance()->graph.size(); i++){ @@ -982,12 +996,6 @@ void FlGui::addMessage(const char *msg) FlGui::instance()->graph[i]->addMessage(msg); } -void FlGui::showMessages() -{ - for(unsigned int i = 0; i < FlGui::instance()->graph.size(); i++) - FlGui::instance()->graph[i]->showMessages(); -} - void FlGui::saveMessages(const char *fileName) { FlGui::instance()->graph[0]->saveMessages(fileName); diff --git a/Fltk/FlGui.h b/Fltk/FlGui.h index 20d3bd2aa7..b397dbdd85 100644 --- a/Fltk/FlGui.h +++ b/Fltk/FlGui.h @@ -44,6 +44,7 @@ class FlGui{ private: static FlGui *_instance; static std::string _openedThroughMacFinder; + std::string _lastStatus; public: std::vector<GVertex*> selectedVertices; std::vector<GEdge*> selectedEdges; @@ -109,17 +110,17 @@ class FlGui{ char selectEntity(int type); // display status message void setStatus(const std::string &msg, bool opengl=false); + // redisplay last status message + void setLastStatus(int col=-1); // display status message and update progress bar void setProgress(const std::string &msg, double val, double min, double max); // set color of progress message void setProgressColor(int col); // create the window for physical context dependant definitions void callForSolverPlugin(int dim); - // add line in message console(s) + // add line in message console void addMessage(const char *msg); - // show the message console - void showMessages(); - // add line in message console(s) + // save messages to file void saveMessages(const char *fileName); // rebuild the tree void rebuildTree(); diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp index f4ff9c4df5..750aeb4b91 100644 --- a/Fltk/graphicWindow.cpp +++ b/Fltk/graphicWindow.cpp @@ -1643,8 +1643,6 @@ static void mesh_inspect_cb(Fl_Widget *w, void *data) str += info[i] + "\n"; FlGui::instance()->getCurrentOpenglWindow()->drawTooltip(str); } - else - FlGui::instance()->showMessages(); } } if(ib == 'q') { @@ -2444,6 +2442,24 @@ class mainWindowSpecialResize : public mainWindow { } }; +class mainWindowProgress : public Fl_Progress{ +public: + mainWindowProgress(int x, int y, int w, int h, const char *l=0) : + Fl_Progress(x, y, w, h, l){} + int handle(int event) + { + if(event == FL_PUSH){ + if(FlGui::available()){ + for(unsigned int i = 0; i < FlGui::instance()->graph.size(); i++) + FlGui::instance()->graph[i]->showHideMessages(); + Msg::ResetErrorCounter(); + } + return 1; + } + return Fl_Progress::handle(event); + } +}; + graphicWindow::graphicWindow(bool main, int numTiles, bool detachedMenu) : _autoScrollMessages(true) { @@ -2585,7 +2601,7 @@ graphicWindow::graphicWindow(bool main, int numTiles, bool detachedMenu) } x += 4; - _label = new Fl_Progress(x, mh + glheight + mheight + 2, width - x, sht); + _label = new mainWindowProgress(x, mh + glheight + mheight + 2, width - x, sht); _label->box(FL_FLAT_BOX); _label->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE | FL_ALIGN_CLIP); _label->color(FL_BACKGROUND_COLOR, FL_DARK2); // FL_DARK_GREEN @@ -2998,7 +3014,7 @@ void graphicWindow::showMessages() if(!_browser || !_win->shown()) return; if(_browser->h() < FL_NORMAL_SIZE){ int height = CTX::instance()->msgSize; - if(height < FL_NORMAL_SIZE) height = 5 * FL_NORMAL_SIZE; + if(height < FL_NORMAL_SIZE) height = 10 * FL_NORMAL_SIZE; int maxh = _win->h() - _bottom->h(); if(height > maxh) height = maxh / 2; setMessageHeight(height); @@ -3031,7 +3047,7 @@ void graphicWindow::addMessage(const char *msg) { if(!_browser) return; _browser->add(msg, 0); - if(_autoScrollMessages && _win->shown() && _browser->h() >= 10) + if(_autoScrollMessages && _win->shown() && _browser->h() >= FL_NORMAL_SIZE) _browser->bottomline(_browser->size()); } diff --git a/Fltk/onelabGroup.cpp b/Fltk/onelabGroup.cpp index 7bbf0de59e..eb9e5153f5 100644 --- a/Fltk/onelabGroup.cpp +++ b/Fltk/onelabGroup.cpp @@ -291,13 +291,13 @@ bool onelab::localNetworkClient::run() Msg::StatusBar(false, "%s %s", _name.c_str(), message.c_str()); break; case GmshSocket::GMSH_INFO: - Msg::Direct("%-8.8s: %s", _name.c_str(), message.c_str()); + Msg::Direct("Info : %s - %s", _name.c_str(), message.c_str()); break; case GmshSocket::GMSH_WARNING: - Msg::Direct(2, "%-8.8s: %s", _name.c_str(), message.c_str()); + Msg::Warning("%s - %s", _name.c_str(), message.c_str()); break; case GmshSocket::GMSH_ERROR: - Msg::Direct(1, "%-8.8s: %s", _name.c_str(), message.c_str()); + Msg::Error("%s - %s", _name.c_str(), message.c_str()); break; case GmshSocket::GMSH_MERGE_FILE: if(CTX::instance()->solver.autoMergeFile){ @@ -473,7 +473,10 @@ static void loadDb(const std::string &name) void onelab_cb(Fl_Widget *w, void *data) { + Msg::ResetErrorCounter(); + if(!data) return; + std::string action((const char*)data); if(action == "refresh"){ @@ -579,7 +582,6 @@ void onelab_cb(Fl_Widget *w, void *data) OpenProject(GModel::current()->getFileName()); drawContext::global()->draw(); } - Msg::ResetErrorCounter(); #endif } else{ @@ -1363,7 +1365,6 @@ void onelabGroup::openTreeItem(const std::string &name) void onelabGroup::checkForErrors(const std::string &client) { if(Msg::GetErrorCount() > 0 && !CTX::instance()->expertMode){ - Msg::ResetErrorCounter(); std::string msg (client + " reported an error: do you really want to continue?\n\n" "(To disable this warning in the future, select `Enable expert mode'\n" @@ -1565,8 +1566,6 @@ void onelabGroup::removeSolver(const std::string &name) void solver_cb(Fl_Widget *w, void *data) { - Msg::ResetErrorCounter(); - int num = (intptr_t)data; if(num >= 0){ std::string name = opt_solver_name(num, GMSH_GET, ""); @@ -1653,7 +1652,6 @@ void flgui_wait_cb(double time) int metamodel_cb(const std::string &name, const std::string &action) { #if defined(HAVE_ONELAB_METAMODEL) - Msg::ResetErrorCounter(); if(FlGui::instance()->onelab->isBusy()) FlGui::instance()->onelab->show(); else{ diff --git a/Fltk/optionWindow.cpp b/Fltk/optionWindow.cpp index 578336e766..deb8dd037e 100644 --- a/Fltk/optionWindow.cpp +++ b/Fltk/optionWindow.cpp @@ -13,6 +13,7 @@ typedef unsigned long intptr_t; #include <FL/Fl_Tabs.H> #include <FL/Fl_Scroll.H> #include <FL/Fl_Color_Chooser.H> +#include <FL/fl_ask.H> #include "GmshDefines.h" #include "GmshMessage.h" #include "FlGui.h" @@ -176,8 +177,7 @@ static void options_show_file_cb(Fl_Widget *w, void *data) file += CTX::instance()->sessionFileName; else file += CTX::instance()->optionsFileName; - Msg::Direct("%s", file.c_str()); - FlGui::instance()->showMessages(); + fl_message("File path: %s", file.c_str()); } static void options_restore_defaults_cb(Fl_Widget *w, void *data) -- GitLab