From: dooglus Date: Mon, 17 Nov 2008 00:38:20 +0000 (+0000) Subject: When loading .sif files, show any warnings in the GUI. When loading .sif files with... X-Git-Url: https://git.pterodactylus.net/?a=commitdiff_plain;h=9eeed0ce9066de4b2e36885d5ec7b66ac8f14aa8;p=synfig.git When loading .sif files, show any warnings in the GUI. When loading .sif files with circular references to themselves, show a warning, and avoid crashing. The circular reference is shortcutted to allow loading. (Fixes https://bugs.launchpad.net/ubuntu/+source/synfig/+bug/195447 ) git-svn-id: https://synfig.svn.sourceforge.net/svnroot/synfig@2203 1f10aa63-cdf2-0310-b900-c93c546f37ac --- diff --git a/synfig-core/trunk/src/synfig/canvas.cpp b/synfig-core/trunk/src/synfig/canvas.cpp index 2997ff4..1bc1a18 100644 --- a/synfig-core/trunk/src/synfig/canvas.cpp +++ b/synfig-core/trunk/src/synfig/canvas.cpp @@ -47,7 +47,7 @@ using namespace synfig; using namespace etl; using namespace std; -namespace synfig { extern Canvas::Handle open_canvas(const String &filename, String &errors); }; +namespace synfig { extern Canvas::Handle open_canvas(const String &filename, String &errors, String &warnings); }; /* === M A C R O S ========================================================= */ @@ -399,7 +399,8 @@ Canvas::find_value_node(const String &id)const //synfig::warning("constfind:value_node_id: "+value_node_id); //synfig::warning("constfind:canvas_id: "+canvas_id); - return find_canvas(canvas_id)->value_node_list_.find(value_node_id); + String warnings; + return find_canvas(canvas_id, warnings)->value_node_list_.find(value_node_id); } ValueNode::Handle @@ -421,7 +422,8 @@ Canvas::surefind_value_node(const String &id) if(canvas_id.empty()) canvas_id=':'; - return surefind_canvas(canvas_id)->value_node_list_.surefind(value_node_id); + String warnings; + return surefind_canvas(canvas_id,warnings)->value_node_list_.surefind(value_node_id); } void @@ -506,11 +508,11 @@ Canvas::remove_value_node(ValueNode::Handle x) x->set_id(""); } -etl::handle -Canvas::surefind_canvas(const String &id) +Canvas::Handle +Canvas::surefind_canvas(const String &id, String &warnings) { if(is_inline() && parent_) - return parent_->surefind_canvas(id); + return parent_->surefind_canvas(id,warnings); if(id.empty()) return this; @@ -522,7 +524,7 @@ Canvas::surefind_canvas(const String &id) // If '#' is the first character, remove it // and attempt to parse the ID again. if(id[0]=='#') - return surefind_canvas(String(id,1)); + return surefind_canvas(String(id,1),warnings); //! \todo This needs a lot more optimization String file_name(id,0,id.find_first_of('#')); @@ -539,16 +541,16 @@ Canvas::surefind_canvas(const String &id) { String errors; if(is_absolute_path(file_name)) - external_canvas=open_canvas(file_name, errors); + external_canvas=open_canvas(file_name, errors, warnings); else - external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name, errors); + external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name, errors, warnings); if(!external_canvas) throw runtime_error(errors); externals_[file_name]=external_canvas; } - return Handle::cast_const(external_canvas.constant()->find_canvas(external_id)); + return Handle::cast_const(external_canvas.constant()->find_canvas(external_id, warnings)); } // If we do not have any resolution, then we assume that the @@ -571,7 +573,7 @@ Canvas::surefind_canvas(const String &id) // If the first character is the separator, then // this references the root canvas. if(id[0]==':') - return get_root()->surefind_canvas(string(id,1)); + return get_root()->surefind_canvas(string(id,1),warnings); // Now we know that the requested Canvas is in a child // of this canvas. We have to find that canvas and @@ -579,25 +581,25 @@ Canvas::surefind_canvas(const String &id) String canvas_name=string(id,0,id.find_first_of(':')); - Canvas::Handle child_canvas=surefind_canvas(canvas_name); + Canvas::Handle child_canvas=surefind_canvas(canvas_name,warnings); - return child_canvas->surefind_canvas(string(id,id.find_first_of(':')+1)); + return child_canvas->surefind_canvas(string(id,id.find_first_of(':')+1),warnings); } Canvas::Handle -Canvas::find_canvas(const String &id) +Canvas::find_canvas(const String &id, String &warnings) { return Canvas::Handle::cast_const( - const_cast(this)->find_canvas(id) + const_cast(this)->find_canvas(id, warnings) ); } Canvas::ConstHandle -Canvas::find_canvas(const String &id)const +Canvas::find_canvas(const String &id, String &warnings)const { if(is_inline() && parent_) - return parent_->find_canvas(id); + return parent_->find_canvas(id, warnings); if(id.empty()) return this; @@ -609,7 +611,7 @@ Canvas::find_canvas(const String &id)const // If '#' is the first character, remove it // and attempt to parse the ID again. if(id[0]=='#') - return find_canvas(String(id,1)); + return find_canvas(String(id,1), warnings); //! \todo This needs a lot more optimization String file_name(id,0,id.find_first_of('#')); @@ -624,18 +626,18 @@ Canvas::find_canvas(const String &id)const external_canvas=externals_[file_name]; else { - String errors; + String errors, warnings; if(is_absolute_path(file_name)) - external_canvas=open_canvas(file_name, errors); + external_canvas=open_canvas(file_name, errors, warnings); else - external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name, errors); + external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name, errors, warnings); if(!external_canvas) throw runtime_error(errors); externals_[file_name]=external_canvas; } - return Handle::cast_const(external_canvas.constant()->find_canvas(external_id)); + return Handle::cast_const(external_canvas.constant()->find_canvas(external_id, warnings)); } // If we do not have any resolution, then we assume that the @@ -656,7 +658,7 @@ Canvas::find_canvas(const String &id)const // If the first character is the separator, then // this references the root canvas. if(id[0]==':') - return get_root()->find_canvas(string(id,1)); + return get_root()->find_canvas(string(id,1), warnings); // Now we know that the requested Canvas is in a child // of this canvas. We have to find that canvas and @@ -664,9 +666,9 @@ Canvas::find_canvas(const String &id)const String canvas_name=string(id,0,id.find_first_of(':')); - Canvas::ConstHandle child_canvas=find_canvas(canvas_name); + Canvas::ConstHandle child_canvas=find_canvas(canvas_name, warnings); - return child_canvas->find_canvas(string(id,id.find_first_of(':')+1)); + return child_canvas->find_canvas(string(id,id.find_first_of(':')+1), warnings); } Canvas::Handle @@ -914,7 +916,8 @@ Canvas::add_child_canvas(Canvas::Handle child_canvas, const synfig::String& id) try { - find_canvas(id); + String warnings; + find_canvas(id, warnings); throw Exception::IDAlreadyExists(id); } catch(Exception::IDNotFound) diff --git a/synfig-core/trunk/src/synfig/canvas.h b/synfig-core/trunk/src/synfig/canvas.h index 76ea332..7f22ce5 100644 --- a/synfig-core/trunk/src/synfig/canvas.h +++ b/synfig-core/trunk/src/synfig/canvas.h @@ -469,19 +469,19 @@ public: ** If not found, it creates a new Canvas and returns it ** If an error occurs, it returns an empty handle */ - Handle surefind_canvas(const String &id); + Handle surefind_canvas(const String &id,String &warnings); //! Finds a child Canvas in the Canvas with the given \a id /*! \return If found, returns a handle to the child Canvas. ** Otherwise, returns an empty handle. */ - Handle find_canvas(const String &id); + Handle find_canvas(const String &id, String &warnings); //! Finds a child Canvas in the Canvas with the given \a id /*! \return If found, returns a handle to the child Canvas. ** Otherwise, returns an empty handle. */ - ConstHandle find_canvas(const String &id)const; + ConstHandle find_canvas(const String &id, String &warnings)const; //! Sets the file path for the Canvas //void set_file_path(const String &); diff --git a/synfig-core/trunk/src/synfig/loadcanvas.cpp b/synfig-core/trunk/src/synfig/loadcanvas.cpp index cf01a8c..102b744 100644 --- a/synfig-core/trunk/src/synfig/loadcanvas.cpp +++ b/synfig-core/trunk/src/synfig/loadcanvas.cpp @@ -39,6 +39,7 @@ #include #include +#include "layer_pastecanvas.h" #include "loadcanvas.h" #include "valuenode.h" #include "valuenode_subtract.h" @@ -92,6 +93,8 @@ test_class test_class_instance; inline bool is_whitespace(char x) { return ((x)=='\n' || (x)=='\t' || (x)==' '); } +std::set CanvasParser::loading_; + /* === P R O C E D U R E S ================================================= */ static std::map* open_canvas_map_(0); @@ -121,19 +124,44 @@ static void _canvas_file_name_changed(Canvas *x) } Canvas::Handle -synfig::open_canvas(const String &filename,String &errors) +synfig::open_canvas(const String &filename,String &errors,String &warnings) { - return open_canvas_as(filename, filename, errors); + return open_canvas_as(filename, filename, errors, warnings); } Canvas::Handle -synfig::open_canvas_as(const String &filename,const String &as,String &errors) +synfig::open_canvas_as(const String &filename,const String &as,String &errors,String &warnings) { - CanvasParser parser; + if (CanvasParser::loading_.count(filename)) + { + String warning(strprintf(_("cannot load '%s' recursively"), filename.c_str())); + synfig::warning(warning); + warnings = " * " + warning + "\n"; + Canvas::Handle canvas(Canvas::create()); + canvas->set_file_name(filename); + Layer::Handle paste(Layer_PasteCanvas::create()); + canvas->push_back(paste); + paste->set_description(warning); + return canvas; + } + Canvas::Handle canvas; + CanvasParser parser; parser.set_allow_errors(true); - Canvas::Handle canvas=parser.parse_from_file_as(filename,as,errors); + try + { + CanvasParser::loading_.insert(filename); + canvas=parser.parse_from_file_as(filename,as,errors); + } + catch (...) + { + CanvasParser::loading_.erase(filename); + throw; + } + CanvasParser::loading_.erase(filename); + + warnings = parser.get_warnings_text(); if(parser.error_count()) { @@ -161,10 +189,13 @@ CanvasParser::error_unexpected_element(xmlpp::Node *element,const String &got) void CanvasParser::warning(xmlpp::Node *element, const String &text) { - string str=strprintf("%s:<%s>:%d: warning: ",filename.c_str(),element->get_name().c_str(),element->get_line())+text; - //synfig::warning(str); - cerr<:%d: ",filename.c_str(),element->get_name().c_str(),element->get_line())+text; + + synfig::warning(str); + // cerr<=max_warnings_) fatal_error(element, _("Too many warnings")); } @@ -908,7 +939,11 @@ CanvasParser::parse_animated(xmlpp::Element *element,Canvas::Handle canvas) // // if (type==ValueBase::TYPE_CANVAS) - waypoint_value_node=ValueNode_Const::create(canvas->surefind_canvas(child->get_attribute("use")->get_value())); + { + String warnings; + waypoint_value_node=ValueNode_Const::create(canvas->surefind_canvas(child->get_attribute("use")->get_value(), warnings)); + warnings_text += warnings; + } else waypoint_value_node=canvas->surefind_value_node(child->get_attribute("use")->get_value()); } @@ -1718,7 +1753,11 @@ CanvasParser::parse_layer(xmlpp::Element *element,Canvas::Handle canvas) error(child,_("Empty use=\"\" value in ")); else if(layer->get_param(param_name).get_type()==ValueBase::TYPE_CANVAS) { - if(!layer->set_param(param_name,canvas->surefind_canvas(str))) + String warnings; + Canvas::Handle c(canvas->surefind_canvas(str, warnings)); + warnings_text += warnings; + if(!c) error((*iter),strprintf(_("Failed to load subcanvas '%s'"), str.c_str())); + if(!layer->set_param(param_name,c)) error((*iter),_("Layer rejected canvas link")); } else @@ -1830,7 +1869,9 @@ CanvasParser::parse_canvas(xmlpp::Element *element,Canvas::Handle parent,bool in { try { - canvas=parent->find_canvas(element->get_attribute("id")->get_value()); + String warnings; + canvas=parent->find_canvas(element->get_attribute("id")->get_value(), warnings); + warnings_text += warnings; } catch(...) { diff --git a/synfig-core/trunk/src/synfig/loadcanvas.h b/synfig-core/trunk/src/synfig/loadcanvas.h index 9c53d12..c527f03 100644 --- a/synfig-core/trunk/src/synfig/loadcanvas.h +++ b/synfig-core/trunk/src/synfig/loadcanvas.h @@ -74,6 +74,7 @@ private: String path; String errors_text; + String warnings_text; GUID guid_; @@ -116,10 +117,13 @@ public: const synfig::String& get_path()const { return path; } const synfig::String& get_errors_text()const { return errors_text; } + const synfig::String& get_warnings_text()const { return warnings_text; } //! \todo writeme Canvas::Handle parse_from_file_as(const String &filename,const String &as,String &errors); + static std::set loading_; + private: // Error/Warning handling functions @@ -168,8 +172,8 @@ private: //! Loads a canvas from \a filename /*! \return The Canvas's handle on success, an empty handle on failure */ -extern Canvas::Handle open_canvas(const String &filename,String &errors); -extern Canvas::Handle open_canvas_as(const String &filename,const String &as,String &errors); +extern Canvas::Handle open_canvas(const String &filename,String &errors,String &warnings); +extern Canvas::Handle open_canvas_as(const String &filename,const String &as,String &errors,String &warnings); std::map >& get_open_canvas_map(); diff --git a/synfig-core/trunk/src/tool/main.cpp b/synfig-core/trunk/src/tool/main.cpp index 13fc438..2fc8640 100644 --- a/synfig-core/trunk/src/tool/main.cpp +++ b/synfig-core/trunk/src/tool/main.cpp @@ -1174,8 +1174,8 @@ int main(int argc, char *argv[]) return ret; // Open the composition - String errors; - job_list.front().root=open_canvas(job_list.front().filename, errors); + String errors, warnings; + job_list.front().root=open_canvas(job_list.front().filename, errors, warnings); if(!job_list.front().root) { @@ -1199,7 +1199,8 @@ int main(int argc, char *argv[]) { try { - job_list.front().canvas=job_list.front().root->find_canvas(canvasid); + String warnings; + job_list.front().canvas=job_list.front().root->find_canvas(canvasid, warnings); } catch(Exception::IDNotFound) { @@ -1235,8 +1236,8 @@ int main(int argc, char *argv[]) extract_append(imageargs,composite_file); if(!composite_file.empty()) { - String errors; - Canvas::Handle composite(open_canvas(composite_file, errors)); + String errors, warnings; + Canvas::Handle composite(open_canvas(composite_file, errors, warnings)); if(!composite) { cerr<<_("Unable to append '")< instance) // find the canvas synfig::Canvas::Handle canvas; try { - canvas = instance->get_canvas()->find_canvas(String(canvas_window_size, current, separator-current)); + String warnings; + canvas = instance->get_canvas()->find_canvas(String(canvas_window_size, current, separator-current), warnings); } catch(Exception::IDNotFound) { // can't find the canvas; skip to the next canvas or return @@ -2358,9 +2359,9 @@ App::open_as(std::string filename,std::string as) try { OneMoment one_moment; - String errors; + String errors, warnings; - etl::handle canvas(open_canvas_as(filename,as,errors)); + etl::handle canvas(open_canvas_as(filename,as,errors,warnings)); if(canvas && get_instance(canvas)) { get_instance(canvas)->find_canvas_view(canvas)->present(); @@ -2372,6 +2373,9 @@ App::open_as(std::string filename,std::string as) if(!canvas) throw (String)strprintf(_("Unable to load \"%s\":\n\n"),filename.c_str()) + errors; + if (warnings != "") + dialog_warning_blocking(_("Warnings"), strprintf("%s:\n\n%s", _("Warnings"), warnings.c_str())); + if (as.find(custom_filename_prefix.c_str()) != 0) add_recent_file(as); diff --git a/synfig-studio/trunk/src/gtkmm/widget_canvaschooser.cpp b/synfig-studio/trunk/src/gtkmm/widget_canvaschooser.cpp index 7ca1ba9..2b9e3f1 100644 --- a/synfig-studio/trunk/src/gtkmm/widget_canvaschooser.cpp +++ b/synfig-studio/trunk/src/gtkmm/widget_canvaschooser.cpp @@ -150,7 +150,8 @@ Widget_CanvasChooser::chooser_menu() Canvas::Handle new_canvas; try { - new_canvas=parent_canvas->find_canvas(canvas_name); + String warnings; + new_canvas=parent_canvas->find_canvas(canvas_name, warnings); set_value_(new_canvas); } catch(std::runtime_error x) diff --git a/synfig-studio/trunk/src/synfigapp/canvasinterface.cpp b/synfig-studio/trunk/src/synfigapp/canvasinterface.cpp index ca4c651..297b7f2 100644 --- a/synfig-studio/trunk/src/synfigapp/canvasinterface.cpp +++ b/synfig-studio/trunk/src/synfigapp/canvasinterface.cpp @@ -579,8 +579,8 @@ CanvasInterface::import(const synfig::String &filename, bool resize_image) // If this is a SIF file, then we need to do things slightly differently if(ext=="sif" || ext=="sifz")try { - String errors; - Canvas::Handle outside_canvas(synfig::open_canvas(filename, errors)); + String errors, warnings; + Canvas::Handle outside_canvas(synfig::open_canvas(filename, errors, warnings)); if(!outside_canvas) throw String(_("Unable to open this composition")) + ":\n\n" + errors;