1 /* === S Y N F I G ========================================================= */
5 ** $Id: app.cpp,v 1.11 2005/03/24 21:47:28 darco Exp $
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 ======================================================= */
35 #ifdef HAVE_SYS_ERRNO_H
36 #include <sys/errno.h>
38 #include <gtkmm/fileselection.h>
39 #include <gtkmm/dialog.h>
40 #include <gtkmm/label.h>
41 #include <gtkmm/stock.h>
42 #include <gtkmm/stockitem.h>
43 #include <gtkmm/iconsource.h>
44 #include <gtkmm/inputdialog.h>
45 #include <gtkmm/accelmap.h>
46 #include <gtkmm/uimanager.h>
50 #include <synfig/loadcanvas.h>
55 #include "canvasview.h"
56 #include "dialog_setup.h"
57 #include "dialog_gradient.h"
58 #include "dialog_color.h"
61 #include "onemoment.h"
63 #include "dockmanager.h"
65 #include "state_eyedrop.h"
66 #include "state_normal.h"
67 #include "state_draw.h"
68 #include "state_fill.h"
69 #include "state_bline.h"
70 #include "state_polygon.h"
71 #include "state_sketch.h"
72 #include "state_gradient.h"
73 #include "state_circle.h"
74 #include "state_rectangle.h"
75 #include "state_smoothmove.h"
76 #include "state_scale.h"
77 #include "state_width.h"
78 #include "state_rotate.h"
79 #include "state_zoom.h"
81 #include "devicetracker.h"
82 #include "dialog_tooloptions.h"
84 #include "autorecover.h"
86 #include <synfigapp/settings.h>
87 #include "dock_history.h"
88 #include "dock_canvases.h"
89 #include "dock_keyframes.h"
90 #include "dock_layers.h"
91 #include "dock_params.h"
92 #include "dock_metadata.h"
93 #include "dock_children.h"
94 #include "dock_info.h"
95 #include "dock_navigator.h"
96 #include "dock_layergroups.h"
97 #include "dock_timetrack.h"
98 #include "dock_curves.h"
100 #include "mod_palette/mod_palette.h"
101 #include "mod_mirror/mod_mirror.h"
103 #include <sys/stat.h>
109 #include "statemanager.h"
116 #define _WIN32_WINNT 0x0500
119 #include <gtkmm/accelmap.h>
120 #include <gtkmm/filechooser.h>
121 #include <gtkmm/filechooserdialog.h>
125 /* === U S I N G =========================================================== */
129 using namespace synfig;
130 using namespace studio;
132 /* === M A C R O S ========================================================= */
134 #ifndef SYNFIG_USER_APP_DIR
136 #define SYNFIG_USER_APP_DIR "Library/Synfig"
138 #define SYNFIG_USER_APP_DIR "Synfig"
143 #define DPM2DPI(x) (float(x)/39.3700787402f)
144 #define DPI2DPM(x) (float(x)*39.3700787402f)
150 # define IMAGE_DIR "share\\pixmaps"
155 # define IMAGE_DIR "/usr/local/share/pixmaps"
159 # define IMAGE_EXT "tif"
162 #include <synfigapp/main.h>
164 /* === S I G N A L S ======================================================= */
166 static sigc::signal<void> signal_present_all_;
168 App::signal_present_all() { return signal_present_all_; }
170 static sigc::signal<void> signal_recent_files_changed_;
172 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
174 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
175 sigc::signal<void,etl::loose_handle<CanvasView> >&
176 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
178 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
179 sigc::signal<void,etl::handle<Instance> >&
180 App::signal_instance_selected() { return signal_instance_selected_; }
182 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
183 sigc::signal<void,etl::handle<Instance> >&
184 App::signal_instance_created() { return signal_instance_created_; }
186 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
187 sigc::signal<void,etl::handle<Instance> >&
188 App::signal_instance_deleted() { return signal_instance_deleted_; }
190 /* === G L O B A L S ======================================================= */
192 static std::list<std::string> recent_files;
193 const std::list<std::string>& App::get_recent_files() { return recent_files; }
195 int App::Busy::count;
196 bool App::shutdown_in_progress;
198 synfig::Gamma App::gamma;
200 Glib::RefPtr<studio::UIManager> App::ui_manager_;
202 synfig::Distance::System App::distance_system;
204 studio::Dialog_Setup* App::dialog_setup;
206 etl::handle< studio::ModPalette > mod_palette_;
207 //studio::Dialog_Palette* App::dialog_palette;
209 std::list<etl::handle<Instance> > App::instance_list;
211 static etl::handle<synfigapp::UIInterface> ui_interface_;
212 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
214 etl::handle<Instance> App::selected_instance;
215 etl::handle<CanvasView> App::selected_canvas_view;
217 studio::Toolbox *studio::App::toolbox=NULL;
219 studio::AutoRecover *studio::App::auto_recover=NULL;
221 studio::IPC *ipc=NULL;
223 studio::DockManager* studio::App::dock_manager=0;
225 studio::DeviceTracker* studio::App::device_tracker=0;
227 studio::Dialog_Gradient* studio::App::dialog_gradient;
229 studio::Dialog_Color* studio::App::dialog_color;
231 Gtk::InputDialog* studio::App::dialog_input;
233 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
235 studio::Dock_History* dock_history;
236 studio::Dock_Canvases* dock_canvases;
237 studio::Dock_Keyframes* dock_keyframes;
238 studio::Dock_Layers* dock_layers;
239 studio::Dock_Params* dock_params;
240 studio::Dock_MetaData* dock_meta_data;
241 studio::Dock_Children* dock_children;
242 studio::Dock_Info* dock_info;
243 studio::Dock_LayerGroups* dock_layer_groups;
244 studio::Dock_Navigator* dock_navigator;
245 studio::Dock_Timetrack* dock_timetrack;
246 studio::Dock_Curves* dock_curves;
248 std::list< etl::handle< studio::Module > > module_list_;
250 bool studio::App::use_colorspace_gamma=true;
252 static int max_recent_files_=25;
253 int studio::App::get_max_recent_files() { return max_recent_files_; }
254 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
256 static synfig::String app_base_path_;
259 }; // END of namespace studio
260 studio::StateManager* state_manager;
265 class GlobalUIInterface : public synfigapp::UIInterface
269 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
274 true // use_separator
276 Gtk::Label label(message);
279 dialog.get_vbox()->pack_start(label);
280 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
281 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
283 dialog.set_default_response(dflt);
285 return (Response)dialog.run();
287 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
292 true // use_separator
294 Gtk::Label label(message);
297 dialog.get_vbox()->pack_start(label);
298 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
299 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
300 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
302 dialog.set_default_response(dflt);
304 return (Response)dialog.run();
306 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
311 true // use_separator
313 Gtk::Label label(message);
316 dialog.get_vbox()->pack_start(label);
317 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
318 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
320 dialog.set_default_response(dflt);
322 return (Response)dialog.run();
326 task(const std::string &task)
328 std::cerr<<task<<std::endl;
329 while(studio::App::events_pending())studio::App::iteration(false);
334 error(const std::string &err)
339 true // use_separator
341 Gtk::Label label(err);
344 dialog.get_vbox()->pack_start(label);
345 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
352 warning(const std::string &err)
354 std::cerr<<"warning: "<<err<<std::endl;
355 while(studio::App::events_pending())studio::App::iteration(false);
360 amount_complete(int current, int total)
362 while(studio::App::events_pending())studio::App::iteration(false);
367 /* === P R O C E D U R E S ================================================= */
369 typedef unsigned char U8;
370 typedef unsigned short U16;
371 typedef unsigned long U32;
381 static inline U32 hash_U32(U32 i)
383 i=i*1664525+1013904223;
384 i=i*1664525+1013904223;
385 i=i*1664525+1013904223;
390 static const int endian_fix_table[8] = { 3, 2, 1, 0, 7, 6, 5, 4 } ;
391 #define endian_fix(x) (endian_fix_table[x])
393 #define endian_fix(x) (x)
396 int v_unwind_key(V_KeyUnwound* unwound, const char* key)
399 unwound->element.serial=0;
400 unwound->element.checksum=0;
408 case '0': data=0; break;
409 case '1': data=1; break;
410 case '2': data=2; break;
411 case '3': data=3; break;
412 case '4': data=4; break;
413 case '5': data=5; break;
414 case '6': data=6; break;
415 case '7': data=7; break;
416 case '8': data=8; break;
417 case '9': data=9; break;
418 case 'a': case 'A': data=10; break;
419 case 'b': case 'B': data=11; break;
420 case 'c': case 'C': data=12; break;
421 case 'd': case 'D': data=13; break;
422 case 'e': case 'E': data=14; break;
423 case 'f': case 'F': data=15; break;
424 default: return 0; break;
427 unwound->element.checksum|=(((U32)data&3)<<bit);
428 unwound->element.serial|=(((U32)(data>>2)&3)<<bit);
433 int v_key_check(const char* key, U32* serial, U32 appid)
435 V_KeyUnwound unwound_key;
436 U32 appid_mask_a=hash_U32(appid);
437 U32 appid_mask_b=hash_U32(appid_mask_a);
439 if(!v_unwind_key(&unwound_key, key))
441 // Invalid characters in key
446 // Undo obfuscation pass
448 U32 next=hash_U32(unwound_key.raw[endian_fix(7)]);
453 unwound_key.raw[endian_fix(i)]^=(next>>24);
457 unwound_key.element.serial^=appid_mask_a;
458 unwound_key.element.checksum^=appid_mask_b;
460 *serial=unwound_key.element.serial;
462 return unwound_key.element.checksum==hash_U32(unwound_key.element.serial);
466 int check_license(String basedir)
468 #ifdef LICENSE_KEY_REQUIRED
473 license_file="/usr/local/etc/.synfiglicense";
475 license_file=basedir+"\\etc\\.synfiglicense";
479 key=Glib::file_get_contents(license_file);
480 } catch (Glib::FileError) { }
482 if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
484 while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
488 if(!App::dialog_entry(
489 _("Synfig Studio Authentication"),
490 _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
493 throw String("No License");
496 FILE* file=fopen(license_file.c_str(),"w");
499 fprintf(file,"%s",key.c_str());
503 synfig::error("Unable to save license key!");
505 synfig::info("License Authenticated -- Serial #%05d",serial);
514 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
516 action_group_list.push_back(action_group);
517 Gtk::UIManager::insert_action_group(action_group, pos);
521 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
523 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
524 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
525 if(*iter==action_group)
527 action_group_list.erase(iter);
528 Gtk::UIManager::remove_action_group(action_group);
531 synfig::error("Unable to find action group");
535 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
537 ui_manager->insert_action_group(group,0);
540 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
541 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
544 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
547 if(*iter && (*iter)->get_name()!="menus")
549 synfig::info("Removing action group "+(*iter)->get_name());
550 ui_manager->remove_action_group(*iter);
554 ui_manager->insert_action_group(group,0);
557 for(;!prev_groups.empty();prev_groups.pop_front())
559 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
560 ui_manager->insert_action_group(prev_groups.front(),1);
565 class Preferences : public synfigapp::Settings
568 virtual bool get_value(const synfig::String& key, synfig::String& value)const
572 value=strprintf("%f %f %f %f",
573 App::gamma.get_gamma_r(),
574 App::gamma.get_gamma_g(),
575 App::gamma.get_gamma_b(),
576 App::gamma.get_black_level()
580 if(key=="time_format")
582 value=strprintf("%i",App::get_time_format());
585 if(key=="file_history.size")
587 value=strprintf("%i",App::get_max_recent_files());
590 if(key=="use_colorspace_gamma")
592 value=strprintf("%i",(int)App::use_colorspace_gamma);
595 if(key=="distance_system")
597 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
600 if(key=="auto_recover_backup_interval")
602 value=strprintf("%i",App::auto_recover->get_timeout());
606 return synfigapp::Settings::get_value(key,value);
609 virtual bool set_value(const synfig::String& key,const synfig::String& value)
615 strscanf(value,"%f %f %f %f",
622 App::gamma.set_all(r,g,b,blk);
626 if(key=="time_format")
628 int i(atoi(value.c_str()));
629 App::set_time_format(static_cast<synfig::Time::Format>(i));
632 if(key=="auto_recover_backup_interval")
634 int i(atoi(value.c_str()));
635 App::auto_recover->set_timeout(i);
638 if(key=="file_history.size")
640 int i(atoi(value.c_str()));
641 App::set_max_recent_files(i);
644 if(key=="use_colorspace_gamma")
646 int i(atoi(value.c_str()));
647 App::use_colorspace_gamma=i;
650 if(key=="distance_system")
652 App::distance_system=Distance::ident_system(value);;
656 return synfigapp::Settings::set_value(key,value);
659 virtual KeyList get_key_list()const
661 KeyList ret(synfigapp::Settings::get_key_list());
662 ret.push_back("gamma");
663 ret.push_back("time_format");
664 ret.push_back("distance_system");
665 ret.push_back("file_history.size");
666 ret.push_back("use_colorspace_gamma");
667 ret.push_back("auto_recover_backup_interval");
672 static ::Preferences _preferences;
677 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
679 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
681 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
683 menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
684 menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
685 menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
686 menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
687 menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
688 menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Mask Ducks") );
689 menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
690 menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") );
691 menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") );
692 menus_action_group->add( Gtk::Action::create("menu-group", "Group") );
693 menus_action_group->add( Gtk::Action::create("menu-state", "State") );
694 menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
696 // Add the synfigapp actions...
697 synfigapp::Action::Book::iterator iter;
698 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
700 actions_action_group->add(Gtk::Action::create(
701 "action-"+iter->second.name,
702 get_action_stock_id(iter->second),
703 iter->second.local_name,iter->second.local_name
707 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
708 #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); }
709 #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); }
711 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
712 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
713 DEFINE_ACTION("open", Gtk::Stock::OPEN);
714 DEFINE_ACTION("save", Gtk::Stock::SAVE);
715 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
716 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
717 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
718 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
719 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
720 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
721 DEFINE_ACTION("import", _("Import"));
722 DEFINE_ACTION("render", _("Render"));
723 DEFINE_ACTION("preview", _("Preview"));
724 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
725 DEFINE_ACTION("sound", _("Sound File"));
726 DEFINE_ACTION("options", _("Options"));
727 DEFINE_ACTION("close", _("Close"));
730 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
731 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
732 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
733 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
734 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
735 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
736 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
737 DEFINE_ACTION("properties", _("Properties"));
739 DEFINE_ACTION("mask-position-ducks", _("Mask Position Ducks"));
740 DEFINE_ACTION("mask-vertex-ducks", _("Mask Vertex Ducks"));
741 DEFINE_ACTION("mask-tangent-ducks", _("Mask Tangent Ducks"));
742 DEFINE_ACTION("mask-radius-ducks", _("Mask Radius Ducks"));
743 DEFINE_ACTION("mask-width-ducks", _("Mask Width Ducks"));
744 DEFINE_ACTION("mask-angle-ducks", _("Mask Angle Ducks"));
745 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
746 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
747 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
748 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
749 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
750 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
751 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
752 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
753 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
754 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
755 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
756 DEFINE_ACTION("play", _("Play"));
757 DEFINE_ACTION("pause", _("Pause"));
758 DEFINE_ACTION("stop", _("Stop"));
759 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
760 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
761 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
762 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
763 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
764 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
765 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
766 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
767 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
768 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
769 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
770 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
771 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
772 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
773 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
774 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
775 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
776 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
777 DEFINE_ACTION("seek-end", _("Seek to End"));
779 DEFINE_ACTION("action-group_add", _("Add group"));
781 DEFINE_ACTION("canvas-new", _("New Canvas"));
783 DEFINE_ACTION("amount-inc", _("Increase Amount"));
784 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
789 // Set up synfigapp actions
791 synfigapp::Action::Book::iterator iter;
793 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
795 Gtk::StockID stock_id;
797 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
799 //Gtk::Image* image(manage(new Gtk::Image()));
800 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
801 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
802 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
803 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
804 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
805 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
806 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
807 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
808 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
809 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
811 actions_action_group->add(Gtk::Action::create(
812 "action-"+iter->second.name,
814 iter->second.local_name,iter->second.local_name
822 Glib::ustring ui_info =
824 " <popup name='menu-toolbox' action='menu-toolbox'>"
825 " <menu action='menu-file'>"
828 " <popup name='menu-main' action='menu-main'>"
829 " <menu action='menu-file'>"
830 " <menuitem action='save' />"
831 " <menuitem action='save-as' />"
832 " <menuitem action='revert' />"
833 " <separator name='bleh01'/>"
834 " <menuitem action='cvs-add' />"
835 " <menuitem action='cvs-update' />"
836 " <menuitem action='cvs-commit' />"
837 " <menuitem action='cvs-revert' />"
838 " <separator name='bleh02'/>"
839 " <menuitem action='import' />"
840 " <separator name='bleh03'/>"
841 " <menuitem action='render' />"
842 " <menuitem action='preview' />"
843 " <menuitem action='sound' />"
844 " <separator name='bleh04'/>"
845 " <menuitem action='options' />"
846 " <menuitem action='close' />"
848 " <menu action='menu-edit'>"
849 " <menuitem action='undo'/>"
850 " <menuitem action='redo'/>"
851 " <separator name='bleh05'/>"
852 " <menuitem action='cut'/>"
853 " <menuitem action='copy'/>"
854 " <menuitem action='paste'/>"
855 " <separator name='bleh06'/>"
856 " <menuitem action='select-all-ducks'/>"
857 " <menuitem action='unselect-all-layers'/>"
858 " <separator name='bleh07'/>"
859 " <menuitem action='properties'/>"
861 " <menu action='menu-view'>"
862 " <menu action='menu-duck-mask'>"
863 " <menuitem action='mask-position-ducks' />"
864 " <menuitem action='mask-vertex-ducks' />"
865 " <menuitem action='mask-tangent-ducks' />"
866 " <menuitem action='mask-radius-ducks' />"
867 " <menuitem action='mask-width-ducks' />"
868 " <menuitem action='mask-angle-ducks' />"
870 " <menu action='menu-preview-quality'>"
871 " <menuitem action='quality-00' />"
872 " <menuitem action='quality-01' />"
873 " <menuitem action='quality-02' />"
874 " <menuitem action='quality-03' />"
875 " <menuitem action='quality-04' />"
876 " <menuitem action='quality-05' />"
877 " <menuitem action='quality-06' />"
878 " <menuitem action='quality-07' />"
879 " <menuitem action='quality-08' />"
880 " <menuitem action='quality-09' />"
881 " <menuitem action='quality-10' />"
883 " <separator name='bleh08'/>"
884 " <menuitem action='play'/>"
885 " <menuitem action='pause'/>"
886 " <menuitem action='stop'/>"
887 " <menuitem action='dialog-flipbook'/>"
888 " <separator name='bleh09'/>"
889 " <menuitem action='toggle-grid-show'/>"
890 " <menuitem action='toggle-grid-snap'/>"
891 " <menuitem action='toggle-guide-show'/>"
892 " <menuitem action='toggle-low-res'/>"
893 " <menuitem action='toggle-onion-skin'/>"
894 " <separator name='bleh10'/>"
895 " <menuitem action='canvas-zoom-in'/>"
896 " <menuitem action='canvas-zoom-out'/>"
897 " <menuitem action='canvas-zoom-fit'/>"
898 " <menuitem action='canvas-zoom-100'/>"
899 " <separator name='bleh11'/>"
900 " <menuitem action='time-zoom-in'/>"
901 " <menuitem action='time-zoom-out'/>"
902 " <separator name='bleh12'/>"
903 " <menuitem action='jump-next-keyframe'/>"
904 " <menuitem action='jump-prev-keyframe'/>"
905 " <menuitem action='seek-next-frame'/>"
906 " <menuitem action='seek-prev-frame'/>"
907 " <menuitem action='seek-next-second'/>"
908 " <menuitem action='seek-prev-second'/>"
909 " <menuitem action='seek-begin'/>"
910 " <menuitem action='seek-end'/>"
912 " <menu action='menu-canvas'>"
913 " <menuitem action='canvas-new'/>"
914 " <menuitem action='amount-inc'/>"
915 " <menuitem action='amount-dec'/>"
917 " <menu name='menu-state' action='menu-state'>"
919 " <menu action='menu-group'>"
920 " <menuitem action='action-group_add'/>"
922 " <menu action='menu-layer'>"
923 //" <menuitem action='cut'/>"
924 //" <menuitem action='copy'/>"
925 //" <menuitem action='paste'/>"
926 //" <separator name='bleh06'/>"
927 " <menu action='menu-layer-new'></menu>"
929 " <menu action='menu-keyframe'>"
930 " <menuitem action='keyframe-properties'/>"
937 " <menubar name='MenuBar'>"
938 " <menu action='MenuFile'>"
939 " <menuitem action='New'/>"
940 " <menuitem action='Open'/>"
942 " <menuitem action='Quit'/>"
944 " <menu action='MenuEdit'>"
945 " <menuitem action='Cut'/>"
946 " <menuitem action='Copy'/>"
947 " <menuitem action='Paste'/>"
950 " <toolbar name='ToolBar'>"
951 " <toolitem action='Open'/>"
952 " <toolitem action='Quit'/>"
958 actions_action_group->set_sensitive(false);
959 App::ui_manager()->set_add_tearoffs(true);
960 App::ui_manager()->insert_action_group(menus_action_group,1);
961 App::ui_manager()->insert_action_group(actions_action_group,1);
962 App::ui_manager()->add_ui_from_string(ui_info);
964 //App::ui_manager()->get_accel_group()->unlock();
966 catch(const Glib::Error& ex)
968 synfig::error("building menus and toolbars failed: " + ex.what());
971 // Add default keyboard accelerators
972 #define ACCEL(path,accel) { Gtk::AccelKey accel_key(accel,path); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
973 #define ACCEL2(accel) { Gtk::AccelKey accel_key(accel); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
974 ACCEL("<Actions>//select-all-ducks","<Control>a");
975 ACCEL("<Actions>//unselect-all-layers","<Control>d");
976 ACCEL("<Actions>//render","F9");
977 ACCEL("<Actions>//preview","F11");
978 ACCEL("<Actions>//properties","F8");
979 ACCEL("<Actions>//options","F12");
980 ACCEL("<Actions>//import","<control>i");
981 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
982 ACCEL("<Actions>//toggle-grid-show","<Control>g");
983 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
984 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
985 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
986 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
987 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
988 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
989 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
990 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
993 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
994 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
996 ACCEL("<Actions>//quality-01","<Control>1");
997 ACCEL("<Actions>//quality-02","<Control>2");
998 ACCEL("<Actions>//quality-03","<Control>3");
999 ACCEL("<Actions>//quality-04","<Control>4");
1000 ACCEL("<Actions>//quality-05","<Control>5");
1001 ACCEL("<Actions>//quality-06","<Control>6");
1002 ACCEL("<Actions>//quality-07","<Control>7");
1003 ACCEL("<Actions>//quality-08","<Control>8");
1004 ACCEL("<Actions>//quality-09","<Control>9");
1005 ACCEL("<Actions>//quality-10","<Control>0");
1006 ACCEL("<Actions>//undo","<Control>z");
1007 ACCEL("<Actions>//redo","<Control>r");
1008 ACCEL("<Actions>//action-layer_remove","Delete");
1010 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
1011 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
1012 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
1013 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
1014 ACCEL("<Actions>//time-zoom-in","+");
1015 ACCEL("<Actions>//time-zoom-out","_");
1017 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
1018 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
1020 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
1021 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
1022 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
1023 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
1024 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
1025 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
1026 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
1027 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
1028 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
1029 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
1030 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
1031 ACCEL("<Actions>//seek-begin","Home");
1032 ACCEL("<Actions>//seek-end","End");
1033 ACCEL("<Actions>//state-normal","<Mod1>a");
1034 ACCEL("<Actions>//state-rotate","<Mod1>s");
1035 ACCEL("<Actions>//state-scale","<Mod1>d");
1036 ACCEL("<Actions>//state-bline","<Mod1>b");
1037 ACCEL("<Actions>//state-fill","<Mod1>f");
1038 ACCEL("<Actions>//state-eyedrop","<Mod1>e");
1039 ACCEL("<Actions>//state-gradient","<Mod1>g");
1040 ACCEL("<Actions>//state-zoom","<Mod1>z");
1041 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1047 #define mkdir(x,y) mkdir(x)
1050 /* === M E T H O D S ======================================================= */
1052 App::App(int *argc, char ***argv):
1053 Gtk::Main(argc,argv),
1054 IconControler(etl::dirname((*argv)[0]))
1056 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1059 serial_=check_license(app_base_path_);
1062 ui_interface_=new GlobalUIInterface();
1066 Glib::thread_init();
1068 distance_system=Distance::SYSTEM_UNITS;
1070 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1073 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1077 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1085 if(!SYNFIG_CHECK_VERSION())
1087 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1088 dialog_error_blocking("SYNFIG Studio",
1089 "This copy of SYNFIG Studio was compiled against a\n"
1090 "different version of libsynfig than what is currently\n"
1091 "installed. Synfig Studio will now abort. Try downloading\n"
1092 "the latest version from the SYNFIG Development Website at\n"
1093 "http://dev.synfig.com/ "
1098 catch(synfig::SoftwareExpired)
1100 cerr<<"FATAL: Software Expired"<<endl;
1101 dialog_error_blocking("SYNFIG Studio",
1102 "This copy of SYNFIG Studio has expired.\n"
1103 "Please erase this copy, or download and\n"
1104 "install the latest copy from the SYNFIG\n"
1105 "Development Website at http://dev.synfig.com/ ."
1109 Glib::set_application_name(_("SYNFIG Studio"));
1112 about_window.set_can_self_destruct(false);
1113 about_window.show();
1115 shutdown_in_progress=false;
1116 SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
1117 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1119 // Initialize the Synfig library
1120 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1123 get_ui_interface()->error("Failed to initialize synfig!");
1127 // add the preferences to the settings
1128 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1132 studio_init_cb.task("Init UI Manager...");
1133 App::ui_manager_=studio::UIManager::create();
1136 studio_init_cb.task("Init Dock Manager...");
1137 dock_manager=new studio::DockManager();
1139 studio_init_cb.task("Init State Manager...");
1140 state_manager=new StateManager();
1142 studio_init_cb.task("Init Toolbox...");
1143 toolbox=new studio::Toolbox();
1145 studio_init_cb.task("Init Tool Options...");
1146 dialog_tool_options=new studio::Dialog_ToolOptions();
1147 dock_manager->register_dockable(*dialog_tool_options);
1149 studio_init_cb.task("Init History...");
1150 dock_history=new studio::Dock_History();
1151 dock_manager->register_dockable(*dock_history);
1153 studio_init_cb.task("Init Canvases...");
1154 dock_canvases=new studio::Dock_Canvases();
1155 dock_manager->register_dockable(*dock_canvases);
1157 studio_init_cb.task("Init Keyframes...");
1158 dock_keyframes=new studio::Dock_Keyframes();
1159 dock_manager->register_dockable(*dock_keyframes);
1161 studio_init_cb.task("Init Layers...");
1162 dock_layers=new studio::Dock_Layers();
1163 dock_manager->register_dockable(*dock_layers);
1165 studio_init_cb.task("Init Params...");
1166 dock_params=new studio::Dock_Params();
1167 dock_manager->register_dockable(*dock_params);
1169 studio_init_cb.task("Init MetaData...");
1170 dock_meta_data=new studio::Dock_MetaData();
1171 dock_manager->register_dockable(*dock_meta_data);
1173 studio_init_cb.task("Init Children...");
1174 dock_children=new studio::Dock_Children();
1175 dock_manager->register_dockable(*dock_children);
1177 studio_init_cb.task("Init Info...");
1178 dock_info = new studio::Dock_Info();
1179 dock_manager->register_dockable(*dock_info);
1181 studio_init_cb.task("Init Navigator...");
1182 dock_navigator = new studio::Dock_Navigator();
1183 dock_manager->register_dockable(*dock_navigator);
1185 studio_init_cb.task("Init Timetrack...");
1186 dock_timetrack = new studio::Dock_Timetrack();
1187 dock_manager->register_dockable(*dock_timetrack);
1189 studio_init_cb.task("Init Curve Editor...");
1190 dock_curves = new studio::Dock_Curves();
1191 dock_manager->register_dockable(*dock_curves);
1193 studio_init_cb.task("Init Layer Groups...");
1194 dock_layer_groups = new studio::Dock_LayerGroups();
1195 dock_manager->register_dockable(*dock_layer_groups);
1198 studio_init_cb.task("Init Color Dialog...");
1199 dialog_color=new studio::Dialog_Color();
1201 studio_init_cb.task("Init Gradient Dialog...");
1202 dialog_gradient=new studio::Dialog_Gradient();
1204 studio_init_cb.task("Init DeviceTracker...");
1205 device_tracker=new studio::DeviceTracker();
1207 studio_init_cb.task("Init Tools...");
1208 state_manager->add_state(&state_normal);
1209 state_manager->add_state(&state_smooth_move);
1210 state_manager->add_state(&state_scale);
1211 state_manager->add_state(&state_rotate);
1213 state_manager->add_state(&state_bline);
1214 state_manager->add_state(&state_polygon);
1215 state_manager->add_state(&state_circle);
1216 state_manager->add_state(&state_rectangle);
1218 state_manager->add_state(&state_draw);
1219 state_manager->add_state(&state_sketch);
1221 state_manager->add_state(&state_eyedrop);
1222 state_manager->add_state(&state_fill);
1224 state_manager->add_state(&state_width);
1225 state_manager->add_state(&state_gradient);
1227 state_manager->add_state(&state_zoom);
1229 studio_init_cb.task("Init ModPalette...");
1230 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1232 studio_init_cb.task("Init ModMirror...");
1233 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1236 studio_init_cb.task("Init Setup Dialog...");
1237 dialog_setup=new studio::Dialog_Setup();
1239 studio_init_cb.task("Init Input Dialog...");
1240 dialog_input=new Gtk::InputDialog();
1242 studio_init_cb.task("Init auto recovery...");
1243 auto_recover=new AutoRecover();
1245 studio_init_cb.amount_complete(9250,10000);
1246 studio_init_cb.task("Loading Settings...");
1248 studio_init_cb.task("Checking auto-recover...");
1250 studio_init_cb.amount_complete(9900,10000);
1252 if(auto_recover->recovery_needed())
1254 about_window.hide();
1256 get_ui_interface()->yes_no(
1258 "SYNFIG Studio seems to have crashed\n"
1259 "before you could save all your files.\n"
1260 "Would you like to re-open those files\n"
1261 "and recover your unsaved changes?"
1262 )==synfigapp::UIInterface::RESPONSE_YES
1265 if(!auto_recover->recover())
1267 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1270 get_ui_interface()->error(
1271 _("SYNFIG Studio has attempted to recover\n"
1272 "from a previous crash. The files that it has\n"
1273 "recovered are NOT YET SAVED. It would be a good\n"
1274 "idea to review them and save them now.")
1277 about_window.show();
1280 // Look for any files given on the command line,
1281 // and load them if found.
1282 for(;*argc>=1;(*argc)--)
1283 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1285 studio_init_cb.task("Loading files...");
1286 about_window.hide();
1287 open((*argv)[*argc]);
1288 about_window.show();
1291 studio_init_cb.task("Done.");
1292 studio_init_cb.amount_complete(10000,10000);
1298 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1302 StateManager* App::get_state_manager() { return state_manager; }
1306 shutdown_in_progress=true;
1310 synfigapp::Main::settings().remove_domain("pref");
1312 selected_instance=0;
1314 // Unload all of the modules
1315 for(;!module_list_.empty();module_list_.pop_back());
1317 delete state_manager;
1321 delete auto_recover;
1325 // studio::App::iteration(false);
1329 // studio::App::iteration(false);
1331 // studio::App::iteration(false);
1333 delete dialog_setup;
1335 delete dialog_gradient;
1337 delete dialog_color;
1339 delete dialog_input;
1341 delete dock_manager;
1343 instance_list.clear();
1345 // studio::App::iteration(false);
1349 App::get_user_app_directory()
1351 return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
1355 App::get_config_file(const synfig::String& file)
1357 return Glib::build_filename(get_user_app_directory(),file);
1361 App::add_recent_file(const std::string &file_name)
1363 std::string filename(file_name);
1365 assert(!filename.empty());
1367 if(filename.empty())
1370 // Toss out any "hidden" files
1371 if(basename(filename)[0]=='.')
1374 // If we aren't an absolute path, turn outselves into one
1375 if(!is_absolute_path(filename))
1376 filename=absolute_path(filename);
1378 list<string>::iterator iter;
1379 // Check to see if the file is already on the list.
1380 // If it is, then remove it from the list
1381 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1384 recent_files.erase(iter);
1389 // Push the filename to the front of the list
1390 recent_files.push_front(filename);
1392 // Clean out the files at the end of the list.
1393 while(recent_files.size()>(unsigned)get_max_recent_files())
1394 recent_files.pop_back();
1396 signal_recent_files_changed_();
1401 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1404 App::get_time_format()
1406 return _App_time_format;
1410 App::set_time_format(synfig::Time::Format x)
1417 App::save_settings()
1422 std::string filename=get_config_file("accelrc");
1423 Gtk::AccelMap::save(filename);
1426 std::string filename=get_config_file("recentfiles");
1428 std::ofstream file(filename.c_str());
1432 synfig::warning("Unable to save %s",filename.c_str());
1436 list<string>::reverse_iterator iter;
1438 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1442 std::string filename=get_config_file("settings");
1443 synfigapp::Main::settings().save_to_file(filename);
1447 synfig::warning("Caught exception when attempting to save settings.");
1452 App::load_settings()
1457 std::string filename=get_config_file("accelrc");
1458 Gtk::AccelMap::load(filename);
1461 std::string filename=get_config_file("recentfiles");
1463 std::ifstream file(filename.c_str());
1467 std::string recent_file;
1468 getline(file,recent_file);
1469 if(!recent_file.empty())
1470 add_recent_file(recent_file);
1473 std::string filename=get_config_file("settings");
1474 if(!synfigapp::Main::settings().load_from_file(filename))
1476 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1477 //if(!synfigapp::Main::settings().load_from_file(filename))
1479 gamma.set_gamma(1.0/2.2);
1480 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1481 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1482 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1483 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1484 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1485 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1486 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1487 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1488 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1489 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1490 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1491 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1492 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1499 synfig::warning("Caught exception when attempting to load settings.");
1504 App::shutdown_request(GdkEventAny*)
1508 //return !shutdown_in_progress;
1514 if(shutdown_in_progress)return;
1517 get_ui_interface()->task("Quit Request");
1520 dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
1524 std::list<etl::handle<Instance> >::iterator iter;
1525 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1527 if(!(*iter)->safe_close())
1531 if((*iter)->synfigapp::Instance::get_action_count())
1533 handle<synfigapp::UIInterface> uim;
1534 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1536 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1537 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1539 case synfigapp::UIInterface::RESPONSE_NO:
1541 case synfigapp::UIInterface::RESPONSE_YES:
1544 case synfigapp::UIInterface::RESPONSE_CANCEL:
1553 if((*iter)->synfigapp::Instance::is_modified())
1555 handle<synfigapp::UIInterface> uim;
1556 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1558 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() );
1559 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1561 case synfigapp::UIInterface::RESPONSE_NO:
1563 case synfigapp::UIInterface::RESPONSE_YES:
1564 (*iter)->dialog_cvs_commit();
1566 case synfigapp::UIInterface::RESPONSE_CANCEL:
1575 // This next line causes things to crash for some reason
1579 shutdown_in_progress=true;
1581 instance_list.clear();
1583 while(studio::App::events_pending())studio::App::iteration(false);
1586 auto_recover->normal_shutdown();
1588 get_ui_interface()->task("Quit Request sent");
1594 dialog_setup->refresh();
1595 dialog_setup->show();
1598 gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
1599 gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
1602 //#define USE_WIN32_FILE_DIALOGS 1
1605 #ifdef USE_WIN32_FILE_DIALOGS
1606 static OPENFILENAME ofn={};
1610 #include <gdk/gdkwin32.h>
1614 App::dialog_open_file(const std::string &title, std::string &filename)
1616 #ifdef USE_WIN32_FILE_DIALOGS
1617 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1619 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1620 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1621 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1623 ofn.lStructSize=sizeof(OPENFILENAME);
1624 ofn.hwndOwner = hWnd;
1625 ofn.hInstance = hInstance;
1626 ofn.lpstrFilter = szFilter;
1627 // ofn.lpstrCustomFilter=NULL;
1628 // ofn.nMaxCustFilter=0;
1629 // ofn.nFilterIndex=0;
1630 // ofn.lpstrFile=NULL;
1631 ofn.nMaxFile=MAX_PATH;
1632 // ofn.lpstrFileTitle=NULL;
1633 // ofn.lpstrInitialDir=NULL;
1634 // ofn.lpstrTitle=NULL;
1635 ofn.Flags=OFN_HIDEREADONLY;
1636 // ofn.nFileOffset=0;
1637 // ofn.nFileExtension=0;
1638 ofn.lpstrDefExt=TEXT("sif");
1639 // ofn.lCustData = 0l;
1641 // ofn.lpTemplateName=NULL;
1643 CHAR szFilename[MAX_PATH];
1645 strcpy(szFilename,filename.c_str());
1646 strcpy(szTitle,title.c_str());
1648 ofn.lpstrFile=szFilename;
1649 ofn.lpstrFileTitle=szTitle;
1651 if(GetOpenFileName(&ofn))
1653 filename=szFilename;
1659 synfig::String prev_path;
1660 if(!_preferences.get_value("curr_path",prev_path))
1663 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_OPEN);
1664 dialog->set_current_folder(prev_path);
1665 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1666 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1667 if(!filename.empty())
1668 dialog->set_filename(filename);
1669 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1670 filename=dialog->get_filename();
1682 GtkWidget *fileselection;
1683 fileselection = gtk_file_selection_new(title.c_str());
1686 if(basename(filename)==filename)
1688 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
1691 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1693 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1695 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1696 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1698 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1699 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1701 gtk_widget_show(fileselection);
1709 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1710 _preferences.set_value("curr_path",dirname(filename));
1714 gtk_widget_destroy(fileselection);
1717 gtk_widget_destroy(fileselection);
1724 App::dialog_save_file(const std::string &title, std::string &filename)
1726 #ifdef USE_WIN32_FILE_DIALOGS
1727 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1729 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1730 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1731 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1733 ofn.lStructSize=sizeof(OPENFILENAME);
1734 ofn.hwndOwner = hWnd;
1735 ofn.hInstance = hInstance;
1736 ofn.lpstrFilter = szFilter;
1737 // ofn.lpstrCustomFilter=NULL;
1738 // ofn.nMaxCustFilter=0;
1739 // ofn.nFilterIndex=0;
1740 // ofn.lpstrFile=NULL;
1741 ofn.nMaxFile=MAX_PATH;
1742 // ofn.lpstrFileTitle=NULL;
1743 // ofn.lpstrInitialDir=NULL;
1744 // ofn.lpstrTitle=NULL;
1745 ofn.Flags=OFN_OVERWRITEPROMPT;
1746 // ofn.nFileOffset=0;
1747 // ofn.nFileExtension=0;
1748 ofn.lpstrDefExt=TEXT("sif");
1749 // ofn.lCustData = 0l;
1751 // ofn.lpTemplateName=NULL;
1753 CHAR szFilename[MAX_PATH];
1755 strcpy(szFilename,filename.c_str());
1756 strcpy(szTitle,title.c_str());
1758 ofn.lpstrFile=szFilename;
1759 ofn.lpstrFileTitle=szTitle;
1761 if(GetSaveFileName(&ofn))
1763 filename=szFilename;
1768 synfig::String prev_path;
1769 if(!_preferences.get_value("curr_path",prev_path))
1772 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1773 dialog->set_current_folder(prev_path);
1774 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1775 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1776 if(!filename.empty())
1777 dialog->set_filename(filename);
1778 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1779 filename=dialog->get_filename();
1785 // return dialog_open_file(title, filename);
1790 App::dialog_saveas_file(const std::string &title, std::string &filename)
1792 #if USE_WIN32_FILE_DIALOGS
1793 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1795 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1796 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1797 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1799 ofn.lStructSize=sizeof(OPENFILENAME);
1800 ofn.hwndOwner = hWnd;
1801 ofn.hInstance = hInstance;
1802 ofn.lpstrFilter = szFilter;
1803 // ofn.lpstrCustomFilter=NULL;
1804 // ofn.nMaxCustFilter=0;
1805 // ofn.nFilterIndex=0;
1806 // ofn.lpstrFile=NULL;
1807 ofn.nMaxFile=MAX_PATH;
1808 // ofn.lpstrFileTitle=NULL;
1809 // ofn.lpstrInitialDir=NULL;
1810 // ofn.lpstrTitle=NULL;
1811 ofn.Flags=OFN_OVERWRITEPROMPT;
1812 // ofn.nFileOffset=0;
1813 // ofn.nFileExtension=0;
1814 ofn.lpstrDefExt=TEXT("sif");
1815 // ofn.lCustData = 0l;
1817 // ofn.lpTemplateName=NULL;
1819 CHAR szFilename[MAX_PATH];
1821 strcpy(szFilename,filename.c_str());
1822 strcpy(szTitle,title.c_str());
1824 ofn.lpstrFile=szFilename;
1825 ofn.lpstrFileTitle=szTitle;
1827 if(GetSaveFileName(&ofn))
1829 filename=szFilename;
1834 synfig::String prev_path;
1835 if(!_preferences.get_value("curr_path",prev_path))
1838 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1839 dialog->set_current_folder(prev_path);
1840 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1841 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1842 if(!filename.empty())
1843 dialog->set_filename(filename);
1844 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1845 filename=dialog->get_filename();
1851 // return dialog_open_file(title, filename);
1856 App::dialog_error_blocking(const std::string &title, const std::string &message)
1861 true // use_separator
1863 Gtk::Label label(message);
1866 dialog.get_vbox()->pack_start(label);
1867 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1873 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1878 true // use_separator
1880 Gtk::Label label(message);
1883 dialog.get_vbox()->pack_start(label);
1884 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1890 App::dialog_yes_no(const std::string &title, const std::string &message)
1895 true // use_separator
1897 Gtk::Label label(message);
1900 dialog.get_vbox()->pack_start(label);
1901 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1902 dialog.add_button(Gtk::StockID("gtk-no"),0);
1904 return dialog.run();
1908 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1913 true // use_separator
1915 Gtk::Label label(message);
1918 dialog.get_vbox()->pack_start(label);
1919 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1920 dialog.add_button(Gtk::StockID("gtk-no"),0);
1921 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1923 return dialog.run();
1927 App::dialog_not_implemented()
1930 "Feature not available", // Title
1932 true // use_separator
1934 Gtk::Label label("Sorry, this feature has not yet been implemented.");
1937 dialog.get_vbox()->pack_start(label);
1938 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1944 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1949 true // use_separator
1951 Gtk::Label label(message);
1953 dialog.get_vbox()->pack_start(label);
1956 entry.set_text(text);
1958 entry.set_activates_default(true);
1959 dialog.get_vbox()->pack_start(entry);
1961 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1962 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1963 dialog.set_default_response(Gtk::RESPONSE_OK);
1964 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1967 if(dialog.run()!=Gtk::RESPONSE_OK)
1970 text=entry.get_text();
1979 App::open(std::string filename)
1981 return open_as(filename,filename);
1985 App::open_as(std::string filename,std::string as)
1988 char long_name[1024];
1989 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
1995 OneMoment one_moment;
1997 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
1998 if(canvas && get_instance(canvas))
2000 get_instance(canvas)->find_canvas_view(canvas)->present();
2001 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
2004 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
2006 add_recent_file(as);
2008 handle<Instance> instance(Instance::create(canvas));
2011 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
2015 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)")))
2016 instance->dialog_cvs_update();
2020 dialog_error_blocking(_("Error"), x);
2025 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
2029 _preferences.set_value("curr_path",dirname(as));
2038 handle<synfig::Canvas> canvas=synfig::Canvas::create();
2039 canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
2041 String file_name(strprintf("untitled%d.sif",Instance::get_count()));
2043 canvas->rend_desc().set_frame_rate(24.0);
2044 canvas->rend_desc().set_time_start(0.0);
2045 canvas->rend_desc().set_time_end(00.0);
2046 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
2047 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
2048 canvas->rend_desc().set_tl(Vector(-4,2.25));
2049 canvas->rend_desc().set_br(Vector(4,-2.25));
2050 canvas->rend_desc().set_w(480);
2051 canvas->rend_desc().set_h(270);
2052 canvas->rend_desc().set_antialias(1);
2053 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
2054 canvas->set_file_name(file_name);
2056 Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
2062 string filename="*.sif";
2064 while(dialog_open_file("Open", filename))
2066 // If the filename still has wildcards, then we should
2067 // continue looking for the file we want
2068 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2074 get_ui_interface()->error(_("Unable to open file"));
2079 App::set_selected_instance(etl::loose_handle<Instance> instance)
2081 /* if(get_selected_instance()==instance)
2083 selected_instance=instance;
2084 signal_instance_selected()(instance);
2090 selected_instance=instance;
2091 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2095 instance->focus(instance->get_canvas());
2098 set_selected_canvas_view(0);
2100 signal_instance_selected()(instance);
2104 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2106 selected_canvas_view=canvas_view;
2107 signal_canvas_view_focus()(selected_canvas_view);
2110 selected_instance=canvas_view->get_instance();
2111 signal_instance_selected()(canvas_view->get_instance());
2114 if(get_selected_canvas_view()==canvas_view)
2116 signal_canvas_view_focus()(selected_canvas_view);
2117 signal_instance_selected()(canvas_view->get_instance());
2120 selected_canvas_view=canvas_view;
2121 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2122 set_selected_instance(canvas_view->get_instance());
2123 signal_canvas_view_focus()(selected_canvas_view);
2127 etl::loose_handle<Instance>
2128 App::get_instance(Canvas::Handle canvas)
2130 if(!canvas) return 0;
2131 canvas=canvas->get_root();
2133 std::list<etl::handle<Instance> >::iterator iter;
2134 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2136 if((*iter)->get_canvas()==canvas)
2145 (new class About())->show();
2151 if(selected_instance)
2152 selected_instance->undo();
2158 if(selected_instance)
2159 selected_instance->redo();
2163 studio::App::get_base_path()
2165 return app_base_path_;