1 /* === S Y N F I G ========================================================= */
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
10 ** This package is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU General Public License as
12 ** published by the Free Software Foundation; either version 2 of
13 ** the License, or (at your option) any later version.
15 ** This package is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** General Public License for more details.
21 /* ========================================================================= */
23 /* === H E A D E R S ======================================================= */
36 #ifdef HAVE_SYS_ERRNO_H
37 #include <sys/errno.h>
39 #include <gtkmm/fileselection.h>
40 #include <gtkmm/dialog.h>
41 #include <gtkmm/messagedialog.h>
42 #include <gtkmm/label.h>
43 #include <gtkmm/stock.h>
44 #include <gtkmm/stockitem.h>
45 #include <gtkmm/iconsource.h>
46 #include <gtkmm/inputdialog.h>
47 #include <gtkmm/accelmap.h>
48 #include <gtkmm/uimanager.h>
52 #include <synfig/loadcanvas.h>
57 #include "canvasview.h"
58 #include "dialog_setup.h"
59 #include "dialog_gradient.h"
60 #include "dialog_color.h"
63 #include "onemoment.h"
65 #include "dockmanager.h"
67 #include "state_eyedrop.h"
68 #include "state_normal.h"
69 #include "state_draw.h"
70 #include "state_fill.h"
71 #include "state_bline.h"
72 #include "state_polygon.h"
73 #include "state_sketch.h"
74 #include "state_gradient.h"
75 #include "state_circle.h"
76 #include "state_rectangle.h"
77 #include "state_smoothmove.h"
78 #include "state_scale.h"
79 #include "state_width.h"
80 #include "state_rotate.h"
81 #include "state_zoom.h"
83 #include "devicetracker.h"
84 #include "dialog_tooloptions.h"
86 #include "autorecover.h"
88 #include <synfigapp/settings.h>
89 #include "dock_history.h"
90 #include "dock_canvases.h"
91 #include "dock_keyframes.h"
92 #include "dock_layers.h"
93 #include "dock_params.h"
94 #include "dock_metadata.h"
95 #include "dock_children.h"
96 #include "dock_info.h"
97 #include "dock_navigator.h"
98 #include "dock_layergroups.h"
99 #include "dock_timetrack.h"
100 #include "dock_curves.h"
102 #include "mod_palette/mod_palette.h"
103 #include "mod_mirror/mod_mirror.h"
105 #include <sys/stat.h>
111 #include "statemanager.h"
118 #define _WIN32_WINNT 0x0500
121 #include <gtkmm/accelmap.h>
122 #include <gtkmm/filechooser.h>
123 #include <gtkmm/filechooserdialog.h>
127 /* === U S I N G =========================================================== */
131 using namespace synfig;
132 using namespace studio;
134 /* === M A C R O S ========================================================= */
136 #ifndef SYNFIG_USER_APP_DIR
138 #define SYNFIG_USER_APP_DIR "Library/Synfig"
139 #elif defined(_WIN32)
140 #define SYNFIG_USER_APP_DIR "Synfig"
142 #define SYNFIG_USER_APP_DIR ".synfig"
147 #define DPM2DPI(x) (float(x)/39.3700787402f)
148 #define DPI2DPM(x) (float(x)*39.3700787402f)
154 # define IMAGE_DIR "share\\pixmaps"
159 # define IMAGE_DIR "/usr/local/share/pixmaps"
163 # define IMAGE_EXT "tif"
166 #include <synfigapp/main.h>
168 /* === S I G N A L S ======================================================= */
170 static sigc::signal<void> signal_present_all_;
172 App::signal_present_all() { return signal_present_all_; }
174 static sigc::signal<void> signal_recent_files_changed_;
176 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
178 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
179 sigc::signal<void,etl::loose_handle<CanvasView> >&
180 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
182 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
183 sigc::signal<void,etl::handle<Instance> >&
184 App::signal_instance_selected() { return signal_instance_selected_; }
186 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
187 sigc::signal<void,etl::handle<Instance> >&
188 App::signal_instance_created() { return signal_instance_created_; }
190 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
191 sigc::signal<void,etl::handle<Instance> >&
192 App::signal_instance_deleted() { return signal_instance_deleted_; }
194 /* === G L O B A L S ======================================================= */
196 static std::list<std::string> recent_files;
197 const std::list<std::string>& App::get_recent_files() { return recent_files; }
199 int App::Busy::count;
200 bool App::shutdown_in_progress;
202 synfig::Gamma App::gamma;
204 Glib::RefPtr<studio::UIManager> App::ui_manager_;
206 synfig::Distance::System App::distance_system;
208 studio::Dialog_Setup* App::dialog_setup;
210 etl::handle< studio::ModPalette > mod_palette_;
211 //studio::Dialog_Palette* App::dialog_palette;
213 std::list<etl::handle<Instance> > App::instance_list;
215 static etl::handle<synfigapp::UIInterface> ui_interface_;
216 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
218 etl::handle<Instance> App::selected_instance;
219 etl::handle<CanvasView> App::selected_canvas_view;
221 studio::Toolbox *studio::App::toolbox=NULL;
223 studio::AutoRecover *studio::App::auto_recover=NULL;
225 studio::IPC *ipc=NULL;
227 studio::DockManager* studio::App::dock_manager=0;
229 studio::DeviceTracker* studio::App::device_tracker=0;
231 studio::Dialog_Gradient* studio::App::dialog_gradient;
233 studio::Dialog_Color* studio::App::dialog_color;
235 Gtk::InputDialog* studio::App::dialog_input;
237 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
239 studio::Dock_History* dock_history;
240 studio::Dock_Canvases* dock_canvases;
241 studio::Dock_Keyframes* dock_keyframes;
242 studio::Dock_Layers* dock_layers;
243 studio::Dock_Params* dock_params;
244 studio::Dock_MetaData* dock_meta_data;
245 studio::Dock_Children* dock_children;
246 studio::Dock_Info* dock_info;
247 studio::Dock_LayerGroups* dock_layer_groups;
248 studio::Dock_Navigator* dock_navigator;
249 studio::Dock_Timetrack* dock_timetrack;
250 studio::Dock_Curves* dock_curves;
252 std::list< etl::handle< studio::Module > > module_list_;
254 bool studio::App::use_colorspace_gamma=true;
256 static int max_recent_files_=25;
257 int studio::App::get_max_recent_files() { return max_recent_files_; }
258 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
260 static synfig::String app_base_path_;
263 }; // END of namespace studio
264 studio::StateManager* state_manager;
269 class GlobalUIInterface : public synfigapp::UIInterface
273 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
278 true // use_separator
280 Gtk::Label label(message);
283 dialog.get_vbox()->pack_start(label);
284 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
285 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
287 dialog.set_default_response(dflt);
289 return (Response)dialog.run();
291 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
296 true // use_separator
298 Gtk::Label label(message);
301 dialog.get_vbox()->pack_start(label);
302 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
303 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
304 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
306 dialog.set_default_response(dflt);
308 return (Response)dialog.run();
310 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
315 true // use_separator
317 Gtk::Label label(message);
320 dialog.get_vbox()->pack_start(label);
321 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
322 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
324 dialog.set_default_response(dflt);
326 return (Response)dialog.run();
330 task(const std::string &task)
332 std::cerr<<task<<std::endl;
333 while(studio::App::events_pending())studio::App::iteration(false);
338 error(const std::string &err)
340 Gtk::MessageDialog dialog(err, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
347 warning(const std::string &err)
349 std::cerr<<"warning: "<<err<<std::endl;
350 while(studio::App::events_pending())studio::App::iteration(false);
355 amount_complete(int current, int total)
357 while(studio::App::events_pending())studio::App::iteration(false);
362 /* === P R O C E D U R E S ================================================= */
364 typedef unsigned char U8;
365 typedef unsigned short U16;
366 typedef unsigned long U32;
376 static inline U32 hash_U32(U32 i)
378 i=i*1664525+1013904223;
379 i=i*1664525+1013904223;
380 i=i*1664525+1013904223;
385 static const int endian_fix_table[8] = { 3, 2, 1, 0, 7, 6, 5, 4 } ;
386 #define endian_fix(x) (endian_fix_table[x])
388 #define endian_fix(x) (x)
391 int v_unwind_key(V_KeyUnwound* unwound, const char* key)
394 unwound->element.serial=0;
395 unwound->element.checksum=0;
403 case '0': data=0; break;
404 case '1': data=1; break;
405 case '2': data=2; break;
406 case '3': data=3; break;
407 case '4': data=4; break;
408 case '5': data=5; break;
409 case '6': data=6; break;
410 case '7': data=7; break;
411 case '8': data=8; break;
412 case '9': data=9; break;
413 case 'a': case 'A': data=10; break;
414 case 'b': case 'B': data=11; break;
415 case 'c': case 'C': data=12; break;
416 case 'd': case 'D': data=13; break;
417 case 'e': case 'E': data=14; break;
418 case 'f': case 'F': data=15; break;
419 default: return 0; break;
422 unwound->element.checksum|=(((U32)data&3)<<bit);
423 unwound->element.serial|=(((U32)(data>>2)&3)<<bit);
428 int v_key_check(const char* key, U32* serial, U32 appid)
430 V_KeyUnwound unwound_key;
431 U32 appid_mask_a=hash_U32(appid);
432 U32 appid_mask_b=hash_U32(appid_mask_a);
434 if(!v_unwind_key(&unwound_key, key))
436 // Invalid characters in key
441 // Undo obfuscation pass
443 U32 next=hash_U32(unwound_key.raw[endian_fix(7)]);
448 unwound_key.raw[endian_fix(i)]^=(next>>24);
452 unwound_key.element.serial^=appid_mask_a;
453 unwound_key.element.checksum^=appid_mask_b;
455 *serial=unwound_key.element.serial;
457 return unwound_key.element.checksum==hash_U32(unwound_key.element.serial);
461 int check_license(String basedir)
463 #ifdef LICENSE_KEY_REQUIRED
468 license_file="/usr/local/etc/.synfiglicense";
470 license_file=basedir+"\\etc\\.synfiglicense";
474 key=Glib::file_get_contents(license_file);
475 } catch (Glib::FileError) { }
477 if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
479 while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
483 if(!App::dialog_entry(
484 _("Synfig Studio Authentication"),
485 _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
488 throw String("No License");
491 FILE* file=fopen(license_file.c_str(),"w");
494 fprintf(file,"%s",key.c_str());
498 synfig::error("Unable to save license key!");
500 synfig::info("License Authenticated -- Serial #%05d",serial);
509 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
511 action_group_list.push_back(action_group);
512 Gtk::UIManager::insert_action_group(action_group, pos);
516 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
518 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
519 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
520 if(*iter==action_group)
522 action_group_list.erase(iter);
523 Gtk::UIManager::remove_action_group(action_group);
526 synfig::error("Unable to find action group");
530 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
532 ui_manager->insert_action_group(group,0);
535 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
536 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
539 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
542 if(*iter && (*iter)->get_name()!="menus")
544 synfig::info("Removing action group "+(*iter)->get_name());
545 ui_manager->remove_action_group(*iter);
549 ui_manager->insert_action_group(group,0);
552 for(;!prev_groups.empty();prev_groups.pop_front())
554 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
555 ui_manager->insert_action_group(prev_groups.front(),1);
560 class Preferences : public synfigapp::Settings
563 virtual bool get_value(const synfig::String& key, synfig::String& value)const
567 value=strprintf("%f %f %f %f",
568 App::gamma.get_gamma_r(),
569 App::gamma.get_gamma_g(),
570 App::gamma.get_gamma_b(),
571 App::gamma.get_black_level()
575 if(key=="time_format")
577 value=strprintf("%i",App::get_time_format());
580 if(key=="file_history.size")
582 value=strprintf("%i",App::get_max_recent_files());
585 if(key=="use_colorspace_gamma")
587 value=strprintf("%i",(int)App::use_colorspace_gamma);
590 if(key=="distance_system")
592 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
595 if(key=="auto_recover_backup_interval")
597 value=strprintf("%i",App::auto_recover->get_timeout());
601 return synfigapp::Settings::get_value(key,value);
604 virtual bool set_value(const synfig::String& key,const synfig::String& value)
610 strscanf(value,"%f %f %f %f",
617 App::gamma.set_all(r,g,b,blk);
621 if(key=="time_format")
623 int i(atoi(value.c_str()));
624 App::set_time_format(static_cast<synfig::Time::Format>(i));
627 if(key=="auto_recover_backup_interval")
629 int i(atoi(value.c_str()));
630 App::auto_recover->set_timeout(i);
633 if(key=="file_history.size")
635 int i(atoi(value.c_str()));
636 App::set_max_recent_files(i);
639 if(key=="use_colorspace_gamma")
641 int i(atoi(value.c_str()));
642 App::use_colorspace_gamma=i;
645 if(key=="distance_system")
647 App::distance_system=Distance::ident_system(value);;
651 return synfigapp::Settings::set_value(key,value);
654 virtual KeyList get_key_list()const
656 KeyList ret(synfigapp::Settings::get_key_list());
657 ret.push_back("gamma");
658 ret.push_back("time_format");
659 ret.push_back("distance_system");
660 ret.push_back("file_history.size");
661 ret.push_back("use_colorspace_gamma");
662 ret.push_back("auto_recover_backup_interval");
667 static ::Preferences _preferences;
672 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
674 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
676 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
678 menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
679 menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
680 menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
681 menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
682 menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
683 menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Show/Hide Ducks") );
684 menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
685 menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") );
686 menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") );
687 menus_action_group->add( Gtk::Action::create("menu-group", "Group") );
688 menus_action_group->add( Gtk::Action::create("menu-state", "State") );
689 menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
691 // Add the synfigapp actions...
692 synfigapp::Action::Book::iterator iter;
693 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
695 actions_action_group->add(Gtk::Action::create(
696 "action-"+iter->second.name,
697 get_action_stock_id(iter->second),
698 iter->second.local_name,iter->second.local_name
702 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
703 #define DEFINE_ACTION2(x,stock,label) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock,label,label) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
704 #define DEFINE_ACTION_SIG(group,x,stock,sig) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ group->add(action,sig); }
706 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
707 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
708 DEFINE_ACTION("open", Gtk::Stock::OPEN);
709 DEFINE_ACTION("save", Gtk::Stock::SAVE);
710 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
711 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
712 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
713 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
714 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
715 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
716 DEFINE_ACTION("import", _("Import"));
717 DEFINE_ACTION("render", _("Render"));
718 DEFINE_ACTION("preview", _("Preview"));
719 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
720 DEFINE_ACTION("sound", _("Sound File"));
721 DEFINE_ACTION("options", _("Options"));
722 DEFINE_ACTION("close", _("Close"));
725 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
726 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
727 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
728 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
729 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
730 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
731 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
732 DEFINE_ACTION("properties", _("Properties"));
734 DEFINE_ACTION("mask-position-ducks", _("Show Position Ducks"));
735 DEFINE_ACTION("mask-vertex-ducks", _("Show Vertex Ducks"));
736 DEFINE_ACTION("mask-tangent-ducks", _("Show Tangent Ducks"));
737 DEFINE_ACTION("mask-radius-ducks", _("Show Radius Ducks"));
738 DEFINE_ACTION("mask-width-ducks", _("Show Width Ducks"));
739 DEFINE_ACTION("mask-angle-ducks", _("Show Angle Ducks"));
740 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
741 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
742 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
743 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
744 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
745 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
746 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
747 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
748 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
749 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
750 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
751 DEFINE_ACTION("play", _("Play"));
752 DEFINE_ACTION("pause", _("Pause"));
753 DEFINE_ACTION("stop", _("Stop"));
754 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
755 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
756 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
757 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
758 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
759 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
760 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
761 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
762 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
763 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
764 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
765 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
766 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
767 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
768 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
769 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
770 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
771 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
772 DEFINE_ACTION("seek-end", _("Seek to End"));
774 DEFINE_ACTION("action-group_add", _("Add group"));
776 DEFINE_ACTION("canvas-new", _("New Canvas"));
778 DEFINE_ACTION("amount-inc", _("Increase Amount"));
779 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
784 // Set up synfigapp actions
786 synfigapp::Action::Book::iterator iter;
788 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
790 Gtk::StockID stock_id;
792 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
794 //Gtk::Image* image(manage(new Gtk::Image()));
795 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
796 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
797 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
798 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
799 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
800 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
801 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
802 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
803 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
804 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
806 actions_action_group->add(Gtk::Action::create(
807 "action-"+iter->second.name,
809 iter->second.local_name,iter->second.local_name
817 Glib::ustring ui_info =
819 " <popup name='menu-toolbox' action='menu-toolbox'>"
820 " <menu action='menu-file'>"
823 " <popup name='menu-main' action='menu-main'>"
824 " <menu action='menu-file'>"
825 " <menuitem action='save' />"
826 " <menuitem action='save-as' />"
827 " <menuitem action='revert' />"
828 " <separator name='bleh01'/>"
829 " <menuitem action='cvs-add' />"
830 " <menuitem action='cvs-update' />"
831 " <menuitem action='cvs-commit' />"
832 " <menuitem action='cvs-revert' />"
833 " <separator name='bleh02'/>"
834 " <menuitem action='import' />"
835 " <separator name='bleh03'/>"
836 " <menuitem action='render' />"
837 " <menuitem action='preview' />"
838 " <menuitem action='sound' />"
839 " <separator name='bleh04'/>"
840 " <menuitem action='options' />"
841 " <menuitem action='close' />"
843 " <menu action='menu-edit'>"
844 " <menuitem action='undo'/>"
845 " <menuitem action='redo'/>"
846 " <separator name='bleh05'/>"
847 " <menuitem action='cut'/>"
848 " <menuitem action='copy'/>"
849 " <menuitem action='paste'/>"
850 " <separator name='bleh06'/>"
851 " <menuitem action='select-all-ducks'/>"
852 " <menuitem action='unselect-all-layers'/>"
853 " <separator name='bleh07'/>"
854 " <menuitem action='properties'/>"
856 " <menu action='menu-view'>"
857 " <menu action='menu-duck-mask'>"
858 " <menuitem action='mask-position-ducks' />"
859 " <menuitem action='mask-vertex-ducks' />"
860 " <menuitem action='mask-tangent-ducks' />"
861 " <menuitem action='mask-radius-ducks' />"
862 " <menuitem action='mask-width-ducks' />"
863 " <menuitem action='mask-angle-ducks' />"
865 " <menu action='menu-preview-quality'>"
866 " <menuitem action='quality-00' />"
867 " <menuitem action='quality-01' />"
868 " <menuitem action='quality-02' />"
869 " <menuitem action='quality-03' />"
870 " <menuitem action='quality-04' />"
871 " <menuitem action='quality-05' />"
872 " <menuitem action='quality-06' />"
873 " <menuitem action='quality-07' />"
874 " <menuitem action='quality-08' />"
875 " <menuitem action='quality-09' />"
876 " <menuitem action='quality-10' />"
878 " <separator name='bleh08'/>"
879 " <menuitem action='play'/>"
880 " <menuitem action='pause'/>"
881 " <menuitem action='stop'/>"
882 " <menuitem action='dialog-flipbook'/>"
883 " <separator name='bleh09'/>"
884 " <menuitem action='toggle-grid-show'/>"
885 " <menuitem action='toggle-grid-snap'/>"
886 " <menuitem action='toggle-guide-show'/>"
887 " <menuitem action='toggle-low-res'/>"
888 " <menuitem action='toggle-onion-skin'/>"
889 " <separator name='bleh10'/>"
890 " <menuitem action='canvas-zoom-in'/>"
891 " <menuitem action='canvas-zoom-out'/>"
892 " <menuitem action='canvas-zoom-fit'/>"
893 " <menuitem action='canvas-zoom-100'/>"
894 " <separator name='bleh11'/>"
895 " <menuitem action='time-zoom-in'/>"
896 " <menuitem action='time-zoom-out'/>"
897 " <separator name='bleh12'/>"
898 " <menuitem action='jump-next-keyframe'/>"
899 " <menuitem action='jump-prev-keyframe'/>"
900 " <menuitem action='seek-next-frame'/>"
901 " <menuitem action='seek-prev-frame'/>"
902 " <menuitem action='seek-next-second'/>"
903 " <menuitem action='seek-prev-second'/>"
904 " <menuitem action='seek-begin'/>"
905 " <menuitem action='seek-end'/>"
907 " <menu action='menu-canvas'>"
908 " <menuitem action='canvas-new'/>"
910 " <menu name='menu-state' action='menu-state'>"
912 " <menu action='menu-group'>"
913 " <menuitem action='action-group_add'/>"
915 " <menu action='menu-layer'>"
916 //" <menuitem action='cut'/>"
917 //" <menuitem action='copy'/>"
918 //" <menuitem action='paste'/>"
919 //" <separator name='bleh06'/>"
920 " <menu action='menu-layer-new'></menu>"
921 " <menuitem action='amount-inc'/>"
922 " <menuitem action='amount-dec'/>"
924 " <menu action='menu-keyframe'>"
925 " <menuitem action='keyframe-properties'/>"
932 " <menubar name='MenuBar'>"
933 " <menu action='MenuFile'>"
934 " <menuitem action='New'/>"
935 " <menuitem action='Open'/>"
937 " <menuitem action='Quit'/>"
939 " <menu action='MenuEdit'>"
940 " <menuitem action='Cut'/>"
941 " <menuitem action='Copy'/>"
942 " <menuitem action='Paste'/>"
945 " <toolbar name='ToolBar'>"
946 " <toolitem action='Open'/>"
947 " <toolitem action='Quit'/>"
953 actions_action_group->set_sensitive(false);
954 App::ui_manager()->set_add_tearoffs(true);
955 App::ui_manager()->insert_action_group(menus_action_group,1);
956 App::ui_manager()->insert_action_group(actions_action_group,1);
957 App::ui_manager()->add_ui_from_string(ui_info);
959 //App::ui_manager()->get_accel_group()->unlock();
961 catch(const Glib::Error& ex)
963 synfig::error("building menus and toolbars failed: " + ex.what());
966 // Add default keyboard accelerators
967 #define ACCEL(path,accel) \
969 Gtk::AccelKey accel_key(accel,path); \
970 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
973 #define ACCEL2(accel) \
975 Gtk::AccelKey accel_key(accel); \
976 Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(), accel_key.get_mod()); \
979 ACCEL("<Actions>//select-all-ducks","<Control>a");
980 ACCEL("<Actions>//unselect-all-layers","<Control>d");
981 ACCEL("<Actions>//render","F9");
982 ACCEL("<Actions>//preview","F11");
983 ACCEL("<Actions>//properties","F8");
984 ACCEL("<Actions>//options","F12");
985 ACCEL("<Actions>//import","<control>i");
986 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
987 ACCEL("<Actions>//toggle-grid-show","<Control>g");
988 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
989 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
990 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
991 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
992 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
993 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
994 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
995 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
997 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
998 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
1000 ACCEL("<Actions>//quality-01","<Control>1");
1001 ACCEL("<Actions>//quality-02","<Control>2");
1002 ACCEL("<Actions>//quality-03","<Control>3");
1003 ACCEL("<Actions>//quality-04","<Control>4");
1004 ACCEL("<Actions>//quality-05","<Control>5");
1005 ACCEL("<Actions>//quality-06","<Control>6");
1006 ACCEL("<Actions>//quality-07","<Control>7");
1007 ACCEL("<Actions>//quality-08","<Control>8");
1008 ACCEL("<Actions>//quality-09","<Control>9");
1009 ACCEL("<Actions>//quality-10","<Control>0");
1010 ACCEL("<Actions>//undo","<Control>z");
1011 ACCEL("<Actions>//redo","<Control>r");
1012 ACCEL("<Actions>//action-layer_remove","Delete");
1014 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
1015 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
1016 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
1017 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
1018 ACCEL("<Actions>//time-zoom-in","+");
1019 ACCEL("<Actions>//time-zoom-out","_");
1021 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
1022 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
1024 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
1025 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
1026 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
1027 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
1028 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
1029 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
1030 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
1031 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
1032 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
1033 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
1034 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
1035 ACCEL("<Actions>//seek-begin","Home");
1036 ACCEL("<Actions>//seek-end","End");
1038 ACCEL("<Actions>//state-normal", "<Mod1>a");
1039 ACCEL("<Actions>//state-smooth_move", "<Mod1>v");
1040 ACCEL("<Actions>//state-scale", "<Mod1>d");
1041 ACCEL("<Actions>//state-rotate", "<Mod1>s");
1043 ACCEL("<Actions>//state-bline", "<Mod1>b");
1044 ACCEL("<Actions>//state-circle", "<Mod1>c");
1045 ACCEL("<Actions>//state-rectangle", "<Mod1>r");
1046 ACCEL("<Actions>//state-gradient", "<Mod1>g");
1048 ACCEL("<Actions>//state-eyedrop", "<Mod1>e");
1049 ACCEL("<Actions>//state-fill", "<Mod1>f");
1050 ACCEL("<Actions>//state-zoom", "<Mod1>z");
1051 ACCEL("<Actions>//state-polygon", "<Mod1>p");
1053 ACCEL("<Actions>//state-draw", "<Mod1>w");
1054 ACCEL("<Actions>//state-sketch", "<Mod1>k");
1055 ACCEL("<Actions>//state-width", "<Mod1>t");
1056 ACCEL("<Actions>//state-mirror", "<Mod1>m");
1058 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1064 #define mkdir(x,y) mkdir(x)
1067 /* === M E T H O D S ======================================================= */
1069 App::App(int *argc, char ***argv):
1070 Gtk::Main(argc,argv),
1071 IconControler(etl::dirname((*argv)[0]))
1073 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1076 serial_=check_license(app_base_path_);
1079 ui_interface_=new GlobalUIInterface();
1083 Glib::thread_init();
1085 distance_system=Distance::SYSTEM_UNITS;
1087 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1090 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1094 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1102 if(!SYNFIG_CHECK_VERSION())
1104 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1105 dialog_error_blocking("Synfig Studio",
1106 "This copy of Synfig Studio was compiled against a\n"
1107 "different version of libsynfig than what is currently\n"
1108 "installed. Synfig Studio will now abort. Try downloading\n"
1109 "the latest version from the Synfig website at\n"
1110 "http://www.synfig.com/ "
1115 catch(synfig::SoftwareExpired)
1117 cerr<<"FATAL: Software Expired"<<endl;
1118 dialog_error_blocking("Synfig Studio",
1119 "This copy of Synfig Studio has expired.\n"
1120 "Please erase this copy, or download and\n"
1121 "install the latest copy from the Synfig\n"
1122 "website at http://www.synfig.com/ ."
1126 Glib::set_application_name(_("Synfig Studio"));
1129 about_window.set_can_self_destruct(false);
1130 about_window.show();
1132 shutdown_in_progress=false;
1133 SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
1134 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1136 // Initialize the Synfig library
1137 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1140 get_ui_interface()->error("Failed to initialize synfig!");
1144 // add the preferences to the settings
1145 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1149 studio_init_cb.task("Init UI Manager...");
1150 App::ui_manager_=studio::UIManager::create();
1153 studio_init_cb.task("Init Dock Manager...");
1154 dock_manager=new studio::DockManager();
1156 studio_init_cb.task("Init State Manager...");
1157 state_manager=new StateManager();
1159 studio_init_cb.task("Init Toolbox...");
1160 toolbox=new studio::Toolbox();
1162 studio_init_cb.task("Init Tool Options...");
1163 dialog_tool_options=new studio::Dialog_ToolOptions();
1164 dock_manager->register_dockable(*dialog_tool_options);
1166 studio_init_cb.task("Init History...");
1167 dock_history=new studio::Dock_History();
1168 dock_manager->register_dockable(*dock_history);
1170 studio_init_cb.task("Init Canvases...");
1171 dock_canvases=new studio::Dock_Canvases();
1172 dock_manager->register_dockable(*dock_canvases);
1174 studio_init_cb.task("Init Keyframes...");
1175 dock_keyframes=new studio::Dock_Keyframes();
1176 dock_manager->register_dockable(*dock_keyframes);
1178 studio_init_cb.task("Init Layers...");
1179 dock_layers=new studio::Dock_Layers();
1180 dock_manager->register_dockable(*dock_layers);
1182 studio_init_cb.task("Init Params...");
1183 dock_params=new studio::Dock_Params();
1184 dock_manager->register_dockable(*dock_params);
1186 studio_init_cb.task("Init MetaData...");
1187 dock_meta_data=new studio::Dock_MetaData();
1188 dock_manager->register_dockable(*dock_meta_data);
1190 studio_init_cb.task("Init Children...");
1191 dock_children=new studio::Dock_Children();
1192 dock_manager->register_dockable(*dock_children);
1194 studio_init_cb.task("Init Info...");
1195 dock_info = new studio::Dock_Info();
1196 dock_manager->register_dockable(*dock_info);
1198 studio_init_cb.task("Init Navigator...");
1199 dock_navigator = new studio::Dock_Navigator();
1200 dock_manager->register_dockable(*dock_navigator);
1202 studio_init_cb.task("Init Timetrack...");
1203 dock_timetrack = new studio::Dock_Timetrack();
1204 dock_manager->register_dockable(*dock_timetrack);
1206 studio_init_cb.task("Init Curve Editor...");
1207 dock_curves = new studio::Dock_Curves();
1208 dock_manager->register_dockable(*dock_curves);
1210 studio_init_cb.task("Init Layer Groups...");
1211 dock_layer_groups = new studio::Dock_LayerGroups();
1212 dock_manager->register_dockable(*dock_layer_groups);
1215 studio_init_cb.task("Init Color Dialog...");
1216 dialog_color=new studio::Dialog_Color();
1218 studio_init_cb.task("Init Gradient Dialog...");
1219 dialog_gradient=new studio::Dialog_Gradient();
1221 studio_init_cb.task("Init DeviceTracker...");
1222 device_tracker=new studio::DeviceTracker();
1224 studio_init_cb.task("Init Tools...");
1225 state_manager->add_state(&state_normal);
1226 state_manager->add_state(&state_smooth_move);
1227 state_manager->add_state(&state_scale);
1228 state_manager->add_state(&state_rotate);
1230 state_manager->add_state(&state_bline);
1233 state_manager->add_state(&state_circle);
1234 state_manager->add_state(&state_rectangle);
1236 state_manager->add_state(&state_gradient);
1237 state_manager->add_state(&state_eyedrop);
1238 state_manager->add_state(&state_fill);
1240 state_manager->add_state(&state_zoom);
1242 // Disabled this tool because it should be
1243 // considered deprecated. Use the bline tool instead.
1244 if(getenv("SYNFIG_ENABLE_POLYGON")) state_manager->add_state(&state_polygon);
1246 // These tools are disabled by default for now,
1247 // because they tend to confuse users.
1248 if(getenv("SYNFIG_ENABLE_DRAW" )) state_manager->add_state(&state_draw);
1249 if(getenv("SYNFIG_ENABLE_SKETCH")) state_manager->add_state(&state_sketch);
1250 if(getenv("SYNFIG_ENABLE_WIDTH" )) state_manager->add_state(&state_width);
1252 studio_init_cb.task("Init ModPalette...");
1253 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1255 studio_init_cb.task("Init ModMirror...");
1256 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1259 studio_init_cb.task("Init Setup Dialog...");
1260 dialog_setup=new studio::Dialog_Setup();
1262 studio_init_cb.task("Init Input Dialog...");
1263 dialog_input=new Gtk::InputDialog();
1264 dialog_input->get_close_button()->signal_clicked().connect( sigc::mem_fun( *dialog_input, &Gtk::InputDialog::hide ) );
1265 dialog_input->get_save_button()->signal_clicked().connect( sigc::ptr_fun(studio::App::dialog_not_implemented) );
1267 studio_init_cb.task("Init auto recovery...");
1268 auto_recover=new AutoRecover();
1270 studio_init_cb.amount_complete(9250,10000);
1271 studio_init_cb.task("Loading Settings...");
1273 studio_init_cb.task("Checking auto-recover...");
1275 studio_init_cb.amount_complete(9900,10000);
1277 if(auto_recover->recovery_needed())
1279 about_window.hide();
1281 get_ui_interface()->yes_no(
1283 "Synfig Studio seems to have crashed\n"
1284 "before you could save all your files.\n"
1285 "Would you like to re-open those files\n"
1286 "and recover your unsaved changes?"
1287 )==synfigapp::UIInterface::RESPONSE_YES
1290 if(!auto_recover->recover())
1292 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1295 get_ui_interface()->error(
1296 _("Synfig Studio has attempted to recover\n"
1297 "from a previous crash. The files that it has\n"
1298 "recovered are NOT YET SAVED. It would be a good\n"
1299 "idea to review them and save them now.")
1302 about_window.show();
1305 // Look for any files given on the command line,
1306 // and load them if found.
1307 for(;*argc>=1;(*argc)--)
1308 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1310 studio_init_cb.task("Loading files...");
1311 about_window.hide();
1312 open((*argv)[*argc]);
1313 about_window.show();
1316 studio_init_cb.task("Done.");
1317 studio_init_cb.amount_complete(10000,10000);
1323 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1327 StateManager* App::get_state_manager() { return state_manager; }
1331 shutdown_in_progress=true;
1335 synfigapp::Main::settings().remove_domain("pref");
1337 selected_instance=0;
1339 // Unload all of the modules
1340 for(;!module_list_.empty();module_list_.pop_back());
1342 delete state_manager;
1346 delete auto_recover;
1350 // studio::App::iteration(false);
1354 // studio::App::iteration(false);
1356 // studio::App::iteration(false);
1358 delete dialog_setup;
1360 delete dialog_gradient;
1362 delete dialog_color;
1364 delete dialog_input;
1366 delete dock_manager;
1368 instance_list.clear();
1370 // studio::App::iteration(false);
1374 App::get_user_app_directory()
1376 return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
1380 App::get_config_file(const synfig::String& file)
1382 return Glib::build_filename(get_user_app_directory(),file);
1386 App::add_recent_file(const std::string &file_name)
1388 std::string filename(file_name);
1390 assert(!filename.empty());
1392 if(filename.empty())
1395 // Toss out any "hidden" files
1396 if(basename(filename)[0]=='.')
1399 // If we aren't an absolute path, turn outselves into one
1400 if(!is_absolute_path(filename))
1401 filename=absolute_path(filename);
1403 list<string>::iterator iter;
1404 // Check to see if the file is already on the list.
1405 // If it is, then remove it from the list
1406 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1409 recent_files.erase(iter);
1414 // Push the filename to the front of the list
1415 recent_files.push_front(filename);
1417 // Clean out the files at the end of the list.
1418 while(recent_files.size()>(unsigned)get_max_recent_files())
1419 recent_files.pop_back();
1421 signal_recent_files_changed_();
1426 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1429 App::get_time_format()
1431 return _App_time_format;
1435 App::set_time_format(synfig::Time::Format x)
1442 App::save_settings()
1447 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1448 setlocale(LC_NUMERIC, "C");
1450 std::string filename=get_config_file("accelrc");
1451 Gtk::AccelMap::save(filename);
1454 std::string filename=get_config_file("recentfiles");
1456 std::ofstream file(filename.c_str());
1460 synfig::warning("Unable to save %s",filename.c_str());
1464 list<string>::reverse_iterator iter;
1466 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1470 std::string filename=get_config_file("settings");
1471 synfigapp::Main::settings().save_to_file(filename);
1472 setlocale(LC_NUMERIC,old_locale);
1476 synfig::warning("Caught exception when attempting to save settings.");
1481 App::load_settings()
1486 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1487 setlocale(LC_NUMERIC, "C");
1489 std::string filename=get_config_file("accelrc");
1490 Gtk::AccelMap::load(filename);
1493 std::string filename=get_config_file("recentfiles");
1495 std::ifstream file(filename.c_str());
1499 std::string recent_file;
1500 getline(file,recent_file);
1501 if(!recent_file.empty())
1502 add_recent_file(recent_file);
1505 std::string filename=get_config_file("settings");
1506 if(!synfigapp::Main::settings().load_from_file(filename))
1508 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1509 //if(!synfigapp::Main::settings().load_from_file(filename))
1511 gamma.set_gamma(1.0/2.2);
1512 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1513 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1514 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1515 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1516 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1517 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1518 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1519 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1520 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1521 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1522 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1523 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1524 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1527 setlocale(LC_NUMERIC,old_locale);
1531 synfig::warning("Caught exception when attempting to load settings.");
1536 App::shutdown_request(GdkEventAny*)
1540 //return !shutdown_in_progress;
1546 if(shutdown_in_progress)return;
1549 get_ui_interface()->task("Quit Request");
1552 dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
1556 std::list<etl::handle<Instance> >::iterator iter;
1557 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1559 if(!(*iter)->safe_close())
1563 if((*iter)->synfigapp::Instance::get_action_count())
1565 handle<synfigapp::UIInterface> uim;
1566 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1568 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1569 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1571 case synfigapp::UIInterface::RESPONSE_NO:
1573 case synfigapp::UIInterface::RESPONSE_YES:
1576 case synfigapp::UIInterface::RESPONSE_CANCEL:
1585 if((*iter)->synfigapp::Instance::is_modified())
1587 handle<synfigapp::UIInterface> uim;
1588 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1590 string str=strprintf(_("%s has changes not yet on the CVS repository.\nWould you like to commit these changes?"),(*iter)->get_file_name().c_str() );
1591 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1593 case synfigapp::UIInterface::RESPONSE_NO:
1595 case synfigapp::UIInterface::RESPONSE_YES:
1596 (*iter)->dialog_cvs_commit();
1598 case synfigapp::UIInterface::RESPONSE_CANCEL:
1607 // This next line causes things to crash for some reason
1611 shutdown_in_progress=true;
1613 instance_list.clear();
1615 while(studio::App::events_pending())studio::App::iteration(false);
1618 auto_recover->normal_shutdown();
1620 get_ui_interface()->task("Quit Request sent");
1626 dialog_setup->refresh();
1627 dialog_setup->show();
1630 gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
1631 gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
1634 //#define USE_WIN32_FILE_DIALOGS 1
1637 #ifdef USE_WIN32_FILE_DIALOGS
1638 static OPENFILENAME ofn={};
1642 #include <gdk/gdkwin32.h>
1646 App::dialog_open_file(const std::string &title, std::string &filename)
1648 #ifdef USE_WIN32_FILE_DIALOGS
1649 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1651 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1652 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1653 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1655 ofn.lStructSize=sizeof(OPENFILENAME);
1656 ofn.hwndOwner = hWnd;
1657 ofn.hInstance = hInstance;
1658 ofn.lpstrFilter = szFilter;
1659 // ofn.lpstrCustomFilter=NULL;
1660 // ofn.nMaxCustFilter=0;
1661 // ofn.nFilterIndex=0;
1662 // ofn.lpstrFile=NULL;
1663 ofn.nMaxFile=MAX_PATH;
1664 // ofn.lpstrFileTitle=NULL;
1665 // ofn.lpstrInitialDir=NULL;
1666 // ofn.lpstrTitle=NULL;
1667 ofn.Flags=OFN_HIDEREADONLY;
1668 // ofn.nFileOffset=0;
1669 // ofn.nFileExtension=0;
1670 ofn.lpstrDefExt=TEXT("sif");
1671 // ofn.lCustData = 0l;
1673 // ofn.lpTemplateName=NULL;
1675 CHAR szFilename[MAX_PATH];
1677 strcpy(szFilename,filename.c_str());
1678 strcpy(szTitle,title.c_str());
1680 ofn.lpstrFile=szFilename;
1681 ofn.lpstrFileTitle=szTitle;
1683 if(GetOpenFileName(&ofn))
1685 filename=szFilename;
1691 synfig::String prev_path;
1692 if(!_preferences.get_value("curr_path",prev_path))
1695 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_OPEN);
1696 dialog->set_current_folder(prev_path);
1697 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1698 dialog->add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1699 if(!filename.empty())
1700 dialog->set_filename(filename);
1701 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1702 filename=dialog->get_filename();
1714 GtkWidget *fileselection;
1715 fileselection = gtk_file_selection_new(title.c_str());
1718 if(basename(filename)==filename)
1720 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
1723 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1725 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1727 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1728 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1730 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1731 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1733 gtk_widget_show(fileselection);
1741 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1742 _preferences.set_value("curr_path",dirname(filename));
1746 gtk_widget_destroy(fileselection);
1749 gtk_widget_destroy(fileselection);
1756 App::dialog_save_file(const std::string &title, std::string &filename)
1758 #ifdef USE_WIN32_FILE_DIALOGS
1759 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1761 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1762 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1763 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1765 ofn.lStructSize=sizeof(OPENFILENAME);
1766 ofn.hwndOwner = hWnd;
1767 ofn.hInstance = hInstance;
1768 ofn.lpstrFilter = szFilter;
1769 // ofn.lpstrCustomFilter=NULL;
1770 // ofn.nMaxCustFilter=0;
1771 // ofn.nFilterIndex=0;
1772 // ofn.lpstrFile=NULL;
1773 ofn.nMaxFile=MAX_PATH;
1774 // ofn.lpstrFileTitle=NULL;
1775 // ofn.lpstrInitialDir=NULL;
1776 // ofn.lpstrTitle=NULL;
1777 ofn.Flags=OFN_OVERWRITEPROMPT;
1778 // ofn.nFileOffset=0;
1779 // ofn.nFileExtension=0;
1780 ofn.lpstrDefExt=TEXT("sif");
1781 // ofn.lCustData = 0l;
1783 // ofn.lpTemplateName=NULL;
1785 CHAR szFilename[MAX_PATH];
1787 strcpy(szFilename,filename.c_str());
1788 strcpy(szTitle,title.c_str());
1790 ofn.lpstrFile=szFilename;
1791 ofn.lpstrFileTitle=szTitle;
1793 if(GetSaveFileName(&ofn))
1795 filename=szFilename;
1800 synfig::String prev_path;
1801 if(!_preferences.get_value("curr_path",prev_path))
1804 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1805 dialog->set_current_folder(prev_path);
1806 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1807 dialog->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1808 if(!filename.empty())
1809 dialog->set_filename(filename);
1810 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1811 filename=dialog->get_filename();
1817 // return dialog_open_file(title, filename);
1822 App::dialog_saveas_file(const std::string &title, std::string &filename)
1824 #if USE_WIN32_FILE_DIALOGS
1825 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1827 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1828 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1829 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1831 ofn.lStructSize=sizeof(OPENFILENAME);
1832 ofn.hwndOwner = hWnd;
1833 ofn.hInstance = hInstance;
1834 ofn.lpstrFilter = szFilter;
1835 // ofn.lpstrCustomFilter=NULL;
1836 // ofn.nMaxCustFilter=0;
1837 // ofn.nFilterIndex=0;
1838 // ofn.lpstrFile=NULL;
1839 ofn.nMaxFile=MAX_PATH;
1840 // ofn.lpstrFileTitle=NULL;
1841 // ofn.lpstrInitialDir=NULL;
1842 // ofn.lpstrTitle=NULL;
1843 ofn.Flags=OFN_OVERWRITEPROMPT;
1844 // ofn.nFileOffset=0;
1845 // ofn.nFileExtension=0;
1846 ofn.lpstrDefExt=TEXT("sif");
1847 // ofn.lCustData = 0l;
1849 // ofn.lpTemplateName=NULL;
1851 CHAR szFilename[MAX_PATH];
1853 strcpy(szFilename,filename.c_str());
1854 strcpy(szTitle,title.c_str());
1856 ofn.lpstrFile=szFilename;
1857 ofn.lpstrFileTitle=szTitle;
1859 if(GetSaveFileName(&ofn))
1861 filename=szFilename;
1866 synfig::String prev_path;
1867 if(!_preferences.get_value("curr_path",prev_path))
1870 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1871 dialog->set_current_folder(prev_path);
1872 dialog->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1873 dialog->add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1874 if(!filename.empty())
1875 dialog->set_filename(filename);
1876 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1877 filename=dialog->get_filename();
1883 // return dialog_open_file(title, filename);
1888 App::dialog_error_blocking(const std::string &title, const std::string &message)
1890 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
1891 dialog.set_title(title);
1897 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1899 Gtk::MessageDialog dialog(message, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_CLOSE, true);
1900 dialog.set_title(title);
1906 App::dialog_yes_no(const std::string &title, const std::string &message)
1911 true // use_separator
1913 Gtk::Label label(message);
1916 dialog.get_vbox()->pack_start(label);
1917 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1918 dialog.add_button(Gtk::StockID("gtk-no"),0);
1920 return dialog.run();
1924 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1929 true // use_separator
1931 Gtk::Label label(message);
1934 dialog.get_vbox()->pack_start(label);
1935 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1936 dialog.add_button(Gtk::StockID("gtk-no"),0);
1937 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1939 return dialog.run();
1943 App::dialog_not_implemented()
1945 Gtk::MessageDialog dialog("Feature not available", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
1946 dialog.set_secondary_text("Sorry, this feature has not yet been implemented.");
1951 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1956 true // use_separator
1958 Gtk::Label label(message);
1960 dialog.get_vbox()->pack_start(label);
1963 entry.set_text(text);
1965 entry.set_activates_default(true);
1966 dialog.get_vbox()->pack_start(entry);
1968 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1969 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1970 dialog.set_default_response(Gtk::RESPONSE_OK);
1971 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1974 if(dialog.run()!=Gtk::RESPONSE_OK)
1977 text=entry.get_text();
1986 App::open(std::string filename)
1988 return open_as(filename,filename);
1992 App::open_as(std::string filename,std::string as)
1995 char long_name[1024];
1996 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
2002 OneMoment one_moment;
2004 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
2005 if(canvas && get_instance(canvas))
2007 get_instance(canvas)->find_canvas_view(canvas)->present();
2008 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
2011 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
2013 add_recent_file(as);
2015 handle<Instance> instance(Instance::create(canvas));
2018 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
2022 if(instance->is_updated() && App::dialog_yes_no(_("CVS Update"), _("There appears to be a newer version of this file available on the CVS repository.\nWould you like to update now? (It would probably be a good idea)")))
2023 instance->dialog_cvs_update();
2027 dialog_error_blocking(_("Error"), x);
2032 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
2036 _preferences.set_value("curr_path",dirname(as));
2045 handle<synfig::Canvas> canvas=synfig::Canvas::create();
2046 canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
2048 String file_name(strprintf("untitled%d.sif",Instance::get_count()));
2050 canvas->rend_desc().set_frame_rate(24.0);
2051 canvas->rend_desc().set_time_start(0.0);
2052 canvas->rend_desc().set_time_end(00.0);
2053 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
2054 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
2055 canvas->rend_desc().set_tl(Vector(-4,2.25));
2056 canvas->rend_desc().set_br(Vector(4,-2.25));
2057 canvas->rend_desc().set_w(480);
2058 canvas->rend_desc().set_h(270);
2059 canvas->rend_desc().set_antialias(1);
2060 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
2061 canvas->set_file_name(file_name);
2063 Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
2069 string filename="*.sif";
2071 while(dialog_open_file("Open", filename))
2073 // If the filename still has wildcards, then we should
2074 // continue looking for the file we want
2075 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2081 get_ui_interface()->error(_("Unable to open file"));
2086 App::set_selected_instance(etl::loose_handle<Instance> instance)
2088 /* if(get_selected_instance()==instance)
2090 selected_instance=instance;
2091 signal_instance_selected()(instance);
2097 selected_instance=instance;
2098 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2102 instance->focus(instance->get_canvas());
2105 set_selected_canvas_view(0);
2107 signal_instance_selected()(instance);
2111 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2113 selected_canvas_view=canvas_view;
2114 signal_canvas_view_focus()(selected_canvas_view);
2117 selected_instance=canvas_view->get_instance();
2118 signal_instance_selected()(canvas_view->get_instance());
2121 if(get_selected_canvas_view()==canvas_view)
2123 signal_canvas_view_focus()(selected_canvas_view);
2124 signal_instance_selected()(canvas_view->get_instance());
2127 selected_canvas_view=canvas_view;
2128 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2129 set_selected_instance(canvas_view->get_instance());
2130 signal_canvas_view_focus()(selected_canvas_view);
2134 etl::loose_handle<Instance>
2135 App::get_instance(Canvas::Handle canvas)
2137 if(!canvas) return 0;
2138 canvas=canvas->get_root();
2140 std::list<etl::handle<Instance> >::iterator iter;
2141 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2143 if((*iter)->get_canvas()==canvas)
2152 (new class About())->show();
2158 if(selected_instance)
2159 selected_instance->undo();
2165 if(selected_instance)
2166 selected_instance->redo();
2170 studio::App::get_base_path()
2172 return app_base_path_;