+}
+
+void Layout::add_route(Route &r)
+{
+ if(routes.count(r.get_name()))
+ throw KeyError("Duplicate route name");
+ routes[r.get_name()] = &r;
+ signal_route_added.emit(r);
+}
+
+Route &Layout::get_route(const string &name) const
+{
+ map<string, Route *>::const_iterator i = routes.find(name);
+ if(i==routes.end())
+ throw KeyError("Unknown route", name);
+ return *i->second;
+}
+
+void Layout::remove_route(Route &r)
+{
+ if(routes.erase(r.get_name()))
+ signal_route_removed.emit(r);
+}
+
+void Layout::save(const string &fn)
+{
+ IO::BufferedFile out(fn, IO::M_WRITE);
+ DataFile::Writer writer(out);
+
+ if(!base.empty())
+ writer.write((DataFile::Statement("base"), base));
+
+ for(set<Track *>::iterator i=tracks.begin(); i!=tracks.end(); ++i)
+ {
+ DataFile::Statement st("track");
+ st.append((*i)->get_type().get_article_number());
+ (*i)->save(st.sub);
+ writer.write(st);
+ }
+
+ for(map<string, Route *>::iterator i=routes.begin(); i!=routes.end(); ++i)
+ {
+ DataFile::Statement st("route");
+ st.append(i->first);
+ i->second->save(st.sub);
+ writer.write(st);