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 #include <gtkmm/fileselection.h>
36 #include <gtkmm/dialog.h>
37 #include <gtkmm/label.h>
38 #include <gtkmm/stock.h>
39 #include <gtkmm/stockitem.h>
40 #include <gtkmm/iconsource.h>
41 #include <gtkmm/inputdialog.h>
42 #include <gtkmm/accelmap.h>
43 #include <gtkmm/uimanager.h>
47 #include <synfig/loadcanvas.h>
52 #include "canvasview.h"
53 #include "dialog_setup.h"
54 #include "dialog_gradient.h"
55 #include "dialog_color.h"
58 #include "onemoment.h"
60 #include "dockmanager.h"
62 #include "state_eyedrop.h"
63 #include "state_normal.h"
64 #include "state_draw.h"
65 #include "state_fill.h"
66 #include "state_bline.h"
67 #include "state_polygon.h"
68 #include "state_sketch.h"
69 #include "state_gradient.h"
70 #include "state_circle.h"
71 #include "state_rectangle.h"
72 #include "state_smoothmove.h"
73 #include "state_scale.h"
74 #include "state_width.h"
75 #include "state_rotate.h"
76 #include "state_zoom.h"
78 #include "devicetracker.h"
79 #include "dialog_tooloptions.h"
81 #include "autorecover.h"
83 #include <synfigapp/settings.h>
84 #include "dock_history.h"
85 #include "dock_canvases.h"
86 #include "dock_keyframes.h"
87 #include "dock_layers.h"
88 #include "dock_params.h"
89 #include "dock_metadata.h"
90 #include "dock_children.h"
91 #include "dock_info.h"
92 #include "dock_navigator.h"
93 #include "dock_layergroups.h"
94 #include "dock_timetrack.h"
95 #include "dock_curves.h"
97 #include "mod_palette/mod_palette.h"
98 #include "mod_mirror/mod_mirror.h"
100 #include <sys/stat.h>
106 #include "statemanager.h"
115 #include <gtkmm/accelmap.h>
119 /* === U S I N G =========================================================== */
123 using namespace synfig;
124 using namespace studio;
126 /* === M A C R O S ========================================================= */
129 #define DPM2DPI(x) (float(x)/39.3700787402f)
130 #define DPI2DPM(x) (float(x)*39.3700787402f)
136 # define IMAGE_DIR "share\\pixmaps"
141 # define IMAGE_DIR "/usr/local/share/pixmaps"
145 # define IMAGE_EXT "tif"
148 #include <synfigapp/main.h>
150 /* === S I G N A L S ======================================================= */
152 static sigc::signal<void> signal_present_all_;
154 App::signal_present_all() { return signal_present_all_; }
156 static sigc::signal<void> signal_recent_files_changed_;
158 App::signal_recent_files_changed() { return signal_recent_files_changed_; }
160 static sigc::signal<void,etl::loose_handle<CanvasView> > signal_canvas_view_focus_;
161 sigc::signal<void,etl::loose_handle<CanvasView> >&
162 App::signal_canvas_view_focus() { return signal_canvas_view_focus_; }
164 static sigc::signal<void,etl::handle<Instance> > signal_instance_selected_;
165 sigc::signal<void,etl::handle<Instance> >&
166 App::signal_instance_selected() { return signal_instance_selected_; }
168 static sigc::signal<void,etl::handle<Instance> > signal_instance_created_;
169 sigc::signal<void,etl::handle<Instance> >&
170 App::signal_instance_created() { return signal_instance_created_; }
172 static sigc::signal<void,etl::handle<Instance> > signal_instance_deleted_;
173 sigc::signal<void,etl::handle<Instance> >&
174 App::signal_instance_deleted() { return signal_instance_deleted_; }
176 /* === G L O B A L S ======================================================= */
178 static std::list<std::string> recent_files;
179 const std::list<std::string>& App::get_recent_files() { return recent_files; }
181 int App::Busy::count;
182 bool App::shutdown_in_progress;
184 synfig::Gamma App::gamma;
186 Glib::RefPtr<studio::UIManager> App::ui_manager_;
188 synfig::Distance::System App::distance_system;
190 studio::Dialog_Setup* App::dialog_setup;
192 etl::handle< studio::ModPalette > mod_palette_;
193 //studio::Dialog_Palette* App::dialog_palette;
195 std::list<etl::handle<Instance> > App::instance_list;
197 static etl::handle<synfigapp::UIInterface> ui_interface_;
198 const etl::handle<synfigapp::UIInterface>& App::get_ui_interface() { return ui_interface_; }
200 etl::handle<Instance> App::selected_instance;
201 etl::handle<CanvasView> App::selected_canvas_view;
203 studio::Toolbox *studio::App::toolbox=NULL;
205 studio::AutoRecover *studio::App::auto_recover=NULL;
207 studio::IPC *ipc=NULL;
209 studio::DockManager* studio::App::dock_manager=0;
211 studio::DeviceTracker* studio::App::device_tracker=0;
213 studio::Dialog_Gradient* studio::App::dialog_gradient;
215 studio::Dialog_Color* studio::App::dialog_color;
217 Gtk::InputDialog* studio::App::dialog_input;
219 studio::Dialog_ToolOptions* studio::App::dialog_tool_options;
221 studio::Dock_History* dock_history;
222 studio::Dock_Canvases* dock_canvases;
223 studio::Dock_Keyframes* dock_keyframes;
224 studio::Dock_Layers* dock_layers;
225 studio::Dock_Params* dock_params;
226 studio::Dock_MetaData* dock_meta_data;
227 studio::Dock_Children* dock_children;
228 studio::Dock_Info* dock_info;
229 studio::Dock_LayerGroups* dock_layer_groups;
230 studio::Dock_Navigator* dock_navigator;
231 studio::Dock_Timetrack* dock_timetrack;
232 studio::Dock_Curves* dock_curves;
234 std::list< etl::handle< studio::Module > > module_list_;
236 bool studio::App::use_colorspace_gamma=true;
238 static int max_recent_files_=25;
239 int studio::App::get_max_recent_files() { return max_recent_files_; }
240 void studio::App::set_max_recent_files(int x) { max_recent_files_=x; }
242 static synfig::String app_base_path_;
245 }; // END of namespace studio
246 studio::StateManager* state_manager;
251 class GlobalUIInterface : public synfigapp::UIInterface
255 virtual Response yes_no(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
260 true // use_separator
262 Gtk::Label label(message);
265 dialog.get_vbox()->pack_start(label);
266 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
267 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
269 dialog.set_default_response(dflt);
271 return (Response)dialog.run();
273 virtual Response yes_no_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_YES)
278 true // use_separator
280 Gtk::Label label(message);
283 dialog.get_vbox()->pack_start(label);
284 dialog.add_button(Gtk::StockID("gtk-yes"),RESPONSE_YES);
285 dialog.add_button(Gtk::StockID("gtk-no"),RESPONSE_NO);
286 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
288 dialog.set_default_response(dflt);
290 return (Response)dialog.run();
292 virtual Response ok_cancel(const std::string &title, const std::string &message,Response dflt=RESPONSE_OK)
297 true // use_separator
299 Gtk::Label label(message);
302 dialog.get_vbox()->pack_start(label);
303 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
304 dialog.add_button(Gtk::StockID("gtk-cancel"),RESPONSE_CANCEL);
306 dialog.set_default_response(dflt);
308 return (Response)dialog.run();
312 task(const std::string &task)
314 std::cerr<<task<<std::endl;
315 while(studio::App::events_pending())studio::App::iteration(false);
320 error(const std::string &err)
325 true // use_separator
327 Gtk::Label label(err);
330 dialog.get_vbox()->pack_start(label);
331 dialog.add_button(Gtk::StockID("gtk-ok"),RESPONSE_OK);
338 warning(const std::string &err)
340 std::cerr<<"warning: "<<err<<std::endl;
341 while(studio::App::events_pending())studio::App::iteration(false);
346 amount_complete(int current, int total)
348 while(studio::App::events_pending())studio::App::iteration(false);
353 /* === P R O C E D U R E S ================================================= */
355 typedef unsigned char U8;
356 typedef unsigned short U16;
357 typedef unsigned long U32;
367 static inline U32 hash_U32(U32 i)
369 i=i*1664525+1013904223;
370 i=i*1664525+1013904223;
371 i=i*1664525+1013904223;
376 static const int endian_fix_table[8] = { 3, 2, 1, 0, 7, 6, 5, 4 } ;
377 #define endian_fix(x) (endian_fix_table[x])
379 #define endian_fix(x) (x)
382 int v_unwind_key(V_KeyUnwound* unwound, const char* key)
385 unwound->element.serial=0;
386 unwound->element.checksum=0;
394 case '0': data=0; break;
395 case '1': data=1; break;
396 case '2': data=2; break;
397 case '3': data=3; break;
398 case '4': data=4; break;
399 case '5': data=5; break;
400 case '6': data=6; break;
401 case '7': data=7; break;
402 case '8': data=8; break;
403 case '9': data=9; break;
404 case 'a': case 'A': data=10; break;
405 case 'b': case 'B': data=11; break;
406 case 'c': case 'C': data=12; break;
407 case 'd': case 'D': data=13; break;
408 case 'e': case 'E': data=14; break;
409 case 'f': case 'F': data=15; break;
410 default: return 0; break;
413 unwound->element.checksum|=(((U32)data&3)<<bit);
414 unwound->element.serial|=(((U32)(data>>2)&3)<<bit);
419 int v_key_check(const char* key, U32* serial, U32 appid)
421 V_KeyUnwound unwound_key;
422 U32 appid_mask_a=hash_U32(appid);
423 U32 appid_mask_b=hash_U32(appid_mask_a);
425 if(!v_unwind_key(&unwound_key, key))
427 // Invalid characters in key
432 // Undo obfuscation pass
434 U32 next=hash_U32(unwound_key.raw[endian_fix(7)]);
439 unwound_key.raw[endian_fix(i)]^=(next>>24);
443 unwound_key.element.serial^=appid_mask_a;
444 unwound_key.element.checksum^=appid_mask_b;
446 *serial=unwound_key.element.serial;
448 return unwound_key.element.checksum==hash_U32(unwound_key.element.serial);
452 int check_license(String basedir)
454 #ifdef LICENSE_KEY_REQUIRED
459 license_file="/usr/local/etc/.synfiglicense";
461 license_file=basedir+"\\etc\\.synfiglicense";
465 key=Glib::file_get_contents(license_file);
466 } catch (Glib::FileError) { }
468 if(!v_key_check(key.c_str(),&serial,0xdeadbeef))
470 while(!v_key_check(key.c_str(),&serial,0xdeadbeef))
474 if(!App::dialog_entry(
475 _("Synfig Studio Authentication"),
476 _("Please enter your license key below. You will not\nbe able to use this software without a valid license key."),
479 throw String("No License");
482 FILE* file=fopen(license_file.c_str(),"w");
485 fprintf(file,"%s",key.c_str());
489 synfig::error("Unable to save license key!");
491 synfig::info("License Authenticated -- Serial #%05d",serial);
500 studio::UIManager::insert_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group, int pos)
502 action_group_list.push_back(action_group);
503 Gtk::UIManager::insert_action_group(action_group, pos);
507 studio::UIManager::remove_action_group (const Glib::RefPtr<Gtk::ActionGroup>& action_group)
509 std::list<Glib::RefPtr<Gtk::ActionGroup> >::iterator iter;
510 for(iter=action_group_list.begin();iter!=action_group_list.end();++iter)
511 if(*iter==action_group)
513 action_group_list.erase(iter);
514 Gtk::UIManager::remove_action_group(action_group);
517 synfig::error("Unable to find action group");
521 studio::add_action_group_to_top(Glib::RefPtr<studio::UIManager> ui_manager, Glib::RefPtr<Gtk::ActionGroup> group)
523 ui_manager->insert_action_group(group,0);
526 std::list<Glib::RefPtr<Gtk::ActionGroup> > prev_groups(ui_manager->get_action_groups());
527 std::list<Glib::RefPtr<Gtk::ActionGroup> >::reverse_iterator iter;
530 for(iter=prev_groups.rbegin();iter!=prev_groups.rend();++iter)
533 if(*iter && (*iter)->get_name()!="menus")
535 synfig::info("Removing action group "+(*iter)->get_name());
536 ui_manager->remove_action_group(*iter);
540 ui_manager->insert_action_group(group,0);
543 for(;!prev_groups.empty();prev_groups.pop_front())
545 if(prev_groups.front() && prev_groups.front()!=group && prev_groups.front()->get_name()!="menus")
546 ui_manager->insert_action_group(prev_groups.front(),1);
551 class Preferences : public synfigapp::Settings
554 virtual bool get_value(const synfig::String& key, synfig::String& value)const
558 value=strprintf("%f %f %f %f",
559 App::gamma.get_gamma_r(),
560 App::gamma.get_gamma_g(),
561 App::gamma.get_gamma_b(),
562 App::gamma.get_black_level()
566 if(key=="time_format")
568 value=strprintf("%i",App::get_time_format());
571 if(key=="file_history.size")
573 value=strprintf("%i",App::get_max_recent_files());
576 if(key=="use_colorspace_gamma")
578 value=strprintf("%i",(int)App::use_colorspace_gamma);
581 if(key=="distance_system")
583 value=strprintf("%s",Distance::system_name(App::distance_system).c_str());
586 if(key=="auto_recover_backup_interval")
588 value=strprintf("%i",App::auto_recover->get_timeout());
592 return synfigapp::Settings::get_value(key,value);
595 virtual bool set_value(const synfig::String& key,const synfig::String& value)
601 strscanf(value,"%f %f %f %f",
608 App::gamma.set_all(r,g,b,blk);
612 if(key=="time_format")
614 int i(atoi(value.c_str()));
615 App::set_time_format(static_cast<synfig::Time::Format>(i));
618 if(key=="auto_recover_backup_interval")
620 int i(atoi(value.c_str()));
621 App::auto_recover->set_timeout(i);
624 if(key=="file_history.size")
626 int i(atoi(value.c_str()));
627 App::set_max_recent_files(i);
630 if(key=="use_colorspace_gamma")
632 int i(atoi(value.c_str()));
633 App::use_colorspace_gamma=i;
636 if(key=="distance_system")
638 App::distance_system=Distance::ident_system(value);;
642 return synfigapp::Settings::set_value(key,value);
645 virtual KeyList get_key_list()const
647 KeyList ret(synfigapp::Settings::get_key_list());
648 ret.push_back("gamma");
649 ret.push_back("time_format");
650 ret.push_back("distance_system");
651 ret.push_back("file_history.size");
652 ret.push_back("use_colorspace_gamma");
653 ret.push_back("auto_recover_backup_interval");
658 static Preferences _preferences;
663 Glib::RefPtr<Gtk::ActionGroup> menus_action_group = Gtk::ActionGroup::create("menus");
665 Glib::RefPtr<Gtk::ActionGroup> toolbox_action_group = Gtk::ActionGroup::create("toolbox");
667 Glib::RefPtr<Gtk::ActionGroup> actions_action_group = Gtk::ActionGroup::create();
669 menus_action_group->add( Gtk::Action::create("menu-file", "_File") );
670 menus_action_group->add( Gtk::Action::create("menu-edit", "_Edit") );
671 menus_action_group->add( Gtk::Action::create("menu-view", "_View") );
672 menus_action_group->add( Gtk::Action::create("menu-canvas", "_Canvas") );
673 menus_action_group->add( Gtk::Action::create("menu-layer", "_Layer") );
674 menus_action_group->add( Gtk::Action::create("menu-duck-mask", "Mask Ducks") );
675 menus_action_group->add( Gtk::Action::create("menu-preview-quality", "Preview Quality") );
676 menus_action_group->add( Gtk::Action::create("menu-layer-new", "New Layer") );
677 menus_action_group->add( Gtk::Action::create("menu-keyframe", "Keyframe") );
678 menus_action_group->add( Gtk::Action::create("menu-group", "Group") );
679 menus_action_group->add( Gtk::Action::create("menu-state", "State") );
680 menus_action_group->add( Gtk::Action::create("menu-toolbox", "Toolbox") );
682 // Add the synfigapp actions...
683 synfigapp::Action::Book::iterator iter;
684 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
686 actions_action_group->add(Gtk::Action::create(
687 "action-"+iter->second.name,
688 get_action_stock_id(iter->second),
689 iter->second.local_name,iter->second.local_name
693 #define DEFINE_ACTION(x,stock) { Glib::RefPtr<Gtk::Action> action( Gtk::Action::create(x, stock) ); /*action->set_sensitive(false);*/ actions_action_group->add(action); }
694 #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); }
695 #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); }
697 DEFINE_ACTION2("keyframe-properties", Gtk::StockID("gtk-properties"), _("Keyframe Properties"));
698 DEFINE_ACTION("about", Gtk::StockID("synfig-about"));
699 DEFINE_ACTION("open", Gtk::Stock::OPEN);
700 DEFINE_ACTION("save", Gtk::Stock::SAVE);
701 DEFINE_ACTION("save-as", Gtk::Stock::SAVE_AS);
702 DEFINE_ACTION("revert", Gtk::Stock::REVERT_TO_SAVED);
703 DEFINE_ACTION("cvs-add", Gtk::StockID("synfig-cvs_add"));
704 DEFINE_ACTION("cvs-update", Gtk::StockID("synfig-cvs_update"));
705 DEFINE_ACTION("cvs-commit", Gtk::StockID("synfig-cvs_commit"));
706 DEFINE_ACTION("cvs-revert", Gtk::StockID("synfig-cvs_revert"));
707 DEFINE_ACTION("import", _("Import"));
708 DEFINE_ACTION("render", _("Render"));
709 DEFINE_ACTION("preview", _("Preview"));
710 DEFINE_ACTION("dialog-flipbook", _("Preview Dialog"));
711 DEFINE_ACTION("sound", _("Sound File"));
712 DEFINE_ACTION("options", _("Options"));
713 DEFINE_ACTION("close", _("Close"));
716 DEFINE_ACTION("undo", Gtk::StockID("gtk-undo"));
717 DEFINE_ACTION("redo", Gtk::StockID("gtk-redo"));
718 DEFINE_ACTION("cut", Gtk::StockID("gtk-cut"));
719 DEFINE_ACTION("copy", Gtk::StockID("gtk-copy"));
720 DEFINE_ACTION("paste", Gtk::StockID("gtk-paste"));
721 DEFINE_ACTION("select-all-ducks", _("Select All Ducks"));
722 DEFINE_ACTION("unselect-all-layers", _("Unselect All Layers"));
723 DEFINE_ACTION("properties", _("Properties"));
725 DEFINE_ACTION("mask-position-ducks", _("Mask Position Ducks"));
726 DEFINE_ACTION("mask-vertex-ducks", _("Mask Vertex Ducks"));
727 DEFINE_ACTION("mask-tangent-ducks", _("Mask Tangent Ducks"));
728 DEFINE_ACTION("mask-radius-ducks", _("Mask Radius Ducks"));
729 DEFINE_ACTION("mask-width-ducks", _("Mask Width Ducks"));
730 DEFINE_ACTION("mask-angle-ducks", _("Mask Angle Ducks"));
731 DEFINE_ACTION("quality-00", _("Use Parametric Renderer"));
732 DEFINE_ACTION("quality-01", _("Use Quality Level 1"));
733 DEFINE_ACTION("quality-02", _("Use Quality Level 2"));
734 DEFINE_ACTION("quality-03", _("Use Quality Level 3"));
735 DEFINE_ACTION("quality-04", _("Use Quality Level 4"));
736 DEFINE_ACTION("quality-05", _("Use Quality Level 5"));
737 DEFINE_ACTION("quality-06", _("Use Quality Level 6"));
738 DEFINE_ACTION("quality-07", _("Use Quality Level 7"));
739 DEFINE_ACTION("quality-08", _("Use Quality Level 8"));
740 DEFINE_ACTION("quality-09", _("Use Quality Level 9"));
741 DEFINE_ACTION("quality-10", _("Use Quality Level 10"));
742 DEFINE_ACTION("play", _("Play"));
743 DEFINE_ACTION("pause", _("Pause"));
744 DEFINE_ACTION("stop", _("Stop"));
745 DEFINE_ACTION("toggle-grid-show", _("Toggle Grid Show"));
746 DEFINE_ACTION("toggle-grid-snap", _("Toggle Grid Snap"));
747 DEFINE_ACTION("toggle-guide-show", _("Toggle Guide Show"));
748 DEFINE_ACTION("toggle-low-res", _("Toggle Low-Res"));
749 DEFINE_ACTION("toggle-onion-skin", _("Toggle Onion Skin"));
750 DEFINE_ACTION("canvas-zoom-in", Gtk::StockID("gtk-zoom-in"));
751 DEFINE_ACTION("canvas-zoom-out", Gtk::StockID("gtk-zoom-out"));
752 DEFINE_ACTION("canvas-zoom-fit", Gtk::StockID("gtk-zoom-fit"));
753 DEFINE_ACTION("canvas-zoom-100", Gtk::StockID("gtk-zoom-100"));
754 DEFINE_ACTION("time-zoom-in", Gtk::StockID("gtk-zoom-in"));
755 DEFINE_ACTION("time-zoom-out", Gtk::StockID("gtk-zoom-out"));
756 DEFINE_ACTION("jump-next-keyframe", _("Jump to Next Keyframe"));
757 DEFINE_ACTION("jump-prev-keyframe", _("Jump to Prev Keyframe"));
758 DEFINE_ACTION("seek-next-frame", _("Next Frame"));
759 DEFINE_ACTION("seek-prev-frame", _("Prev Frame"));
760 DEFINE_ACTION("seek-next-second", _("Seek Forward"));
761 DEFINE_ACTION("seek-prev-second", _("Seek Backward"));
762 DEFINE_ACTION("seek-begin", _("Seek to Begin"));
763 DEFINE_ACTION("seek-end", _("Seek to End"));
765 DEFINE_ACTION("action-group_add", _("Add group"));
767 DEFINE_ACTION("canvas-new", _("New Canvas"));
769 DEFINE_ACTION("amount-inc", _("Increase Amount"));
770 DEFINE_ACTION("amount-dec", _("Decrease Amount"));
775 // Set up synfigapp actions
777 synfigapp::Action::Book::iterator iter;
779 for(iter=synfigapp::Action::book().begin();iter!=synfigapp::Action::book().end();++iter)
781 Gtk::StockID stock_id;
783 if(!(iter->second.category&synfigapp::Action::CATEGORY_HIDDEN))
785 //Gtk::Image* image(manage(new Gtk::Image()));
786 if(iter->second.task=="raise") stock_id=Gtk::Stock::GO_UP;
787 else if(iter->second.task=="lower") stock_id=Gtk::Stock::GO_DOWN;
788 else if(iter->second.task=="move_top") stock_id=Gtk::Stock::GOTO_TOP;
789 else if(iter->second.task=="move_bottom") stock_id=Gtk::Stock::GOTO_BOTTOM;
790 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
791 else if(iter->second.task=="set_on") stock_id=Gtk::Stock::YES;
792 else if(iter->second.task=="set_off") stock_id=Gtk::Stock::NO;
793 //else if(iter->second.task=="duplicate") stock_id=Gtk::Stock::COPY;
794 else if(iter->second.task=="remove") stock_id=Gtk::Stock::DELETE;
795 else stock_id=Gtk::StockID("synfig-"+iter->second.task);
797 actions_action_group->add(Gtk::Action::create(
798 "action-"+iter->second.name,
800 iter->second.local_name,iter->second.local_name
808 Glib::ustring ui_info =
810 " <popup name='menu-toolbox' action='menu-toolbox'>"
811 " <menu action='menu-file'>"
814 " <popup name='menu-main' action='menu-main'>"
815 " <menu action='menu-file'>"
816 " <menuitem action='save' />"
817 " <menuitem action='save-as' />"
818 " <menuitem action='revert' />"
819 " <separator name='bleh01'/>"
820 " <menuitem action='cvs-add' />"
821 " <menuitem action='cvs-update' />"
822 " <menuitem action='cvs-commit' />"
823 " <menuitem action='cvs-revert' />"
824 " <separator name='bleh02'/>"
825 " <menuitem action='import' />"
826 " <separator name='bleh03'/>"
827 " <menuitem action='render' />"
828 " <menuitem action='preview' />"
829 " <menuitem action='sound' />"
830 " <separator name='bleh04'/>"
831 " <menuitem action='options' />"
832 " <menuitem action='close' />"
834 " <menu action='menu-edit'>"
835 " <menuitem action='undo'/>"
836 " <menuitem action='redo'/>"
837 " <separator name='bleh05'/>"
838 " <menuitem action='cut'/>"
839 " <menuitem action='copy'/>"
840 " <menuitem action='paste'/>"
841 " <separator name='bleh06'/>"
842 " <menuitem action='select-all-ducks'/>"
843 " <menuitem action='unselect-all-layers'/>"
844 " <separator name='bleh07'/>"
845 " <menuitem action='properties'/>"
847 " <menu action='menu-view'>"
848 " <menu action='menu-duck-mask'>"
849 " <menuitem action='mask-position-ducks' />"
850 " <menuitem action='mask-vertex-ducks' />"
851 " <menuitem action='mask-tangent-ducks' />"
852 " <menuitem action='mask-radius-ducks' />"
853 " <menuitem action='mask-width-ducks' />"
854 " <menuitem action='mask-angle-ducks' />"
856 " <menu action='menu-preview-quality'>"
857 " <menuitem action='quality-00' />"
858 " <menuitem action='quality-01' />"
859 " <menuitem action='quality-02' />"
860 " <menuitem action='quality-03' />"
861 " <menuitem action='quality-04' />"
862 " <menuitem action='quality-05' />"
863 " <menuitem action='quality-06' />"
864 " <menuitem action='quality-07' />"
865 " <menuitem action='quality-08' />"
866 " <menuitem action='quality-09' />"
867 " <menuitem action='quality-10' />"
869 " <separator name='bleh08'/>"
870 " <menuitem action='play'/>"
871 " <menuitem action='pause'/>"
872 " <menuitem action='stop'/>"
873 " <menuitem action='dialog-flipbook'/>"
874 " <separator name='bleh09'/>"
875 " <menuitem action='toggle-grid-show'/>"
876 " <menuitem action='toggle-grid-snap'/>"
877 " <menuitem action='toggle-guide-show'/>"
878 " <menuitem action='toggle-low-res'/>"
879 " <menuitem action='toggle-onion-skin'/>"
880 " <separator name='bleh10'/>"
881 " <menuitem action='canvas-zoom-in'/>"
882 " <menuitem action='canvas-zoom-out'/>"
883 " <menuitem action='canvas-zoom-fit'/>"
884 " <menuitem action='canvas-zoom-100'/>"
885 " <separator name='bleh11'/>"
886 " <menuitem action='time-zoom-in'/>"
887 " <menuitem action='time-zoom-out'/>"
888 " <separator name='bleh12'/>"
889 " <menuitem action='jump-next-keyframe'/>"
890 " <menuitem action='jump-prev-keyframe'/>"
891 " <menuitem action='seek-next-frame'/>"
892 " <menuitem action='seek-prev-frame'/>"
893 " <menuitem action='seek-next-second'/>"
894 " <menuitem action='seek-prev-second'/>"
895 " <menuitem action='seek-begin'/>"
896 " <menuitem action='seek-end'/>"
898 " <menu action='menu-canvas'>"
899 " <menuitem action='canvas-new'/>"
900 " <menuitem action='amount-inc'/>"
901 " <menuitem action='amount-dec'/>"
903 " <menu name='menu-state' action='menu-state'>"
905 " <menu action='menu-group'>"
906 " <menuitem action='action-group_add'/>"
908 " <menu action='menu-layer'>"
909 //" <menuitem action='cut'/>"
910 //" <menuitem action='copy'/>"
911 //" <menuitem action='paste'/>"
912 //" <separator name='bleh06'/>"
913 " <menu action='menu-layer-new'></menu>"
915 " <menu action='menu-keyframe'>"
916 " <menuitem action='keyframe-properties'/>"
923 " <menubar name='MenuBar'>"
924 " <menu action='MenuFile'>"
925 " <menuitem action='New'/>"
926 " <menuitem action='Open'/>"
928 " <menuitem action='Quit'/>"
930 " <menu action='MenuEdit'>"
931 " <menuitem action='Cut'/>"
932 " <menuitem action='Copy'/>"
933 " <menuitem action='Paste'/>"
936 " <toolbar name='ToolBar'>"
937 " <toolitem action='Open'/>"
938 " <toolitem action='Quit'/>"
944 actions_action_group->set_sensitive(false);
945 App::ui_manager()->set_add_tearoffs(true);
946 App::ui_manager()->insert_action_group(menus_action_group,1);
947 App::ui_manager()->insert_action_group(actions_action_group,1);
948 App::ui_manager()->add_ui_from_string(ui_info);
950 //App::ui_manager()->get_accel_group()->unlock();
952 catch(const Glib::Error& ex)
954 synfig::error("building menus and toolbars failed: " + ex.what());
957 // Add default keyboard accelerators
958 #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()); }
959 #define ACCEL2(accel) { Gtk::AccelKey accel_key(accel); Gtk::AccelMap::add_entry(accel_key.get_path(), accel_key.get_key(),accel_key.get_mod()); }
960 ACCEL("<Actions>//select-all-ducks","<Control>a");
961 ACCEL("<Actions>//unselect-all-layers","<Control>d");
962 ACCEL("<Actions>//render","F9");
963 ACCEL("<Actions>//preview","F11");
964 ACCEL("<Actions>//properties","F8");
965 ACCEL("<Actions>//options","F12");
966 ACCEL("<Actions>//import","<control>i");
967 ACCEL2(Gtk::AccelKey(GDK_Escape,static_cast<Gdk::ModifierType>(0),"<Actions>//stop"));
968 ACCEL("<Actions>//toggle-grid-show","<Control>g");
969 ACCEL("<Actions>//toggle-grid-snap","<Control>l");
970 ACCEL2(Gtk::AccelKey('`',Gdk::CONTROL_MASK,"<Actions>//toggle-low-res"));
971 ACCEL("<Actions>//mask-position-ducks", "<Mod1>1");
972 ACCEL("<Actions>//mask-vertex-ducks", "<Mod1>2");
973 ACCEL("<Actions>//mask-tangent-ducks", "<Mod1>3");
974 ACCEL("<Actions>//mask-radius-ducks", "<Mod1>4");
975 ACCEL("<Actions>//mask-width-ducks", "<Mod1>5");
976 ACCEL("<Actions>//mask-angle-ducks", "<Mod1>6");
979 ACCEL2(Gtk::AccelKey(GDK_Page_Up,Gdk::SHIFT_MASK,"<Actions>//action-layer_raise"));
980 ACCEL2(Gtk::AccelKey(GDK_Page_Down,Gdk::SHIFT_MASK,"<Actions>//action-layer_lower"));
982 ACCEL("<Actions>//quality-01","<Control>1");
983 ACCEL("<Actions>//quality-02","<Control>2");
984 ACCEL("<Actions>//quality-03","<Control>3");
985 ACCEL("<Actions>//quality-04","<Control>4");
986 ACCEL("<Actions>//quality-05","<Control>5");
987 ACCEL("<Actions>//quality-06","<Control>6");
988 ACCEL("<Actions>//quality-07","<Control>7");
989 ACCEL("<Actions>//quality-08","<Control>8");
990 ACCEL("<Actions>//quality-09","<Control>9");
991 ACCEL("<Actions>//quality-10","<Control>0");
992 ACCEL("<Actions>//undo","<Control>z");
993 ACCEL("<Actions>//redo","<Control>r");
994 ACCEL("<Actions>//action-layer_remove","Delete");
996 /* ACCEL2(Gtk::AccelKey(']',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-next-keyframe"));
997 ACCEL2(Gtk::AccelKey('[',static_cast<Gdk::ModifierType>(0),"<Actions>//jump-prev-keyframe"));
998 ACCEL2(Gtk::AccelKey('=',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-in"));
999 ACCEL2(Gtk::AccelKey('-',static_cast<Gdk::ModifierType>(0),"<Actions>//canvas-zoom-out"));
1000 ACCEL("<Actions>//time-zoom-in","+");
1001 ACCEL("<Actions>//time-zoom-out","_");
1003 ACCEL2(Gtk::AccelKey('(',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-dec"));
1004 ACCEL2(Gtk::AccelKey(')',Gdk::MOD1_MASK|Gdk::CONTROL_MASK,"<Actions>//amount-inc"));
1006 ACCEL2(Gtk::AccelKey(']',Gdk::CONTROL_MASK,"<Actions>//jump-next-keyframe"));
1007 ACCEL2(Gtk::AccelKey('[',Gdk::CONTROL_MASK,"<Actions>//jump-prev-keyframe"));
1008 ACCEL2(Gtk::AccelKey('=',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-in"));
1009 ACCEL2(Gtk::AccelKey('-',Gdk::CONTROL_MASK,"<Actions>//canvas-zoom-out"));
1010 ACCEL2(Gtk::AccelKey('+',Gdk::CONTROL_MASK,"<Actions>//time-zoom-in"));
1011 ACCEL2(Gtk::AccelKey('_',Gdk::CONTROL_MASK,"<Actions>//time-zoom-out"));
1012 ACCEL2(Gtk::AccelKey('.',Gdk::CONTROL_MASK,"<Actions>//seek-next-frame"));
1013 ACCEL2(Gtk::AccelKey(',',Gdk::CONTROL_MASK,"<Actions>//seek-prev-frame"));
1014 ACCEL2(Gtk::AccelKey('>',Gdk::CONTROL_MASK,"<Actions>//seek-next-second"));
1015 ACCEL2(Gtk::AccelKey('<',Gdk::CONTROL_MASK,"<Actions>//seek-prev-second"));
1016 ACCEL2(Gtk::AccelKey('o',Gdk::CONTROL_MASK,"<Actions>//toggle-onion-skin"));
1017 ACCEL("<Actions>//seek-begin","Home");
1018 ACCEL("<Actions>//seek-end","End");
1019 ACCEL("<Actions>//state-normal","<Mod1>a");
1020 ACCEL("<Actions>//state-rotate","<Mod1>s");
1021 ACCEL("<Actions>//state-scale","<Mod1>d");
1022 ACCEL("<Actions>//state-bline","<Mod1>b");
1023 ACCEL("<Actions>//state-fill","<Mod1>f");
1024 ACCEL("<Actions>//state-eyedrop","<Mod1>e");
1025 ACCEL("<Actions>//state-gradient","<Mod1>g");
1026 ACCEL("<Actions>//state-zoom","<Mod1>z");
1027 ACCEL("<Actions>//canvas-zoom-fit","<Control><Shift>z");
1033 #define mkdir(x,y) mkdir(x)
1036 /* === M E T H O D S ======================================================= */
1038 App::App(int *argc, char ***argv):
1039 Gtk::Main(argc,argv),
1040 IconControler(etl::dirname((*argv)[0]))
1042 app_base_path_=etl::dirname(etl::dirname((*argv)[0]));
1045 serial_=check_license(app_base_path_);
1048 ui_interface_=new GlobalUIInterface();
1052 Glib::thread_init();
1054 distance_system=Distance::SYSTEM_UNITS;
1056 if(mkdir(get_user_app_directory().c_str(),ACCESSPERMS)<0)
1059 synfig::error("UNABLE TO CREATE \"%s\"",get_user_app_directory().c_str());
1063 synfig::info("Created directory \"%s\"",get_user_app_directory().c_str());
1071 if(!SYNFIG_CHECK_VERSION())
1073 cerr<<"FATAL: Synfig Version Mismatch"<<endl;
1074 dialog_error_blocking("SYNFIG Studio",
1075 "This copy of SYNFIG Studio was compiled against a\n"
1076 "different version of libsynfig than what is currently\n"
1077 "installed. Synfig Studio will now abort. Try downloading\n"
1078 "the latest version from the SYNFIG Development Website at\n"
1079 "http://dev.synfig.com/ "
1084 catch(synfig::SoftwareExpired)
1086 cerr<<"FATAL: Software Expired"<<endl;
1087 dialog_error_blocking("SYNFIG Studio",
1088 "This copy of SYNFIG Studio has expired.\n"
1089 "Please erase this copy, or download and\n"
1090 "install the latest copy from the SYNFIG\n"
1091 "Development Website at http://dev.synfig.com/ ."
1095 Glib::set_application_name(_("SYNFIG Studio"));
1098 about_window.set_can_self_destruct(false);
1099 about_window.show();
1101 shutdown_in_progress=false;
1102 SuperCallback synfig_init_cb(about_window.get_callback(),0,9000,10000);
1103 SuperCallback studio_init_cb(about_window.get_callback(),9000,10000,10000);
1105 // Initialize the Synfig library
1106 try { synfigapp_main=etl::smart_ptr<synfigapp::Main>(new synfigapp::Main(etl::dirname((*argv)[0]),&synfig_init_cb)); }
1109 get_ui_interface()->error("Failed to initialize synfig!");
1113 // add the preferences to the settings
1114 synfigapp::Main::settings().add_domain(&_preferences,"pref");
1118 studio_init_cb.task("Init UI Manager...");
1119 App::ui_manager_=studio::UIManager::create();
1122 studio_init_cb.task("Init Dock Manager...");
1123 dock_manager=new studio::DockManager();
1125 studio_init_cb.task("Init State Manager...");
1126 state_manager=new StateManager();
1128 studio_init_cb.task("Init Toolbox...");
1129 toolbox=new studio::Toolbox();
1131 studio_init_cb.task("Init Tool Options...");
1132 dialog_tool_options=new studio::Dialog_ToolOptions();
1133 dock_manager->register_dockable(*dialog_tool_options);
1135 studio_init_cb.task("Init History...");
1136 dock_history=new studio::Dock_History();
1137 dock_manager->register_dockable(*dock_history);
1139 studio_init_cb.task("Init Canvases...");
1140 dock_canvases=new studio::Dock_Canvases();
1141 dock_manager->register_dockable(*dock_canvases);
1143 studio_init_cb.task("Init Keyframes...");
1144 dock_keyframes=new studio::Dock_Keyframes();
1145 dock_manager->register_dockable(*dock_keyframes);
1147 studio_init_cb.task("Init Layers...");
1148 dock_layers=new studio::Dock_Layers();
1149 dock_manager->register_dockable(*dock_layers);
1151 studio_init_cb.task("Init Params...");
1152 dock_params=new studio::Dock_Params();
1153 dock_manager->register_dockable(*dock_params);
1155 studio_init_cb.task("Init MetaData...");
1156 dock_meta_data=new studio::Dock_MetaData();
1157 dock_manager->register_dockable(*dock_meta_data);
1159 studio_init_cb.task("Init Children...");
1160 dock_children=new studio::Dock_Children();
1161 dock_manager->register_dockable(*dock_children);
1163 studio_init_cb.task("Init Info...");
1164 dock_info = new studio::Dock_Info();
1165 dock_manager->register_dockable(*dock_info);
1167 studio_init_cb.task("Init Navigator...");
1168 dock_navigator = new studio::Dock_Navigator();
1169 dock_manager->register_dockable(*dock_navigator);
1171 studio_init_cb.task("Init Timetrack...");
1172 dock_timetrack = new studio::Dock_Timetrack();
1173 dock_manager->register_dockable(*dock_timetrack);
1175 studio_init_cb.task("Init Curve Editor...");
1176 dock_curves = new studio::Dock_Curves();
1177 dock_manager->register_dockable(*dock_curves);
1179 studio_init_cb.task("Init Layer Groups...");
1180 dock_layer_groups = new studio::Dock_LayerGroups();
1181 dock_manager->register_dockable(*dock_layer_groups);
1184 studio_init_cb.task("Init Color Dialog...");
1185 dialog_color=new studio::Dialog_Color();
1187 studio_init_cb.task("Init Gradient Dialog...");
1188 dialog_gradient=new studio::Dialog_Gradient();
1190 studio_init_cb.task("Init DeviceTracker...");
1191 device_tracker=new studio::DeviceTracker();
1193 studio_init_cb.task("Init Tools...");
1194 state_manager->add_state(&state_normal);
1195 state_manager->add_state(&state_smooth_move);
1196 state_manager->add_state(&state_scale);
1197 state_manager->add_state(&state_rotate);
1199 state_manager->add_state(&state_bline);
1200 state_manager->add_state(&state_polygon);
1201 state_manager->add_state(&state_circle);
1202 state_manager->add_state(&state_rectangle);
1204 state_manager->add_state(&state_draw);
1205 state_manager->add_state(&state_sketch);
1207 state_manager->add_state(&state_eyedrop);
1208 state_manager->add_state(&state_fill);
1210 state_manager->add_state(&state_width);
1211 state_manager->add_state(&state_gradient);
1213 state_manager->add_state(&state_zoom);
1215 studio_init_cb.task("Init ModPalette...");
1216 module_list_.push_back(new ModPalette()); module_list_.back()->start();
1218 studio_init_cb.task("Init ModMirror...");
1219 module_list_.push_back(new ModMirror()); module_list_.back()->start();
1222 studio_init_cb.task("Init Setup Dialog...");
1223 dialog_setup=new studio::Dialog_Setup();
1225 studio_init_cb.task("Init Input Dialog...");
1226 dialog_input=new Gtk::InputDialog();
1228 studio_init_cb.task("Init auto recovery...");
1229 auto_recover=new AutoRecover();
1231 studio_init_cb.amount_complete(9250,10000);
1232 studio_init_cb.task("Loading Settings...");
1234 studio_init_cb.task("Checking auto-recover...");
1236 studio_init_cb.amount_complete(9900,10000);
1238 if(auto_recover->recovery_needed())
1240 about_window.hide();
1242 get_ui_interface()->yes_no(
1244 "SYNFIG Studio seems to have crashed\n"
1245 "before you could save all your files.\n"
1246 "Would you like to re-open those files\n"
1247 "and recover your unsaved changes?"
1248 )==synfigapp::UIInterface::RESPONSE_YES
1251 if(!auto_recover->recover())
1253 get_ui_interface()->error(_("Unable to fully recover from previous crash"));
1256 get_ui_interface()->error(
1257 _("SYNFIG Studio has attempted to recover\n"
1258 "from a previous crash. The files that it has\n"
1259 "recovered are NOT YET SAVED. It would be a good\n"
1260 "idea to review them and save them now.")
1263 about_window.show();
1266 // Look for any files given on the command line,
1267 // and load them if found.
1268 for(;*argc>=1;(*argc)--)
1269 if((*argv)[*argc] && (*argv)[*argc][0]!='-')
1271 studio_init_cb.task("Loading files...");
1272 about_window.hide();
1273 open((*argv)[*argc]);
1274 about_window.show();
1277 studio_init_cb.task("Done.");
1278 studio_init_cb.amount_complete(10000,10000);
1284 get_ui_interface()->error(_("Unknown exception caught when constructing App.\nThis software may be unstable."));
1288 StateManager* App::get_state_manager() { return state_manager; }
1292 shutdown_in_progress=true;
1296 synfigapp::Main::settings().remove_domain("pref");
1298 selected_instance=0;
1300 // Unload all of the modules
1301 for(;!module_list_.empty();module_list_.pop_back());
1303 delete state_manager;
1307 delete auto_recover;
1311 // studio::App::iteration(false);
1315 // studio::App::iteration(false);
1317 // studio::App::iteration(false);
1319 delete dialog_setup;
1321 delete dialog_gradient;
1323 delete dialog_color;
1325 delete dialog_input;
1327 delete dock_manager;
1329 instance_list.clear();
1331 // studio::App::iteration(false);
1335 App::get_user_app_directory()
1338 return Glib::build_filename(Glib::get_home_dir(),"Library/Synfig");
1340 return Glib::build_filename(Glib::get_home_dir(),"Synfig");
1345 App::get_config_file(const synfig::String& file)
1347 return Glib::build_filename(get_user_app_directory(),file);
1351 App::add_recent_file(const std::string &file_name)
1353 std::string filename(file_name);
1355 assert(!filename.empty());
1357 if(filename.empty())
1360 // Toss out any "hidden" files
1361 if(basename(filename)[0]=='.')
1364 // If we aren't an absolute path, turn outselves into one
1365 if(!is_absolute_path(filename))
1366 filename=absolute_path(filename);
1368 list<string>::iterator iter;
1369 // Check to see if the file is already on the list.
1370 // If it is, then remove it from the list
1371 for(iter=recent_files.begin();iter!=recent_files.end();iter++)
1374 recent_files.erase(iter);
1379 // Push the filename to the front of the list
1380 recent_files.push_front(filename);
1382 // Clean out the files at the end of the list.
1383 while(recent_files.size()>(unsigned)get_max_recent_files())
1384 recent_files.pop_back();
1386 signal_recent_files_changed_();
1391 static Time::Format _App_time_format(Time::FORMAT_NORMAL);
1394 App::get_time_format()
1396 return _App_time_format;
1400 App::set_time_format(synfig::Time::Format x)
1407 App::save_settings()
1412 std::string filename=get_config_file("accelrc");
1413 Gtk::AccelMap::save(filename);
1416 std::string filename=get_config_file("recentfiles");
1418 std::ofstream file(filename.c_str());
1422 synfig::warning("Unable to save %s",filename.c_str());
1426 list<string>::reverse_iterator iter;
1428 for(iter=recent_files.rbegin();iter!=recent_files.rend();iter++)
1432 std::string filename=get_config_file("settings");
1433 synfigapp::Main::settings().save_to_file(filename);
1437 synfig::warning("Caught exception when attempting to save settings.");
1442 App::load_settings()
1447 std::string filename=get_config_file("accelrc");
1448 Gtk::AccelMap::load(filename);
1451 std::string filename=get_config_file("recentfiles");
1453 std::ifstream file(filename.c_str());
1457 std::string recent_file;
1458 getline(file,recent_file);
1459 if(!recent_file.empty())
1460 add_recent_file(recent_file);
1463 std::string filename=get_config_file("settings");
1464 if(!synfigapp::Main::settings().load_from_file(filename))
1466 //std::string filename=Glib::build_filename(Glib::get_home_dir(),".synfigrc");
1467 //if(!synfigapp::Main::settings().load_from_file(filename))
1469 gamma.set_gamma(1.0/2.2);
1470 synfigapp::Main::settings().set_value("dock.dialog.1.comp_selector","1");
1471 synfigapp::Main::settings().set_value("dock.dialog.1.contents","navigator - info pal_edit pal_browse - tool_options history canvases - layers groups");
1472 synfigapp::Main::settings().set_value("dock.dialog.1.contents_size","225 167 207");
1473 synfigapp::Main::settings().set_value("dock.dialog.1.pos","1057 32");
1474 synfigapp::Main::settings().set_value("dock.dialog.1.size","208 1174");
1475 synfigapp::Main::settings().set_value("dock.dialog.2.comp_selector","0");
1476 synfigapp::Main::settings().set_value("dock.dialog.2.contents","params children keyframes | timetrack curves meta_data");
1477 synfigapp::Main::settings().set_value("dock.dialog.2.contents_size","263");
1478 synfigapp::Main::settings().set_value("dock.dialog.2.pos","0 973");
1479 synfigapp::Main::settings().set_value("dock.dialog.2.size","1045 235");
1480 synfigapp::Main::settings().set_value("pref.distance_system","pt");
1481 synfigapp::Main::settings().set_value("pref.use_colorspace_gamma","1");
1482 synfigapp::Main::settings().set_value("window.toolbox.pos","4 4");
1489 synfig::warning("Caught exception when attempting to load settings.");
1494 App::shutdown_request(GdkEventAny*)
1498 //return !shutdown_in_progress;
1504 if(shutdown_in_progress)return;
1507 get_ui_interface()->task("Quit Request");
1510 dialog_error_blocking("Cannot quit!","Tasks are currently running.\nPlease cancel the current tasks and try again");
1514 std::list<etl::handle<Instance> >::iterator iter;
1515 for(iter=instance_list.begin();!instance_list.empty();iter=instance_list.begin())
1517 if(!(*iter)->safe_close())
1521 if((*iter)->synfigapp::Instance::get_action_count())
1523 handle<synfigapp::UIInterface> uim;
1524 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1526 string str=strprintf(_("Would you like to save your changes to %s?"),(*iter)->get_file_name().c_str() );
1527 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1529 case synfigapp::UIInterface::RESPONSE_NO:
1531 case synfigapp::UIInterface::RESPONSE_YES:
1534 case synfigapp::UIInterface::RESPONSE_CANCEL:
1543 if((*iter)->synfigapp::Instance::is_modified())
1545 handle<synfigapp::UIInterface> uim;
1546 uim=(*iter)->find_canvas_view((*iter)->get_canvas())->get_ui_interface();
1548 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() );
1549 switch(uim->yes_no_cancel((*iter)->get_canvas()->get_name(),str,synfigapp::UIInterface::RESPONSE_YES))
1551 case synfigapp::UIInterface::RESPONSE_NO:
1553 case synfigapp::UIInterface::RESPONSE_YES:
1554 (*iter)->dialog_cvs_commit();
1556 case synfigapp::UIInterface::RESPONSE_CANCEL:
1565 // This next line causes things to crash for some reason
1569 shutdown_in_progress=true;
1571 instance_list.clear();
1573 while(studio::App::events_pending())studio::App::iteration(false);
1576 auto_recover->normal_shutdown();
1578 get_ui_interface()->task("Quit Request sent");
1584 dialog_setup->refresh();
1585 dialog_setup->show();
1588 gint Signal_Open_Ok(GtkWidget *widget, int *val){*val=1;return 0;}
1589 gint Signal_Open_Cancel(GtkWidget *widget, int *val){*val=2;return 0;}
1592 //#define USE_WIN32_FILE_DIALOGS 1
1595 #ifdef USE_WIN32_FILE_DIALOGS
1596 static OPENFILENAME ofn={};
1600 #include <gdk/gdkwin32.h>
1604 App::dialog_open_file(const std::string &title, std::string &filename)
1606 #ifdef USE_WIN32_FILE_DIALOGS
1607 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1609 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1610 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1611 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1613 ofn.lStructSize=sizeof(OPENFILENAME);
1614 ofn.hwndOwner = hWnd;
1615 ofn.hInstance = hInstance;
1616 ofn.lpstrFilter = szFilter;
1617 // ofn.lpstrCustomFilter=NULL;
1618 // ofn.nMaxCustFilter=0;
1619 // ofn.nFilterIndex=0;
1620 // ofn.lpstrFile=NULL;
1621 ofn.nMaxFile=MAX_PATH;
1622 // ofn.lpstrFileTitle=NULL;
1623 // ofn.lpstrInitialDir=NULL;
1624 // ofn.lpstrTitle=NULL;
1625 ofn.Flags=OFN_HIDEREADONLY;
1626 // ofn.nFileOffset=0;
1627 // ofn.nFileExtension=0;
1628 ofn.lpstrDefExt=TEXT("sif");
1629 // ofn.lCustData = 0l;
1631 // ofn.lpTemplateName=NULL;
1633 CHAR szFilename[MAX_PATH];
1635 strcpy(szFilename,filename.c_str());
1636 strcpy(szTitle,title.c_str());
1638 ofn.lpstrFile=szFilename;
1639 ofn.lpstrFileTitle=szTitle;
1641 if(GetOpenFileName(&ofn))
1643 filename=szFilename;
1649 synfig::String prev_path;
1650 if(!_preferences.get_value("curr_path",prev_path))
1657 GtkWidget *fileselection;
1658 fileselection = gtk_file_selection_new(title.c_str());
1661 if(basename(filename)==filename)
1663 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),(prev_path+ETL_DIRECTORY_SEPERATOR).c_str());
1666 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileselection),dirname(filename).c_str());
1668 gtk_file_selection_complete(GTK_FILE_SELECTION(fileselection),basename(filename).c_str());
1670 ok=GTK_FILE_SELECTION(fileselection)->ok_button;
1671 cancel=GTK_FILE_SELECTION(fileselection)->cancel_button;
1673 gtk_signal_connect(GTK_OBJECT(ok),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Ok),&val);
1674 gtk_signal_connect(GTK_OBJECT(cancel),"clicked",GTK_SIGNAL_FUNC(Signal_Open_Cancel),&val);
1676 gtk_widget_show(fileselection);
1684 filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(fileselection));
1685 _preferences.set_value("curr_path",dirname(filename));
1689 gtk_widget_destroy(fileselection);
1692 gtk_widget_destroy(fileselection);
1698 App::dialog_save_file(const std::string &title, std::string &filename)
1700 #ifdef USE_WIN32_FILE_DIALOGS
1701 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1703 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1704 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1705 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1707 ofn.lStructSize=sizeof(OPENFILENAME);
1708 ofn.hwndOwner = hWnd;
1709 ofn.hInstance = hInstance;
1710 ofn.lpstrFilter = szFilter;
1711 // ofn.lpstrCustomFilter=NULL;
1712 // ofn.nMaxCustFilter=0;
1713 // ofn.nFilterIndex=0;
1714 // ofn.lpstrFile=NULL;
1715 ofn.nMaxFile=MAX_PATH;
1716 // ofn.lpstrFileTitle=NULL;
1717 // ofn.lpstrInitialDir=NULL;
1718 // ofn.lpstrTitle=NULL;
1719 ofn.Flags=OFN_OVERWRITEPROMPT;
1720 // ofn.nFileOffset=0;
1721 // ofn.nFileExtension=0;
1722 ofn.lpstrDefExt=TEXT("sif");
1723 // ofn.lCustData = 0l;
1725 // ofn.lpTemplateName=NULL;
1727 CHAR szFilename[MAX_PATH];
1729 strcpy(szFilename,filename.c_str());
1730 strcpy(szTitle,title.c_str());
1732 ofn.lpstrFile=szFilename;
1733 ofn.lpstrFileTitle=szTitle;
1735 if(GetSaveFileName(&ofn))
1737 filename=szFilename;
1742 return dialog_open_file(title, filename);
1747 App::dialog_saveas_file(const std::string &title, std::string &filename)
1749 #if USE_WIN32_FILE_DIALOGS
1750 static TCHAR szFilter[] = TEXT ("All Files (*.*)\0*.*\0\0") ;
1752 GdkWindow *gdkWinPtr=toolbox->get_window()->gobj();
1753 HINSTANCE hInstance=static_cast<HINSTANCE>(GetModuleHandle(NULL));
1754 HWND hWnd=static_cast<HWND>(GDK_WINDOW_HWND(gdkWinPtr));
1756 ofn.lStructSize=sizeof(OPENFILENAME);
1757 ofn.hwndOwner = hWnd;
1758 ofn.hInstance = hInstance;
1759 ofn.lpstrFilter = szFilter;
1760 // ofn.lpstrCustomFilter=NULL;
1761 // ofn.nMaxCustFilter=0;
1762 // ofn.nFilterIndex=0;
1763 // ofn.lpstrFile=NULL;
1764 ofn.nMaxFile=MAX_PATH;
1765 // ofn.lpstrFileTitle=NULL;
1766 // ofn.lpstrInitialDir=NULL;
1767 // ofn.lpstrTitle=NULL;
1768 ofn.Flags=OFN_OVERWRITEPROMPT;
1769 // ofn.nFileOffset=0;
1770 // ofn.nFileExtension=0;
1771 ofn.lpstrDefExt=TEXT("sif");
1772 // ofn.lCustData = 0l;
1774 // ofn.lpTemplateName=NULL;
1776 CHAR szFilename[MAX_PATH];
1778 strcpy(szFilename,filename.c_str());
1779 strcpy(szTitle,title.c_str());
1781 ofn.lpstrFile=szFilename;
1782 ofn.lpstrFileTitle=szTitle;
1784 if(GetSaveFileName(&ofn))
1786 filename=szFilename;
1791 return dialog_open_file(title, filename);
1796 App::dialog_error_blocking(const std::string &title, const std::string &message)
1801 true // use_separator
1803 Gtk::Label label(message);
1806 dialog.get_vbox()->pack_start(label);
1807 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1813 App::dialog_warning_blocking(const std::string &title, const std::string &message)
1818 true // use_separator
1820 Gtk::Label label(message);
1823 dialog.get_vbox()->pack_start(label);
1824 dialog.add_button(Gtk::StockID("gtk-ok"),1);
1830 App::dialog_yes_no(const std::string &title, const std::string &message)
1835 true // use_separator
1837 Gtk::Label label(message);
1840 dialog.get_vbox()->pack_start(label);
1841 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1842 dialog.add_button(Gtk::StockID("gtk-no"),0);
1844 return dialog.run();
1848 App::dialog_yes_no_cancel(const std::string &title, const std::string &message)
1853 true // use_separator
1855 Gtk::Label label(message);
1858 dialog.get_vbox()->pack_start(label);
1859 dialog.add_button(Gtk::StockID("gtk-yes"),1);
1860 dialog.add_button(Gtk::StockID("gtk-no"),0);
1861 dialog.add_button(Gtk::StockID("gtk-cancel"),2);
1863 return dialog.run();
1867 App::dialog_not_implemented()
1870 "Feature not available", // Title
1872 true // use_separator
1874 Gtk::Label label("Sorry, this feature has not yet been implemented.");
1877 dialog.get_vbox()->pack_start(label);
1878 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1884 App::dialog_entry(const std::string &title, const std::string &message,std::string &text)
1889 true // use_separator
1891 Gtk::Label label(message);
1893 dialog.get_vbox()->pack_start(label);
1896 entry.set_text(text);
1898 entry.set_activates_default(true);
1899 dialog.get_vbox()->pack_start(entry);
1901 dialog.add_button(Gtk::StockID("gtk-ok"),Gtk::RESPONSE_OK);
1902 dialog.add_button(Gtk::StockID("gtk-cancel"),Gtk::RESPONSE_CANCEL);
1903 dialog.set_default_response(Gtk::RESPONSE_OK);
1904 entry.signal_activate().connect(sigc::bind(sigc::mem_fun(dialog,&Gtk::Dialog::response),Gtk::RESPONSE_OK));
1907 if(dialog.run()!=Gtk::RESPONSE_OK)
1910 text=entry.get_text();
1919 App::open(std::string filename)
1921 return open_as(filename,filename);
1925 App::open_as(std::string filename,std::string as)
1929 OneMoment one_moment;
1931 etl::handle<synfig::Canvas> canvas(open_canvas_as(filename,as));
1932 if(canvas && get_instance(canvas))
1934 get_instance(canvas)->find_canvas_view(canvas)->present();
1935 throw (String)strprintf(_("\"%s\" appears to already be open!"),filename.c_str());
1938 throw (String)strprintf(_("Unable to open file \"%s\""),filename.c_str());
1940 add_recent_file(as);
1942 handle<Instance> instance(Instance::create(canvas));
1945 throw (String)strprintf(_("Unable to create instance for \"%s\""),filename.c_str());
1949 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)")))
1950 instance->dialog_cvs_update();
1954 dialog_error_blocking(_("Error"), x);
1959 dialog_error_blocking(_("Error"), _("Uncaught error on file open (BUG)"));
1963 _preferences.set_value("curr_path",dirname(as));
1972 handle<synfig::Canvas> canvas=synfig::Canvas::create();
1973 canvas->set_name(strprintf("Untitled%d",Instance::get_count()));
1975 String file_name(strprintf("untitled%d.sif",Instance::get_count()));
1977 canvas->rend_desc().set_frame_rate(24.0);
1978 canvas->rend_desc().set_time_start(0.0);
1979 canvas->rend_desc().set_time_end(00.0);
1980 canvas->rend_desc().set_x_res(DPI2DPM(72.0f));
1981 canvas->rend_desc().set_y_res(DPI2DPM(72.0f));
1982 canvas->rend_desc().set_tl(Vector(-4,2.25));
1983 canvas->rend_desc().set_br(Vector(4,-2.25));
1984 canvas->rend_desc().set_w(480);
1985 canvas->rend_desc().set_h(270);
1986 canvas->rend_desc().set_antialias(1);
1987 canvas->rend_desc().set_flags(RendDesc::PX_ASPECT|RendDesc::IM_SPAN);
1988 canvas->set_file_name(file_name);
1990 Instance::create(canvas)->find_canvas_view(canvas)->canvas_properties.present();
1996 string filename="*.sif";
1998 while(dialog_open_file("Open", filename))
2000 // If the filename still has wildcards, then we should
2001 // continue looking for the file we want
2002 if(find(filename.begin(),filename.end(),'*')!=filename.end())
2008 get_ui_interface()->error(_("Unable to open file"));
2013 App::set_selected_instance(etl::loose_handle<Instance> instance)
2015 /* if(get_selected_instance()==instance)
2017 selected_instance=instance;
2018 signal_instance_selected()(instance);
2024 selected_instance=instance;
2025 if(get_selected_canvas_view() && get_selected_canvas_view()->get_instance()!=instance)
2029 instance->focus(instance->get_canvas());
2032 set_selected_canvas_view(0);
2034 signal_instance_selected()(instance);
2038 App::set_selected_canvas_view(etl::loose_handle<CanvasView> canvas_view)
2040 selected_canvas_view=canvas_view;
2041 signal_canvas_view_focus()(selected_canvas_view);
2044 selected_instance=canvas_view->get_instance();
2045 signal_instance_selected()(canvas_view->get_instance());
2048 if(get_selected_canvas_view()==canvas_view)
2050 signal_canvas_view_focus()(selected_canvas_view);
2051 signal_instance_selected()(canvas_view->get_instance());
2054 selected_canvas_view=canvas_view;
2055 if(canvas_view && canvas_view->get_instance() != get_selected_instance())
2056 set_selected_instance(canvas_view->get_instance());
2057 signal_canvas_view_focus()(selected_canvas_view);
2061 etl::loose_handle<Instance>
2062 App::get_instance(Canvas::Handle canvas)
2064 if(!canvas) return 0;
2065 canvas=canvas->get_root();
2067 std::list<etl::handle<Instance> >::iterator iter;
2068 for(iter=instance_list.begin();iter!=instance_list.end();++iter)
2070 if((*iter)->get_canvas()==canvas)
2079 (new class About())->show();
2085 if(selected_instance)
2086 selected_instance->undo();
2092 if(selected_instance)
2093 selected_instance->redo();
2097 studio::App::get_base_path()
2099 return app_base_path_;