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 ======================================================= */
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"
140 #define SYNFIG_USER_APP_DIR "Synfig"
145 #define DPM2DPI(x) (float(x)/39.3700787402f)
146 #define DPI2DPM(x) (float(x)*39.3700787402f)
152 # define IMAGE_DIR "share\\pixmaps"
157 # define IMAGE_DIR "/usr/local/share/pixmaps"
161 # define IMAGE_EXT "tif"
164 #include <synfigapp/main.h>
166 /* === S I G N A L S ======================================================= */
168 static sigc::signal<void> signal_present_all_;
170 App::signal_present_all() { return signal_present_all_; }
172 static sigc::signal<void> signal_recent_files_changed_;
174 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
176 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
177 sigc::signal<void,etl::loose_handle<CanvasView> >&
178 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
180 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
181 sigc::signal<void,etl::handle<Instance> >&
182 App::signal_instance_selected() { return signal_instance_selected_; }
184 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
185 sigc::signal<void,etl::handle<Instance> >&
186 App::signal_instance_created() { return signal_instance_created_; }
188 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
189 sigc::signal<void,etl::handle<Instance> >&
190 App::signal_instance_deleted() { return signal_instance_deleted_; }
192 /* === G L O B A L S ======================================================= */
194 static std::list<std::string> recent_files;
195 const std::list<std::string>& App::get_recent_files() { return recent_files; }
197 int App::Busy::count;
198 bool App::shutdown_in_progress;
200 synfig::Gamma App::gamma;
202 Glib::RefPtr<studio::UIManager> App::ui_manager_;
204 synfig::Distance::System App::distance_system;
206 studio::Dialog_Setup* App::dialog_setup;
208 etl::handle< studio::ModPalette > mod_palette_;
209 //studio::Dialog_Palette* App::dialog_palette;
211 std::list<etl::handle<Instance> > App::instance_list;
213 static etl::handle<synfigapp::UIInterface> ui_interface_;
214 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
216 etl::handle<Instance> App::selected_instance;
217 etl::handle<CanvasView> App::selected_canvas_view;
219 studio::Toolbox *studio::App::toolbox=NULL;
221 studio::AutoRecover *studio::App::auto_recover=NULL;
223 studio::IPC *ipc=NULL;
225 studio::DockManager* studio::App::dock_manager=0;
227 studio::DeviceTracker* studio::App::device_tracker=0;
229 studio::Dialog_Gradient* studio::App::dialog_gradient;
231 studio::Dialog_Color* studio::App::dialog_color;
233 Gtk::InputDialog* studio::App::dialog_input;
235 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
237 studio::Dock_History* dock_history;
238 studio::Dock_Canvases* dock_canvases;
239 studio::Dock_Keyframes* dock_keyframes;
240 studio::Dock_Layers* dock_layers;
241 studio::Dock_Params* dock_params;
242 studio::Dock_MetaData* dock_meta_data;
243 studio::Dock_Children* dock_children;
244 studio::Dock_Info* dock_info;
245 studio::Dock_LayerGroups* dock_layer_groups;
246 studio::Dock_Navigator* dock_navigator;
247 studio::Dock_Timetrack* dock_timetrack;
248 studio::Dock_Curves* dock_curves;
250 std::list< etl::handle< studio::Module > > module_list_;
252 bool studio::App::use_colorspace_gamma=true;
254 static int max_recent_files_=25;
255 int studio::App::get_max_recent_files() { return max_recent_files_; }
256 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
258 static synfig::String app_base_path_;
261 }; // END of namespace studio
262 studio::StateManager* state_manager;
267 class GlobalUIInterface : public synfigapp::UIInterface
271 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
276 true // use_separator
278 Gtk::Label label(message);
281 dialog.get_vbox()->pack_start(label);
282 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
283 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
285 dialog.set_default_response(dflt);
287 return (Response)dialog.run();
289 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
294 true // use_separator
296 Gtk::Label label(message);
299 dialog.get_vbox()->pack_start(label);
300 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
301 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
302 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
304 dialog.set_default_response(dflt);
306 return (Response)dialog.run();
308 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
313 true // use_separator
315 Gtk::Label label(message);
318 dialog.get_vbox()->pack_start(label);
319 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
320 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
322 dialog.set_default_response(dflt);
324 return (Response)dialog.run();
328 task(const std::string &task)
330 std::cerr<<task<<std::endl;
331 while(studio::App::events_pending())studio::App::iteration(false);
336 error(const std::string &err)
341 true // use_separator
343 Gtk::Label label(err);
346 dialog.get_vbox()->pack_start(label);
347 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
354 warning(const std::string &err)
356 std::cerr<<"warning: "<<err<<std::endl;
357 while(studio::App::events_pending())studio::App::iteration(false);
362 amount_complete(int current, int total)
364 while(studio::App::events_pending())studio::App::iteration(false);
369 /* === P R O C E D U R E S ================================================= */
371 typedef unsigned char U8;
372 typedef unsigned short U16;
373 typedef unsigned long U32;
383 static inline U32 hash_U32(U32 i)
385 i=i*1664525+1013904223;
386 i=i*1664525+1013904223;
387 i=i*1664525+1013904223;
392 static const int endian_fix_table[8] = { 3, 2, 1, 0, 7, 6, 5, 4 } ;
393 #define endian_fix(x) (endian_fix_table[x])
395 #define endian_fix(x) (x)
398 int v_unwind_key(V_KeyUnwound* unwound, const char* key)
401 unwound->element.serial=0;
402 unwound->element.checksum=0;
410 case '0': data=0; break;
411 case '1': data=1; break;
412 case '2': data=2; break;
413 case '3': data=3; break;
414 case '4': data=4; break;
415 case '5': data=5; break;
416 case '6': data=6; break;
417 case '7': data=7; break;
418 case '8': data=8; break;
419 case '9': data=9; break;
420 case 'a': case 'A': data=10; break;
421 case 'b': case 'B': data=11; break;
422 case 'c': case 'C': data=12; break;
423 case 'd': case 'D': data=13; break;
424 case 'e': case 'E': data=14; break;
425 case 'f': case 'F': data=15; break;
426 default: return 0; break;
429 unwound->element.checksum|=(((U32)data&3)<<bit);
430 unwound->element.serial|=(((U32)(data>>2)&3)<<bit);
435 int v_key_check(const char* key, U32* serial, U32 appid)
437 V_KeyUnwound unwound_key;
438 U32 appid_mask_a=hash_U32(appid);
439 U32 appid_mask_b=hash_U32(appid_mask_a);
441 if(!v_unwind_key(&unwound_key, key))
443 // Invalid characters in key
448 // Undo obfuscation pass
450 U32 next=hash_U32(unwound_key.raw[endian_fix(7)]);
455 unwound_key.raw[endian_fix(i)]^=(next>>24);
459 unwound_key.element.serial^=appid_mask_a;
460 unwound_key.element.checksum^=appid_mask_b;
462 *serial=unwound_key.element.serial;
464 return unwound_key.element.checksum==hash_U32(unwound_key.element.serial);
468 int check_license(String basedir)
470 #ifdef LICENSE_KEY_REQUIRED
475 license_file="/usr/local/etc/.synfiglicense";
477 license_file=basedir+"\\etc\\.synfiglicense";
481 key=Glib::file_get_contents(license_file);
482 } catch (Glib::FileError) { }
484 if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
486 while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
490 if(!App::dialog_entry(
491 _("Synfig Studio Authentication"),
492 _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
495 throw String("No License");
498 FILE* file=fopen(license_file.c_str(),"w");
501 fprintf(file,"%s",key.c_str());
505 synfig::error("Unable to save license key!");
507 synfig::info("License Authenticated -- Serial #%05d",serial);
516 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
518 action_group_list.push_back(action_group);
519 Gtk::UIManager::insert_action_group(action_group, pos);
523 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
525 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
526 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
527 if(*iter==action_group)
529 action_group_list.erase(iter);
530 Gtk::UIManager::remove_action_group(action_group);
533 synfig::error("Unable to find action group");
537 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
539 ui_manager->insert_action_group(group,0);
542 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
543 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
546 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
549 if(*iter && (*iter)->get_name()!="menus")
551 synfig::info("Removing action group "+(*iter)->get_name());
552 ui_manager->remove_action_group(*iter);
556 ui_manager->insert_action_group(group,0);
559 for(;!prev_groups.empty();prev_groups.pop_front())
561 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
562 ui_manager->insert_action_group(prev_groups.front(),1);
567 class Preferences : public synfigapp::Settings
570 virtual bool get_value(const synfig::String& key, synfig::String& value)const
574 value=strprintf("%f %f %f %f",
575 App::gamma.get_gamma_r(),
576 App::gamma.get_gamma_g(),
577 App::gamma.get_gamma_b(),
578 App::gamma.get_black_level()
582 if(key=="time_format")
584 value=strprintf("%i",App::get_time_format());
587 if(key=="file_history.size")
589 value=strprintf("%i",App::get_max_recent_files());
592 if(key=="use_colorspace_gamma")
594 value=strprintf("%i",(int)App::use_colorspace_gamma);
597 if(key=="distance_system")
599 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
602 if(key=="auto_recover_backup_interval")
604 value=strprintf("%i",App::auto_recover->get_timeout());
608 return synfigapp::Settings::get_value(key,value);
611 virtual bool set_value(const synfig::String& key,const synfig::String& value)
617 strscanf(value,"%f %f %f %f",
624 App::gamma.set_all(r,g,b,blk);
628 if(key=="time_format")
630 int i(atoi(value.c_str()));
631 App::set_time_format(static_cast<synfig::Time::Format>(i));
634 if(key=="auto_recover_backup_interval")
636 int i(atoi(value.c_str()));
637 App::auto_recover->set_timeout(i);
640 if(key=="file_history.size")
642 int i(atoi(value.c_str()));
643 App::set_max_recent_files(i);
646 if(key=="use_colorspace_gamma")
648 int i(atoi(value.c_str()));
649 App::use_colorspace_gamma=i;
652 if(key=="distance_system")
654 App::distance_system=Distance::ident_system(value);;
658 return synfigapp::Settings::set_value(key,value);
661 virtual KeyList get_key_list()const
663 KeyList ret(synfigapp::Settings::get_key_list());
664 ret.push_back("gamma");
665 ret.push_back("time_format");
666 ret.push_back("distance_system");
667 ret.push_back("file_history.size");
668 ret.push_back("use_colorspace_gamma");
669 ret.push_back("auto_recover_backup_interval");
674 static ::Preferences _preferences;
679 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
681 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
683 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
685 menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
686 menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
687 menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
688 menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
689 menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
690 menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Show/Hide Ducks") );
691 menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
692 menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") );
693 menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") );
694 menus_action_group->add( Gtk::Action::create("menu-group", "Group") );
695 menus_action_group->add( Gtk::Action::create("menu-state", "State") );
696 menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
698 // Add the synfigapp actions...
699 synfigapp::Action::Book::iterator iter;
700 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
702 actions_action_group->add(Gtk::Action::create(
703 "action-"+iter->second.name,
704 get_action_stock_id(iter->second),
705 iter->second.local_name,iter->second.local_name
709 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
710 #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); }
711 #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); }
713 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
714 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
715 DEFINE_ACTION("open", Gtk::Stock::OPEN);
716 DEFINE_ACTION("save", Gtk::Stock::SAVE);
717 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
718 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
719 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
720 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
721 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
722 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
723 DEFINE_ACTION("import", _("Import"));
724 DEFINE_ACTION("render", _("Render"));
725 DEFINE_ACTION("preview", _("Preview"));
726 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
727 DEFINE_ACTION("sound", _("Sound File"));
728 DEFINE_ACTION("options", _("Options"));
729 DEFINE_ACTION("close", _("Close"));
732 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
733 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
734 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
735 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
736 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
737 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
738 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
739 DEFINE_ACTION("properties", _("Properties"));
741 DEFINE_ACTION("mask-position-ducks", _("Show Position Ducks"));
742 DEFINE_ACTION("mask-vertex-ducks", _("Show Vertex Ducks"));
743 DEFINE_ACTION("mask-tangent-ducks", _("Show Tangent Ducks"));
744 DEFINE_ACTION("mask-radius-ducks", _("Show Radius Ducks"));
745 DEFINE_ACTION("mask-width-ducks", _("Show Width Ducks"));
746 DEFINE_ACTION("mask-angle-ducks", _("Show Angle Ducks"));
747 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
748 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
749 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
750 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
751 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
752 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
753 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
754 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
755 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
756 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
757 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
758 DEFINE_ACTION("play", _("Play"));
759 DEFINE_ACTION("pause", _("Pause"));
760 DEFINE_ACTION("stop", _("Stop"));
761 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
762 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
763 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
764 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
765 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
766 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
767 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
768 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
769 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
770 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
771 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
772 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
773 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
774 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
775 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
776 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
777 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
778 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
779 DEFINE_ACTION("seek-end", _("Seek to End"));
781 DEFINE_ACTION("action-group_add", _("Add group"));
783 DEFINE_ACTION("canvas-new", _("New Canvas"));
785 DEFINE_ACTION("amount-inc", _("Increase Amount"));
786 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
791 // Set up synfigapp actions
793 synfigapp::Action::Book::iterator iter;
795 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
797 Gtk::StockID stock_id;
799 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
801 //Gtk::Image* image(manage(new Gtk::Image()));
802 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
803 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
804 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
805 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
806 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
807 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
808 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
809 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
810 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
811 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
813 actions_action_group->add(Gtk::Action::create(
814 "action-"+iter->second.name,
816 iter->second.local_name,iter->second.local_name
824 Glib::ustring ui_info =
826 " <popup name='menu-toolbox' action='menu-toolbox'>"
827 " <menu action='menu-file'>"
830 " <popup name='menu-main' action='menu-main'>"
831 " <menu action='menu-file'>"
832 " <menuitem action='save' />"
833 " <menuitem action='save-as' />"
834 " <menuitem action='revert' />"
835 " <separator name='bleh01'/>"
836 " <menuitem action='cvs-add' />"
837 " <menuitem action='cvs-update' />"
838 " <menuitem action='cvs-commit' />"
839 " <menuitem action='cvs-revert' />"
840 " <separator name='bleh02'/>"
841 " <menuitem action='import' />"
842 " <separator name='bleh03'/>"
843 " <menuitem action='render' />"
844 " <menuitem action='preview' />"
845 " <menuitem action='sound' />"
846 " <separator name='bleh04'/>"
847 " <menuitem action='options' />"
848 " <menuitem action='close' />"
850 " <menu action='menu-edit'>"
851 " <menuitem action='undo'/>"
852 " <menuitem action='redo'/>"
853 " <separator name='bleh05'/>"
854 " <menuitem action='cut'/>"
855 " <menuitem action='copy'/>"
856 " <menuitem action='paste'/>"
857 " <separator name='bleh06'/>"
858 " <menuitem action='select-all-ducks'/>"
859 " <menuitem action='unselect-all-layers'/>"
860 " <separator name='bleh07'/>"
861 " <menuitem action='properties'/>"
863 " <menu action='menu-view'>"
864 " <menu action='menu-duck-mask'>"
865 " <menuitem action='mask-position-ducks' />"
866 " <menuitem action='mask-vertex-ducks' />"
867 " <menuitem action='mask-tangent-ducks' />"
868 " <menuitem action='mask-radius-ducks' />"
869 " <menuitem action='mask-width-ducks' />"
870 " <menuitem action='mask-angle-ducks' />"
872 " <menu action='menu-preview-quality'>"
873 " <menuitem action='quality-00' />"
874 " <menuitem action='quality-01' />"
875 " <menuitem action='quality-02' />"
876 " <menuitem action='quality-03' />"
877 " <menuitem action='quality-04' />"
878 " <menuitem action='quality-05' />"
879 " <menuitem action='quality-06' />"
880 " <menuitem action='quality-07' />"
881 " <menuitem action='quality-08' />"
882 " <menuitem action='quality-09' />"
883 " <menuitem action='quality-10' />"
885 " <separator name='bleh08'/>"
886 " <menuitem action='play'/>"
887 " <menuitem action='pause'/>"
888 " <menuitem action='stop'/>"
889 " <menuitem action='dialog-flipbook'/>"
890 " <separator name='bleh09'/>"
891 " <menuitem action='toggle-grid-show'/>"
892 " <menuitem action='toggle-grid-snap'/>"
893 " <menuitem action='toggle-guide-show'/>"
894 " <menuitem action='toggle-low-res'/>"
895 " <menuitem action='toggle-onion-skin'/>"
896 " <separator name='bleh10'/>"
897 " <menuitem action='canvas-zoom-in'/>"
898 " <menuitem action='canvas-zoom-out'/>"
899 " <menuitem action='canvas-zoom-fit'/>"
900 " <menuitem action='canvas-zoom-100'/>"
901 " <separator name='bleh11'/>"
902 " <menuitem action='time-zoom-in'/>"
903 " <menuitem action='time-zoom-out'/>"
904 " <separator name='bleh12'/>"
905 " <menuitem action='jump-next-keyframe'/>"
906 " <menuitem action='jump-prev-keyframe'/>"
907 " <menuitem action='seek-next-frame'/>"
908 " <menuitem action='seek-prev-frame'/>"
909 " <menuitem action='seek-next-second'/>"
910 " <menuitem action='seek-prev-second'/>"
911 " <menuitem action='seek-begin'/>"
912 " <menuitem action='seek-end'/>"
914 " <menu action='menu-canvas'>"
915 " <menuitem action='canvas-new'/>"
916 " <menuitem action='amount-inc'/>"
917 " <menuitem action='amount-dec'/>"
919 " <menu name='menu-state' action='menu-state'>"
921 " <menu action='menu-group'>"
922 " <menuitem action='action-group_add'/>"
924 " <menu action='menu-layer'>"
925 //" <menuitem action='cut'/>"
926 //" <menuitem action='copy'/>"
927 //" <menuitem action='paste'/>"
928 //" <separator name='bleh06'/>"
929 " <menu action='menu-layer-new'></menu>"
931 " <menu action='menu-keyframe'>"
932 " <menuitem action='keyframe-properties'/>"
939 " <menubar name='MenuBar'>"
940 " <menu action='MenuFile'>"
941 " <menuitem action='New'/>"
942 " <menuitem action='Open'/>"
944 " <menuitem action='Quit'/>"
946 " <menu action='MenuEdit'>"
947 " <menuitem action='Cut'/>"
948 " <menuitem action='Copy'/>"
949 " <menuitem action='Paste'/>"
952 " <toolbar name='ToolBar'>"
953 " <toolitem action='Open'/>"
954 " <toolitem action='Quit'/>"
960 actions_action_group->set_sensitive(false);
961 App::ui_manager()->set_add_tearoffs(true);
962 App::ui_manager()->insert_action_group(menus_action_group,1);
963 App::ui_manager()->insert_action_group(actions_action_group,1);
964 App::ui_manager()->add_ui_from_string(ui_info);
966 //App::ui_manager()->get_accel_group()->unlock();
968 catch(const Glib::Error& ex)
970 synfig::error("building menus and toolbars failed: " + ex.what());
973 // Add default keyboard accelerators
974 #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()); }
975 #define ACCEL2(accel) { Gtk::AccelKey accel_key(accel); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
976 ACCEL("<Actions>//select-all-ducks","<Control>a");
977 ACCEL("<Actions>//unselect-all-layers","<Control>d");
978 ACCEL("<Actions>//render","F9");
979 ACCEL("<Actions>//preview","F11");
980 ACCEL("<Actions>//properties","F8");
981 ACCEL("<Actions>//options","F12");
982 ACCEL("<Actions>//import","<control>i");
983 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
984 ACCEL("<Actions>//toggle-grid-show","<Control>g");
985 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
986 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
987 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
988 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
989 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
990 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
991 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
992 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
995 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
996 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
998 ACCEL("<Actions>//quality-01","<Control>1");
999 ACCEL("<Actions>//quality-02","<Control>2");
1000 ACCEL("<Actions>//quality-03","<Control>3");
1001 ACCEL("<Actions>//quality-04","<Control>4");
1002 ACCEL("<Actions>//quality-05","<Control>5");
1003 ACCEL("<Actions>//quality-06","<Control>6");
1004 ACCEL("<Actions>//quality-07","<Control>7");
1005 ACCEL("<Actions>//quality-08","<Control>8");
1006 ACCEL("<Actions>//quality-09","<Control>9");
1007 ACCEL("<Actions>//quality-10","<Control>0");
1008 ACCEL("<Actions>//undo","<Control>z");
1009 ACCEL("<Actions>//redo","<Control>r");
1010 ACCEL("<Actions>//action-layer_remove","Delete");
1012 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
1013 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
1014 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
1015 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
1016 ACCEL("<Actions>//time-zoom-in","+");
1017 ACCEL("<Actions>//time-zoom-out","_");
1019 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
1020 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
1022 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
1023 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
1024 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
1025 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
1026 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
1027 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
1028 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
1029 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
1030 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
1031 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
1032 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
1033 ACCEL("<Actions>//seek-begin","Home");
1034 ACCEL("<Actions>//seek-end","End");
1035 ACCEL("<Actions>//state-normal","<Mod1>a");
1036 ACCEL("<Actions>//state-rotate","<Mod1>s");
1037 ACCEL("<Actions>//state-scale","<Mod1>d");
1038 ACCEL("<Actions>//state-bline","<Mod1>b");
1039 ACCEL("<Actions>//state-fill","<Mod1>f");
1040 ACCEL("<Actions>//state-eyedrop","<Mod1>e");
1041 ACCEL("<Actions>//state-gradient","<Mod1>g");
1042 ACCEL("<Actions>//state-zoom","<Mod1>z");
1043 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1049 #define mkdir(x,y) mkdir(x)
1052 /* === M E T H O D S ======================================================= */
1054 App::App(int *argc, char ***argv):
1055 Gtk::Main(argc,argv),
1056 IconControler(etl::dirname((*argv)[0]))
1058 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1061 serial_=check_license(app_base_path_);
1064 ui_interface_=new GlobalUIInterface();
1068 Glib::thread_init();
1070 distance_system=Distance::SYSTEM_UNITS;
1072 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1075 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1079 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1087 if(!SYNFIG_CHECK_VERSION())
1089 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1090 dialog_error_blocking("SYNFIG Studio",
1091 "This copy of SYNFIG Studio was compiled against a\n"
1092 "different version of libsynfig than what is currently\n"
1093 "installed. Synfig Studio will now abort. Try downloading\n"
1094 "the latest version from the SYNFIG Development Website at\n"
1095 "http://dev.synfig.com/ "
1100 catch(synfig::SoftwareExpired)
1102 cerr<<"FATAL: Software Expired"<<endl;
1103 dialog_error_blocking("SYNFIG Studio",
1104 "This copy of SYNFIG Studio has expired.\n"
1105 "Please erase this copy, or download and\n"
1106 "install the latest copy from the SYNFIG\n"
1107 "Development Website at http://dev.synfig.com/ ."
1111 Glib::set_application_name(_("SYNFIG Studio"));
1114 about_window.set_can_self_destruct(false);
1115 about_window.show();
1117 shutdown_in_progress=false;
1118 SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
1119 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1121 // Initialize the Synfig library
1122 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1125 get_ui_interface()->error("Failed to initialize synfig!");
1129 // add the preferences to the settings
1130 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1134 studio_init_cb.task("Init UI Manager...");
1135 App::ui_manager_=studio::UIManager::create();
1138 studio_init_cb.task("Init Dock Manager...");
1139 dock_manager=new studio::DockManager();
1141 studio_init_cb.task("Init State Manager...");
1142 state_manager=new StateManager();
1144 studio_init_cb.task("Init Toolbox...");
1145 toolbox=new studio::Toolbox();
1147 studio_init_cb.task("Init Tool Options...");
1148 dialog_tool_options=new studio::Dialog_ToolOptions();
1149 dock_manager->register_dockable(*dialog_tool_options);
1151 studio_init_cb.task("Init History...");
1152 dock_history=new studio::Dock_History();
1153 dock_manager->register_dockable(*dock_history);
1155 studio_init_cb.task("Init Canvases...");
1156 dock_canvases=new studio::Dock_Canvases();
1157 dock_manager->register_dockable(*dock_canvases);
1159 studio_init_cb.task("Init Keyframes...");
1160 dock_keyframes=new studio::Dock_Keyframes();
1161 dock_manager->register_dockable(*dock_keyframes);
1163 studio_init_cb.task("Init Layers...");
1164 dock_layers=new studio::Dock_Layers();
1165 dock_manager->register_dockable(*dock_layers);
1167 studio_init_cb.task("Init Params...");
1168 dock_params=new studio::Dock_Params();
1169 dock_manager->register_dockable(*dock_params);
1171 studio_init_cb.task("Init MetaData...");
1172 dock_meta_data=new studio::Dock_MetaData();
1173 dock_manager->register_dockable(*dock_meta_data);
1175 studio_init_cb.task("Init Children...");
1176 dock_children=new studio::Dock_Children();
1177 dock_manager->register_dockable(*dock_children);
1179 studio_init_cb.task("Init Info...");
1180 dock_info = new studio::Dock_Info();
1181 dock_manager->register_dockable(*dock_info);
1183 studio_init_cb.task("Init Navigator...");
1184 dock_navigator = new studio::Dock_Navigator();
1185 dock_manager->register_dockable(*dock_navigator);
1187 studio_init_cb.task("Init Timetrack...");
1188 dock_timetrack = new studio::Dock_Timetrack();
1189 dock_manager->register_dockable(*dock_timetrack);
1191 studio_init_cb.task("Init Curve Editor...");
1192 dock_curves = new studio::Dock_Curves();
1193 dock_manager->register_dockable(*dock_curves);
1195 studio_init_cb.task("Init Layer Groups...");
1196 dock_layer_groups = new studio::Dock_LayerGroups();
1197 dock_manager->register_dockable(*dock_layer_groups);
1200 studio_init_cb.task("Init Color Dialog...");
1201 dialog_color=new studio::Dialog_Color();
1203 studio_init_cb.task("Init Gradient Dialog...");
1204 dialog_gradient=new studio::Dialog_Gradient();
1206 studio_init_cb.task("Init DeviceTracker...");
1207 device_tracker=new studio::DeviceTracker();
1209 studio_init_cb.task("Init Tools...");
1210 state_manager->add_state(&state_normal);
1211 state_manager->add_state(&state_smooth_move);
1212 state_manager->add_state(&state_scale);
1213 state_manager->add_state(&state_rotate);
1215 state_manager->add_state(&state_bline);
1218 state_manager->add_state(&state_circle);
1219 state_manager->add_state(&state_rectangle);
1221 state_manager->add_state(&state_gradient);
1222 state_manager->add_state(&state_eyedrop);
1223 state_manager->add_state(&state_fill);
1225 state_manager->add_state(&state_zoom);
1227 // Disabled this tool because it should be
1228 // considered deprecated. Use the bline tool instead.
1229 if(getenv("SYNFIG_ENABLE_POLYGON")) state_manager->add_state(&state_polygon);
1231 // These tools are disabled by default for now,
1232 // because they tend to confuse users.
1233 if(getenv("SYNFIG_ENABLE_DRAW" )) state_manager->add_state(&state_draw);
1234 if(getenv("SYNFIG_ENABLE_SKETCH")) state_manager->add_state(&state_sketch);
1235 if(getenv("SYNFIG_ENABLE_WIDTH" )) state_manager->add_state(&state_width);
1237 studio_init_cb.task("Init ModPalette...");
1238 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1240 studio_init_cb.task("Init ModMirror...");
1241 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1244 studio_init_cb.task("Init Setup Dialog...");
1245 dialog_setup=new studio::Dialog_Setup();
1247 studio_init_cb.task("Init Input Dialog...");
1248 dialog_input=new Gtk::InputDialog();
1250 studio_init_cb.task("Init auto recovery...");
1251 auto_recover=new AutoRecover();
1253 studio_init_cb.amount_complete(9250,10000);
1254 studio_init_cb.task("Loading Settings...");
1256 studio_init_cb.task("Checking auto-recover...");
1258 studio_init_cb.amount_complete(9900,10000);
1260 if(auto_recover->recovery_needed())
1262 about_window.hide();
1264 get_ui_interface()->yes_no(
1266 "SYNFIG Studio seems to have crashed\n"
1267 "before you could save all your files.\n"
1268 "Would you like to re-open those files\n"
1269 "and recover your unsaved changes?"
1270 )==synfigapp::UIInterface::RESPONSE_YES
1273 if(!auto_recover->recover())
1275 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1278 get_ui_interface()->error(
1279 _("SYNFIG Studio has attempted to recover\n"
1280 "from a previous crash. The files that it has\n"
1281 "recovered are NOT YET SAVED. It would be a good\n"
1282 "idea to review them and save them now.")
1285 about_window.show();
1288 // Look for any files given on the command line,
1289 // and load them if found.
1290 for(;*argc>=1;(*argc)--)
1291 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1293 studio_init_cb.task("Loading files...");
1294 about_window.hide();
1295 open((*argv)[*argc]);
1296 about_window.show();
1299 studio_init_cb.task("Done.");
1300 studio_init_cb.amount_complete(10000,10000);
1306 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1310 StateManager* App::get_state_manager() { return state_manager; }
1314 shutdown_in_progress=true;
1318 synfigapp::Main::settings().remove_domain("pref");
1320 selected_instance=0;
1322 // Unload all of the modules
1323 for(;!module_list_.empty();module_list_.pop_back());
1325 delete state_manager;
1329 delete auto_recover;
1333 // studio::App::iteration(false);
1337 // studio::App::iteration(false);
1339 // studio::App::iteration(false);
1341 delete dialog_setup;
1343 delete dialog_gradient;
1345 delete dialog_color;
1347 delete dialog_input;
1349 delete dock_manager;
1351 instance_list.clear();
1353 // studio::App::iteration(false);
1357 App::get_user_app_directory()
1359 return Glib::build_filename(Glib::get_home_dir(),SYNFIG_USER_APP_DIR);
1363 App::get_config_file(const synfig::String& file)
1365 return Glib::build_filename(get_user_app_directory(),file);
1369 App::add_recent_file(const std::string &file_name)
1371 std::string filename(file_name);
1373 assert(!filename.empty());
1375 if(filename.empty())
1378 // Toss out any "hidden" files
1379 if(basename(filename)[0]=='.')
1382 // If we aren't an absolute path, turn outselves into one
1383 if(!is_absolute_path(filename))
1384 filename=absolute_path(filename);
1386 list<string>::iterator iter;
1387 // Check to see if the file is already on the list.
1388 // If it is, then remove it from the list
1389 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1392 recent_files.erase(iter);
1397 // Push the filename to the front of the list
1398 recent_files.push_front(filename);
1400 // Clean out the files at the end of the list.
1401 while(recent_files.size()>(unsigned)get_max_recent_files())
1402 recent_files.pop_back();
1404 signal_recent_files_changed_();
1409 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1412 App::get_time_format()
1414 return _App_time_format;
1418 App::set_time_format(synfig::Time::Format x)
1425 App::save_settings()
1430 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1431 setlocale(LC_NUMERIC, "C");
1433 std::string filename=get_config_file("accelrc");
1434 Gtk::AccelMap::save(filename);
1437 std::string filename=get_config_file("recentfiles");
1439 std::ofstream file(filename.c_str());
1443 synfig::warning("Unable to save %s",filename.c_str());
1447 list<string>::reverse_iterator iter;
1449 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1453 std::string filename=get_config_file("settings");
1454 synfigapp::Main::settings().save_to_file(filename);
1455 setlocale(LC_NUMERIC,old_locale);
1459 synfig::warning("Caught exception when attempting to save settings.");
1464 App::load_settings()
1469 old_locale=strdup(setlocale(LC_NUMERIC, NULL));
1470 setlocale(LC_NUMERIC, "C");
1472 std::string filename=get_config_file("accelrc");
1473 Gtk::AccelMap::load(filename);
1476 std::string filename=get_config_file("recentfiles");
1478 std::ifstream file(filename.c_str());
1482 std::string recent_file;
1483 getline(file,recent_file);
1484 if(!recent_file.empty())
1485 add_recent_file(recent_file);
1488 std::string filename=get_config_file("settings");
1489 if(!synfigapp::Main::settings().load_from_file(filename))
1491 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1492 //if(!synfigapp::Main::settings().load_from_file(filename))
1494 gamma.set_gamma(1.0/2.2);
1495 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1496 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1497 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1498 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1499 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1500 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1501 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1502 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1503 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1504 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1505 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1506 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1507 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1510 setlocale(LC_NUMERIC,old_locale);
1514 synfig::warning("Caught exception when attempting to load settings.");
1519 App::shutdown_request(GdkEventAny*)
1523 //return !shutdown_in_progress;
1529 if(shutdown_in_progress)return;
1532 get_ui_interface()->task("Quit Request");
1535 dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
1539 std::list<etl::handle<Instance> >::iterator iter;
1540 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1542 if(!(*iter)->safe_close())
1546 if((*iter)->synfigapp::Instance::get_action_count())
1548 handle<synfigapp::UIInterface> uim;
1549 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1551 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1552 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1554 case synfigapp::UIInterface::RESPONSE_NO:
1556 case synfigapp::UIInterface::RESPONSE_YES:
1559 case synfigapp::UIInterface::RESPONSE_CANCEL:
1568 if((*iter)->synfigapp::Instance::is_modified())
1570 handle<synfigapp::UIInterface> uim;
1571 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1573 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() );
1574 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1576 case synfigapp::UIInterface::RESPONSE_NO:
1578 case synfigapp::UIInterface::RESPONSE_YES:
1579 (*iter)->dialog_cvs_commit();
1581 case synfigapp::UIInterface::RESPONSE_CANCEL:
1590 // This next line causes things to crash for some reason
1594 shutdown_in_progress=true;
1596 instance_list.clear();
1598 while(studio::App::events_pending())studio::App::iteration(false);
1601 auto_recover->normal_shutdown();
1603 get_ui_interface()->task("Quit Request sent");
1609 dialog_setup->refresh();
1610 dialog_setup->show();
1613 gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
1614 gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
1617 //#define USE_WIN32_FILE_DIALOGS 1
1620 #ifdef USE_WIN32_FILE_DIALOGS
1621 static OPENFILENAME ofn={};
1625 #include <gdk/gdkwin32.h>
1629 App::dialog_open_file(const std::string &title, std::string &filename)
1631 #ifdef USE_WIN32_FILE_DIALOGS
1632 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1634 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1635 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1636 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1638 ofn.lStructSize=sizeof(OPENFILENAME);
1639 ofn.hwndOwner = hWnd;
1640 ofn.hInstance = hInstance;
1641 ofn.lpstrFilter = szFilter;
1642 // ofn.lpstrCustomFilter=NULL;
1643 // ofn.nMaxCustFilter=0;
1644 // ofn.nFilterIndex=0;
1645 // ofn.lpstrFile=NULL;
1646 ofn.nMaxFile=MAX_PATH;
1647 // ofn.lpstrFileTitle=NULL;
1648 // ofn.lpstrInitialDir=NULL;
1649 // ofn.lpstrTitle=NULL;
1650 ofn.Flags=OFN_HIDEREADONLY;
1651 // ofn.nFileOffset=0;
1652 // ofn.nFileExtension=0;
1653 ofn.lpstrDefExt=TEXT("sif");
1654 // ofn.lCustData = 0l;
1656 // ofn.lpTemplateName=NULL;
1658 CHAR szFilename[MAX_PATH];
1660 strcpy(szFilename,filename.c_str());
1661 strcpy(szTitle,title.c_str());
1663 ofn.lpstrFile=szFilename;
1664 ofn.lpstrFileTitle=szTitle;
1666 if(GetOpenFileName(&ofn))
1668 filename=szFilename;
1674 synfig::String prev_path;
1675 if(!_preferences.get_value("curr_path",prev_path))
1678 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_OPEN);
1679 dialog->set_current_folder(prev_path);
1680 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1681 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1682 if(!filename.empty())
1683 dialog->set_filename(filename);
1684 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1685 filename=dialog->get_filename();
1697 GtkWidget *fileselection;
1698 fileselection = gtk_file_selection_new(title.c_str());
1701 if(basename(filename)==filename)
1703 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
1706 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1708 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1710 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1711 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1713 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1714 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1716 gtk_widget_show(fileselection);
1724 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1725 _preferences.set_value("curr_path",dirname(filename));
1729 gtk_widget_destroy(fileselection);
1732 gtk_widget_destroy(fileselection);
1739 App::dialog_save_file(const std::string &title, std::string &filename)
1741 #ifdef USE_WIN32_FILE_DIALOGS
1742 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1744 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1745 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1746 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1748 ofn.lStructSize=sizeof(OPENFILENAME);
1749 ofn.hwndOwner = hWnd;
1750 ofn.hInstance = hInstance;
1751 ofn.lpstrFilter = szFilter;
1752 // ofn.lpstrCustomFilter=NULL;
1753 // ofn.nMaxCustFilter=0;
1754 // ofn.nFilterIndex=0;
1755 // ofn.lpstrFile=NULL;
1756 ofn.nMaxFile=MAX_PATH;
1757 // ofn.lpstrFileTitle=NULL;
1758 // ofn.lpstrInitialDir=NULL;
1759 // ofn.lpstrTitle=NULL;
1760 ofn.Flags=OFN_OVERWRITEPROMPT;
1761 // ofn.nFileOffset=0;
1762 // ofn.nFileExtension=0;
1763 ofn.lpstrDefExt=TEXT("sif");
1764 // ofn.lCustData = 0l;
1766 // ofn.lpTemplateName=NULL;
1768 CHAR szFilename[MAX_PATH];
1770 strcpy(szFilename,filename.c_str());
1771 strcpy(szTitle,title.c_str());
1773 ofn.lpstrFile=szFilename;
1774 ofn.lpstrFileTitle=szTitle;
1776 if(GetSaveFileName(&ofn))
1778 filename=szFilename;
1783 synfig::String prev_path;
1784 if(!_preferences.get_value("curr_path",prev_path))
1787 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1788 dialog->set_current_folder(prev_path);
1789 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1790 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1791 if(!filename.empty())
1792 dialog->set_filename(filename);
1793 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1794 filename=dialog->get_filename();
1800 // return dialog_open_file(title, filename);
1805 App::dialog_saveas_file(const std::string &title, std::string &filename)
1807 #if USE_WIN32_FILE_DIALOGS
1808 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1810 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1811 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1812 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1814 ofn.lStructSize=sizeof(OPENFILENAME);
1815 ofn.hwndOwner = hWnd;
1816 ofn.hInstance = hInstance;
1817 ofn.lpstrFilter = szFilter;
1818 // ofn.lpstrCustomFilter=NULL;
1819 // ofn.nMaxCustFilter=0;
1820 // ofn.nFilterIndex=0;
1821 // ofn.lpstrFile=NULL;
1822 ofn.nMaxFile=MAX_PATH;
1823 // ofn.lpstrFileTitle=NULL;
1824 // ofn.lpstrInitialDir=NULL;
1825 // ofn.lpstrTitle=NULL;
1826 ofn.Flags=OFN_OVERWRITEPROMPT;
1827 // ofn.nFileOffset=0;
1828 // ofn.nFileExtension=0;
1829 ofn.lpstrDefExt=TEXT("sif");
1830 // ofn.lCustData = 0l;
1832 // ofn.lpTemplateName=NULL;
1834 CHAR szFilename[MAX_PATH];
1836 strcpy(szFilename,filename.c_str());
1837 strcpy(szTitle,title.c_str());
1839 ofn.lpstrFile=szFilename;
1840 ofn.lpstrFileTitle=szTitle;
1842 if(GetSaveFileName(&ofn))
1844 filename=szFilename;
1849 synfig::String prev_path;
1850 if(!_preferences.get_value("curr_path",prev_path))
1853 Gtk::FileChooserDialog *dialog=new Gtk::FileChooserDialog(title,Gtk::FILE_CHOOSER_ACTION_SAVE);
1854 dialog->set_current_folder(prev_path);
1855 dialog->add_button(Gtk::StockID("gtk-ok"),GTK_RESPONSE_ACCEPT);
1856 dialog->add_button(Gtk::StockID("gtk-cancel"),GTK_RESPONSE_CANCEL);
1857 if(!filename.empty())
1858 dialog->set_filename(filename);
1859 if(dialog->run()==GTK_RESPONSE_ACCEPT) {
1860 filename=dialog->get_filename();
1866 // return dialog_open_file(title, filename);
1871 App::dialog_error_blocking(const std::string &title, const std::string &message)
1876 true // use_separator
1878 Gtk::Label label(message);
1881 dialog.get_vbox()->pack_start(label);
1882 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1888 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1893 true // use_separator
1895 Gtk::Label label(message);
1898 dialog.get_vbox()->pack_start(label);
1899 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1905 App::dialog_yes_no(const std::string &title, const std::string &message)
1910 true // use_separator
1912 Gtk::Label label(message);
1915 dialog.get_vbox()->pack_start(label);
1916 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1917 dialog.add_button(Gtk::StockID("gtk-no"),0);
1919 return dialog.run();
1923 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1928 true // use_separator
1930 Gtk::Label label(message);
1933 dialog.get_vbox()->pack_start(label);
1934 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1935 dialog.add_button(Gtk::StockID("gtk-no"),0);
1936 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1938 return dialog.run();
1942 App::dialog_not_implemented()
1944 Gtk::MessageDialog dialog("Feature not available", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
1945 dialog.set_secondary_text("Sorry, this feature has not yet been implemented.");
1950 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1955 true // use_separator
1957 Gtk::Label label(message);
1959 dialog.get_vbox()->pack_start(label);
1962 entry.set_text(text);
1964 entry.set_activates_default(true);
1965 dialog.get_vbox()->pack_start(entry);
1967 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1968 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1969 dialog.set_default_response(Gtk::RESPONSE_OK);
1970 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1973 if(dialog.run()!=Gtk::RESPONSE_OK)
1976 text=entry.get_text();
1985 App::open(std::string filename)
1987 return open_as(filename,filename);
1991 App::open_as(std::string filename,std::string as)
1994 char long_name[1024];
1995 if(GetLongPathName(as.c_str(),long_name,sizeof(long_name)));
2001 OneMoment one_moment;
2003 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
2004 if(canvas && get_instance(canvas))
2006 get_instance(canvas)->find_canvas_view(canvas)->present();
2007 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
2010 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
2012 add_recent_file(as);
2014 handle<Instance> instance(Instance::create(canvas));
2017 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
2021 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)")))
2022 instance->dialog_cvs_update();
2026 dialog_error_blocking(_("Error"), x);
2031 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
2035 _preferences.set_value("curr_path",dirname(as));
2044 handle<synfig::Canvas> canvas=synfig::Canvas::create();
2045 canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
2047 String file_name(strprintf("untitled%d.sif",Instance::get_count()));
2049 canvas->rend_desc().set_frame_rate(24.0);
2050 canvas->rend_desc().set_time_start(0.0);
2051 canvas->rend_desc().set_time_end(00.0);
2052 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
2053 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
2054 canvas->rend_desc().set_tl(Vector(-4,2.25));
2055 canvas->rend_desc().set_br(Vector(4,-2.25));
2056 canvas->rend_desc().set_w(480);
2057 canvas->rend_desc().set_h(270);
2058 canvas->rend_desc().set_antialias(1);
2059 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
2060 canvas->set_file_name(file_name);
2062 Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
2068 string filename="*.sif";
2070 while(dialog_open_file("Open", filename))
2072 // If the filename still has wildcards, then we should
2073 // continue looking for the file we want
2074 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2080 get_ui_interface()->error(_("Unable to open file"));
2085 App::set_selected_instance(etl::loose_handle<Instance> instance)
2087 /* if(get_selected_instance()==instance)
2089 selected_instance=instance;
2090 signal_instance_selected()(instance);
2096 selected_instance=instance;
2097 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2101 instance->focus(instance->get_canvas());
2104 set_selected_canvas_view(0);
2106 signal_instance_selected()(instance);
2110 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2112 selected_canvas_view=canvas_view;
2113 signal_canvas_view_focus()(selected_canvas_view);
2116 selected_instance=canvas_view->get_instance();
2117 signal_instance_selected()(canvas_view->get_instance());
2120 if(get_selected_canvas_view()==canvas_view)
2122 signal_canvas_view_focus()(selected_canvas_view);
2123 signal_instance_selected()(canvas_view->get_instance());
2126 selected_canvas_view=canvas_view;
2127 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2128 set_selected_instance(canvas_view->get_instance());
2129 signal_canvas_view_focus()(selected_canvas_view);
2133 etl::loose_handle<Instance>
2134 App::get_instance(Canvas::Handle canvas)
2136 if(!canvas) return 0;
2137 canvas=canvas->get_root();
2139 std::list<etl::handle<Instance> >::iterator iter;
2140 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2142 if((*iter)->get_canvas()==canvas)
2151 (new class About())->show();
2157 if(selected_instance)
2158 selected_instance->undo();
2164 if(selected_instance)
2165 selected_instance->redo();
2169 studio::App::get_base_path()
2171 return app_base_path_;