diff --git a/Common/Gmsh.cpp b/Common/Gmsh.cpp index fb8a33bd4ba171085252452f194bd06235c59537..c88d471b281c6b1803098c97841377f0af5414ce 100644 --- a/Common/Gmsh.cpp +++ b/Common/Gmsh.cpp @@ -285,7 +285,7 @@ int GmshFLTK(int argc, char **argv) if(CTX::instance()->post.combineTime){ PView::combine(true, 2, CTX::instance()->post.combineRemoveOrig); - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); } // init first context diff --git a/Common/OS.cpp b/Common/OS.cpp index 027d62e54144d95d04b4eda36b1ac7e660c79e2c..480bbafe9f8ba581ef504afecaf8a30da8ea2e25 100644 --- a/Common/OS.cpp +++ b/Common/OS.cpp @@ -219,12 +219,19 @@ int SystemCall(const std::string &command, bool blocking) // get executable extension std::vector<std::string> split = SplitFileName(exe); + // do we try to run a python script? + bool script = (split[2] == ".py" || split[2] == ".PY"); + if(script && StatFile(exe)){ + Msg::Error("Unable to open file '%s'", exe.c_str()); + return 1; + } + #if defined(WIN32) - if(split[2] == ".py" || split[2] == ".PY"){ - Msg::Info("Shell opening '%s' with arguments '%s'", - exe.c_str(), args.c_str()); + if(script){ + Msg::Info("Shell opening '%s' with arguments '%s'", exe.c_str(), + args.c_str()); ShellExecute(NULL, (char*)"open", (char*)exe.c_str(), - (char*)args.c_str(), NULL, 0); + (char*)args.c_str(), NULL, 0); } else{ STARTUPINFO suInfo; @@ -250,10 +257,9 @@ int SystemCall(const std::string &command, bool blocking) &suInfo, &prInfo); } } - return 0; #else std::string cmd(command); - if(split[2] == ".py" || split[2] == ".PY"){ + if(script){ if(access(exe.c_str(), X_OK)){ Msg::Info("Script '%s' is not executable: running with python", exe.c_str()); cmd = "python " + cmd; @@ -270,8 +276,8 @@ int SystemCall(const std::string &command, bool blocking) if(!blocking) cmd += " &"; Msg::Info("Calling '%s'", cmd.c_str()); if(!system(cmd.c_str())) return 1; - return 0; #endif + return 0; } std::string GetCurrentWorkdir() diff --git a/Common/OpenFile.cpp b/Common/OpenFile.cpp index 4a85449b44906429864fbb36a28ebebf8c79911f..e57a71fc1f8ccde4d17bcb8eb1c0ac97d60215ef 100644 --- a/Common/OpenFile.cpp +++ b/Common/OpenFile.cpp @@ -233,7 +233,7 @@ int ParseFile(const std::string &fileName, bool close, bool warnIfMissing) #if defined(HAVE_FLTK) && defined(HAVE_POST) if(FlGui::available()) - FlGui::instance()->updateViews(numViewsBefore != (int)PView::list.size()); + FlGui::instance()->updateViews(numViewsBefore != (int)PView::list.size(), false); #endif return 1; @@ -482,7 +482,7 @@ int MergeFile(const std::string &fileName, bool warnIfMissing) for(unsigned int i = numViewsBefore; i < PView::list.size(); i++) opt_view_timestep(i, GMSH_SET | GMSH_GUI, PView::list[i]->getData()->getFirstNonEmptyTimeStep()); - FlGui::instance()->updateViews(numViewsBefore != (int)PView::list.size()); + FlGui::instance()->updateViews(numViewsBefore != (int)PView::list.size(), false); } #endif @@ -605,7 +605,7 @@ void ClearProject() if(FlGui::available()){ FlGui::instance()->setGraphicTitle(GModel::current()->getFileName()); FlGui::instance()->resetVisibility(); - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); FlGui::instance()->updateFields(); GModel::current()->setSelection(0); } @@ -675,7 +675,7 @@ void OpenProject(const std::string &fileName) if(FlGui::available()){ file_watch_cb(0, 0); FlGui::instance()->resetVisibility(); - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, false); FlGui::instance()->updateFields(); GModel::current()->setSelection(0); GModel::current()->setCompoundVisibility(); diff --git a/Fltk/FlGui.cpp b/Fltk/FlGui.cpp index 10c4850dd9172ca108bf2579d0bd6cc92ce86a60..82aae7c944ac2a88cbb46b89fd8a229afc7d0d1c 100644 --- a/Fltk/FlGui.cpp +++ b/Fltk/FlGui.cpp @@ -338,9 +338,9 @@ FlGui::FlGui(int argc, char **argv) fullscreen->mode(mode); fullscreen->end(); fullscreen->fullscreen(); - #if not defined (__APPLE__) +#if not defined (__APPLE__) fullscreen->icon(graph[0]->getWindow()->icon()); - #endif +#endif // create all other windows options = new optionWindow(CTX::instance()->deltaFontSize); @@ -778,12 +778,12 @@ void FlGui::setGraphicTitle(std::string title) } } -void FlGui::updateViews(bool numberOfViewsHasChanged) +void FlGui::updateViews(bool numberOfViewsHasChanged, bool deleteWidgets) { for(unsigned int i = 0; i < graph.size(); i++) graph[i]->checkAnimButtons(); if(numberOfViewsHasChanged){ - onelab->rebuildTree(true); + onelab->rebuildTree(deleteWidgets); options->resetBrowser(); options->resetExternalViewList(); fields->loadFieldViewList(); diff --git a/Fltk/FlGui.h b/Fltk/FlGui.h index d12f165068d8a837b66322bb3aaf78ba25421bc5..eadfc31cbb4f5dd3d04ec82982a36c28e1607157 100644 --- a/Fltk/FlGui.h +++ b/Fltk/FlGui.h @@ -95,8 +95,8 @@ class FlGui{ int testArrowShortcuts(); // set the title of the graphic windows void setGraphicTitle(std::string title); - // update the GUI when views get added or deleted - void updateViews(bool numberOfViewsHasChanged=true); + // update the GUI when views get modified, added or deleted + void updateViews(bool numberOfViewsHasChanged, bool deleteWidgets); // update the GUI when fields change void updateFields(); // reset the visibility window diff --git a/Fltk/fieldWindow.cpp b/Fltk/fieldWindow.cpp index aa41cb17b8aa71406d1c7de4ff04a65ddef1c390..2e36971fc5f8f2116ba86917b2bf18bd438843a5 100644 --- a/Fltk/fieldWindow.cpp +++ b/Fltk/fieldWindow.cpp @@ -76,7 +76,7 @@ static void field_put_on_view_cb(Fl_Widget *w, void *data) field->putOnNewView(); else if(mb->value() - 1 < (int)PView::list.size()) field->putOnView(PView::list[mb->value() - 1]); - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(mb->value() == 0, true); drawContext::global()->draw(); } @@ -102,7 +102,7 @@ fieldWindow::fieldWindow(int deltaFontSize) : _deltaFontSize(deltaFontSize) int width0 = 34 * FL_NORMAL_SIZE + WB; int height0 = 12 * BH + 4 * WB; - int width = (CTX::instance()->fieldSize[0] < width0) ? width0 : + int width = (CTX::instance()->fieldSize[0] < width0) ? width0 : CTX::instance()->fieldSize[0]; int height = (CTX::instance()->fieldSize[1] < height0) ? height0 : CTX::instance()->fieldSize[1]; @@ -125,7 +125,7 @@ fieldWindow::fieldWindow(int deltaFontSize) : _deltaFontSize(deltaFontSize) browser = new Fl_Hold_Browser(x, y + WB, w, h - 2 * WB); browser->callback(field_browser_cb); - y += h; + y += h; delete_btn = new Fl_Button(x, y, w, BH, "Delete"); delete_btn->callback(field_delete_cb, this); @@ -146,7 +146,7 @@ fieldWindow::fieldWindow(int deltaFontSize) : _deltaFontSize(deltaFontSize) title = new Fl_Box(x, y, w, BH, "field_name"); title->labelfont(FL_BOLD); title->labelsize(FL_NORMAL_SIZE + 3); - + y += BH + WB; h -= BH + WB; Fl_Tabs *tabs = new Fl_Tabs(x, y , w, h); @@ -156,14 +156,14 @@ fieldWindow::fieldWindow(int deltaFontSize) : _deltaFontSize(deltaFontSize) w -= 2 * WB; Fl_Group *options_tab = new Fl_Group(x, y, w, h, "Options"); - + options_scroll = new Fl_Scroll(x, y + WB, w, h - BH - 3 * WB); options_scroll->end(); - + Fl_Button *apply_btn = new Fl_Return_Button (x + w - BB, y + h - BH - WB, BB, BH, "Apply"); apply_btn->callback(field_apply_cb, this); - + background_btn = new Fl_Round_Button (x, y + h - BH - WB, w - BB - WB, BH, "Set as background field"); background_btn->tooltip("Only a single field can be set as background field.\n" @@ -180,13 +180,13 @@ fieldWindow::fieldWindow(int deltaFontSize) : _deltaFontSize(deltaFontSize) editor_group->end(); - win->resizable(new Fl_Box((int)(1.5 * BB) + 2 * WB, BH + 2 * WB, + win->resizable(new Fl_Box((int)(1.5 * BB) + 2 * WB, BH + 2 * WB, width - 3 * WB - (int)(1.5 * BB), height - 3 * BH - 5 * WB)); editor_group->resizable(tabs); tabs->resizable(options_tab); options_tab->resizable(new Fl_Box(3 * BB + 4 * WB, BH + 2 * WB, - width - 9 * WB - 5 * BB, + width - 9 * WB - 5 * BB, height - 3 * BH - 5 * WB)); win->size_range(width0, height0); win->position(CTX::instance()->fieldPosition[0], CTX::instance()->fieldPosition[1]); @@ -359,7 +359,7 @@ void fieldWindow::editField(Field *f) ConvertToHTML(help); if (! f->options.empty()) help += std::string("<p><center><b>Options</b></center>"); - for(std::map<std::string, FieldOption*>::iterator it = f->options.begin(); + for(std::map<std::string, FieldOption*>::iterator it = f->options.begin(); it != f->options.end(); it++){ Fl_Widget *input; help += std::string("<p><b>") + it->first + "</b>"; @@ -399,7 +399,7 @@ void fieldWindow::editField(Field *f) } if (! f->callbacks.empty()) help += std::string("<p><center><b>Actions</b></center>"); - for(std::map<std::string, FieldCallback*>::iterator it = f->callbacks.begin(); + for(std::map<std::string, FieldCallback*>::iterator it = f->callbacks.begin(); it != f->callbacks.end(); it++){ Fl_Widget *btn; help += std::string("<p><b>") + it->first + "</b>: "; diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp index 6e4a20d2745ccfbf635ab13609b82ad2cd13f399..c551c6bc69c2949f2425489d37927b23bf742128 100644 --- a/Fltk/graphicWindow.cpp +++ b/Fltk/graphicWindow.cpp @@ -214,7 +214,7 @@ static void file_remote_cb(Fl_Widget *w, void *data) server->SendString(GmshSocket::GMSH_PARSE_STRING, "Delete All;"); for(int i = PView::list.size() - 1; i >= 0; i--) if(PView::list[i]->getData()->isRemote()) delete PView::list[i]; - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); drawContext::global()->draw(); } else if(str == "test"){ diff --git a/Fltk/onelabGroup.cpp b/Fltk/onelabGroup.cpp index 0c4b480830e75ee196a667a95c393956308b9e0d..1488ab0405a1ba0303a1167bb85afb7e091eb547 100644 --- a/Fltk/onelabGroup.cpp +++ b/Fltk/onelabGroup.cpp @@ -356,7 +356,7 @@ bool gmshLocalNetworkClient::receiveMessage(gmshLocalNetworkClient *master) int n = PView::list.size(); PView::fillVertexArray(this, length, &message[0], swap); if(FlGui::available()) - FlGui::instance()->updateViews(n != (int)PView::list.size()); + FlGui::instance()->updateViews(n != (int)PView::list.size(), true); drawContext::global()->draw(); } break; @@ -570,7 +570,7 @@ static void updateGraphs() redraw = redraw || ret; } if(redraw){ - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); drawContext::global()->draw(); } } @@ -1566,16 +1566,15 @@ void onelabGroup::rebuildTree(bool deleteWidgets) _tree->sortorder(FL_TREE_SORT_ASCENDING); _tree->selectmode(FL_TREE_SELECT_NONE); + // we don't delete widgets everytime the tree is rebuilt to minimize potential + // race conditions (e.g. during heavy user interaction with autoCheck, with + // risks to call handle() or focus() on deleted widgets) + std::vector<Fl_Widget*> delWidgets; + std::vector<char*> delStrings; if(deleteWidgets){ - // we don't delete all the widgets everytime the tree is rebuilt to minimize - // potential race conditions (e.g. during heavy user interaction with - // autoCheck, with risks to call handle() or focus() on deleted widgets) - Msg::Debug("Deleting onelabGroup widgets (%d)", (int)_treeWidgets.size()); - for(unsigned int i = 0; i < _treeWidgets.size(); i++) - Fl::delete_widget(_treeWidgets[i]); + delWidgets = _treeWidgets; + delStrings = _treeStrings; _treeWidgets.clear(); - for(unsigned int i = 0; i < _treeStrings.size(); i++) - free(_treeStrings[i]); _treeStrings.clear(); } @@ -1642,6 +1641,15 @@ void onelabGroup::rebuildTree(bool deleteWidgets) FL_NORMAL_SIZE += CTX::instance()->deltaFontSize; FlGui::check(); // necessary e.g. on windows to avoid "ghosting" + + if(deleteWidgets){ + // this needs to be performed after FlGui::check() + Msg::Debug("Deleting onelabGroup widgets (%d)", (int)_treeWidgets.size()); + for(unsigned int i = 0; i < delWidgets.size(); i++) + Fl::delete_widget(delWidgets[i]); + for(unsigned int i = 0; i < delStrings.size(); i++) + free(delStrings[i]); + } } void onelabGroup::openTreeItem(const std::string &name) diff --git a/Fltk/pluginWindow.cpp b/Fltk/pluginWindow.cpp index 83c2b0d9733bb0f73ad23f620ac2bd820d593d1f..63a213e03f9334dcb9c5765453b46e8d38601a69 100644 --- a/Fltk/pluginWindow.cpp +++ b/Fltk/pluginWindow.cpp @@ -206,7 +206,7 @@ static void plugin_run_cb(Fl_Widget *w, void *data) p->run(); } - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); GMSH_Plugin::draw = 0; drawContext::global()->draw(); } diff --git a/Fltk/statisticsWindow.cpp b/Fltk/statisticsWindow.cpp index f7e5fc511f992e4976c075ef0739519e7b371149..a2dda55db7db6aeef6006c5a89d1bfe9f3128ed9 100644 --- a/Fltk/statisticsWindow.cpp +++ b/Fltk/statisticsWindow.cpp @@ -84,7 +84,7 @@ static void statistics_histogram_cb(Fl_Widget *w, void *data) new PView(name, "ElementData", GModel::current(), d); } - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); drawContext::global()->draw(); } diff --git a/Fltk/viewButton.cpp b/Fltk/viewButton.cpp index 2bf10258563df8f63acdb2e0d881bd656915b7f6..ae4fcd90756f059f913f71a07d88429e27ac6035 100644 --- a/Fltk/viewButton.cpp +++ b/Fltk/viewButton.cpp @@ -57,7 +57,7 @@ static void view_reload(int index) if(p->getOptions()->timeStep > p->getData()->getNumTimeSteps() - 1) p->getOptions()->timeStep = 0; p->setChanged(true); - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); } } } @@ -88,7 +88,7 @@ static void view_remove_other_cb(Fl_Widget *w, void *data) if(PView::list.empty()) return; for(int i = PView::list.size() - 1; i >= 0; i--) if(i != (intptr_t)data) delete PView::list[i]; - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); drawContext::global()->draw(); } @@ -118,14 +118,14 @@ static void view_remove_all_cb(Fl_Widget *w, void *data) if(PView::list[i]->getData()->getName() == name) delete PView::list[i]; } - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); drawContext::global()->draw(); } static void view_remove_cb(Fl_Widget *w, void *data) { delete PView::list[(intptr_t)data]; - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); drawContext::global()->draw(); } @@ -179,56 +179,56 @@ static void view_save_cb(Fl_Widget *w, void *data) static void view_alias_cb(Fl_Widget *w, void *data) { new PView(PView::list[(intptr_t)data], false); - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); drawContext::global()->draw(); } static void view_alias_with_options_cb(Fl_Widget *w, void *data) { new PView(PView::list[(intptr_t)data], true); - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); drawContext::global()->draw(); } static void view_combine_space_all_cb(Fl_Widget *w, void *data) { PView::combine(false, 1, CTX::instance()->post.combineRemoveOrig); - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); drawContext::global()->draw(); } static void view_combine_space_visible_cb(Fl_Widget *w, void *data) { PView::combine(false, 0, CTX::instance()->post.combineRemoveOrig); - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); drawContext::global()->draw(); } static void view_combine_space_by_name_cb(Fl_Widget *w, void *data) { PView::combine(false, 2, CTX::instance()->post.combineRemoveOrig); - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); drawContext::global()->draw(); } static void view_combine_time_all_cb(Fl_Widget *w, void *data) { PView::combine(true, 1, CTX::instance()->post.combineRemoveOrig); - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); drawContext::global()->draw(); } static void view_combine_time_visible_cb(Fl_Widget *w, void *data) { PView::combine(true, 0, CTX::instance()->post.combineRemoveOrig); - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); drawContext::global()->draw(); } static void view_combine_time_by_name_cb(Fl_Widget *w, void *data) { PView::combine(true, 2, CTX::instance()->post.combineRemoveOrig); - FlGui::instance()->updateViews(); + FlGui::instance()->updateViews(true, true); drawContext::global()->draw(); } diff --git a/Geo/Chain.cpp b/Geo/Chain.cpp index 142315c9bdba782ffda9c1025ca88f5cafc15c85..3c7b04b3f6f74f972b6077de4758a7f2c26cef2d 100644 --- a/Geo/Chain.cpp +++ b/Geo/Chain.cpp @@ -23,7 +23,7 @@ void updateFltk() { #if defined(HAVE_FLTK) - if(FlGui::available()) FlGui::instance()->updateViews(); + if(FlGui::available()) FlGui::instance()->updateViews(true, true); #endif }