def __init__(self, **kwargs): super(Designer, self).__init__(**kwargs) self.project_watcher = ProjectWatcher(self.project_modified) self.project_loader = ProjectLoader(self.project_watcher) self.recent_manager = RecentManager() self.widget_to_paste = None self.designer_content = DesignerContent(size_hint=(1, None)) self.designer_settings = DesignerSettings() self.designer_settings.bind(on_config_change=self._config_change) self.designer_settings.load_settings() self.designer_settings.bind(on_close=self._cancel_popup) Clock.schedule_interval( self.project_loader.perform_auto_save, int( self.designer_settings.config_parser.getdefault( 'global', 'auto_save_time', 5)) * 60)
def __init__(self, **kwargs): super(Designer, self).__init__(**kwargs) self.project_watcher = ProjectWatcher(self.project_modified) self.project_loader = ProjectLoader(self.project_watcher) self.recent_manager = RecentManager() self.widget_to_paste = None self.designer_content = DesignerContent(size_hint=(1, None)) self.designer_settings = DesignerSettings() self.designer_settings.bind(on_config_change=self._config_change) self.designer_settings.load_settings() self.designer_settings.bind(on_close=self._cancel_popup) Clock.schedule_interval(self.project_loader.perform_auto_save, int(self.designer_settings.config_parser.getdefault( 'global', 'auto_save_time', 5))*60)
class Designer(FloatLayout): '''Designer is the Main Window class of Kivy Designer :data:`message` is a :class:`~kivy.properties.StringProperty` ''' designer_console = ObjectProperty(None) '''Instance of :class:`designer.designer_console.ConsoleDialog` ''' statusbar = ObjectProperty(None) '''Reference to the :class:`~designer.statusbar.StatusBar` instance. :data:`statusbar` is a :class:`~kivy.properties.ObjectProperty` ''' editcontview = ObjectProperty(None) '''Reference to the :class:`~designer.uix.EditContView` instance. :data:`v` is a :class:`~kivy.properties.ObjectProperty` ''' actionbar = ObjectProperty(None) '''Reference to the :class:`~kivy.actionbar.ActionBar` instance. ActionBar is used as a MenuBar to display bunch of menu items. :data:`actionbar` is a :class:`~kivy.properties.ObjectProperty` ''' undo_manager = ObjectProperty(UndoManager()) '''Reference to the :class:`~designer.UndoManager` instance. :data:`undo_manager` is a :class:`~kivy.properties.ObjectProperty` ''' project_watcher = ObjectProperty(None) '''Reference to the :class:`~designer.project_watcher.ProjectWatcher`. :data:`project_watcher` is a :class:`~kivy.properties.ObjectProperty` ''' project_loader = ObjectProperty(None) '''Reference to the :class:`~designer.project_loader.ProjectLoader`. :data:`project_loader` is a :class:`~kivy.properties.ObjectProperty` ''' proj_settings = ObjectProperty(None) '''Reference of :class:`~designer.project_settings.ProjectSettings`. :data:`proj_settings` is a :class:`~kivy.properties.ObjectProperty` ''' _curr_proj_changed = BooleanProperty(False) '''Specifies whether current project has been changed inside Kivy Designer :data:`_curr_proj_changed` is a :class:`~kivy.properties.BooleanProperty` ''' _proj_modified_outside = BooleanProperty(False) '''Specifies whether current project has been changed outside Kivy Designer :data:`_proj_modified_outside` is a :class:`~kivy.properties.BooleanProperty` ''' ui_creator = ObjectProperty(None) '''Reference to :class:`~designer.ui_creator.UICreator` instance. :data:`ui_creator` is a :class:`~kivy.properties.ObjectProperty` ''' designer_content = ObjectProperty(None) '''Reference to :class:`~designer.designer_content.DesignerContent` instance. :data:`designer_content` is a :class:`~kivy.properties.ObjectProperty` ''' proj_tree_view = ObjectProperty(None) '''Reference to Project Tree instance :data:`proj_tree_view` is a :class:`~kivy.properties.ObjectProperty` ''' designer_settings = ObjectProperty(None) '''Reference of :class:`~designer.designer_settings.DesignerSettings`. :data:`designer_settings` is a :class:`~kivy.properties.ObjectProperty` ''' start_page = ObjectProperty(None) '''Reference of :class:`~designer.start_page.DesignerStartPage`. :data:`start_page` is a :class:`~kivy.properties.ObjectProperty` ''' recent_files_cont_menu = ObjectProperty(None) '''The context sub menu, containing the recently opened/saved projects. Reference of :class:`~designer.uix.contextual.ContextSubMenu`. :data:`recent_files_cont_menu` is a :class:`~kivy.properties.ObjectProperty` ''' def __init__(self, **kwargs): super(Designer, self).__init__(**kwargs) self.project_watcher = ProjectWatcher(self.project_modified) self.project_loader = ProjectLoader(self.project_watcher) self.recent_manager = RecentManager() self.widget_to_paste = None self.designer_content = DesignerContent(size_hint=(1, None)) self.designer_settings = DesignerSettings() self.designer_settings.bind(on_config_change=self._config_change) self.designer_settings.load_settings() self.designer_settings.bind(on_close=self._cancel_popup) Clock.schedule_interval(self.project_loader.perform_auto_save, int(self.designer_settings.config_parser.getdefault( 'global', 'auto_save_time', 5))*60) def _config_change(self, *args): '''Event Handler for 'on_config_change' event of self.designer_settings. ''' Clock.unschedule(self.project_loader.perform_auto_save) Clock.schedule_interval(self.project_loader.perform_auto_save, int(self.designer_settings.config_parser.getdefault( 'global', 'auto_save_time', 5))*60) self.ui_creator.kv_code_input.reload_kv = \ bool(self.designer_settings.config_parser.getdefault( 'global', 'reload_kv', True)) self.recent_manager.max_recent_files = \ int(self.designer_settings.config_parser.getdefault( 'global', 'num_recent_files', 5)) def _add_designer_content(self): '''Add designer_content to Designer, when a project is loaded ''' for _child in self.children[:]: if _child == self.designer_content: return self.remove_widget(self.start_page) self.add_widget(self.designer_content, 1) self.ids['actn_btn_save'].disabled = False self.ids['actn_btn_save_as'].disabled = False self.ids['actn_chk_proj_tree'].disabled = False self.ids['actn_chk_prop_event'].disabled = False self.ids['actn_chk_widget_tree'].disabled = False self.ids['actn_chk_status_bar'].disabled = False self.ids['actn_chk_kv_lang_area'].disabled = False self.ids['actn_btn_add_file'].disabled = False self.ids['actn_btn_custom_widget'].disabled = False self.ids['actn_btn_proj_pref'].disabled = False self.ids['actn_btn_run_proj'].disabled = False def on_statusbar_height(self, *args): '''Callback for statusbar.height ''' self.designer_content.y = self.statusbar.height self.on_height(*args) def on_actionbar_height(self, *args): '''Callback for actionbar.height ''' self.on_height(*args) def on_height(self, *args): '''Callback for self.height ''' if self.actionbar and self.statusbar: self.designer_content.height = self.height - \ self.actionbar.height - self.statusbar.height self.designer_content.y = self.statusbar.height def project_modified(self, *args): '''Event Handler called when Project is modified outside Kivy Designer ''' #To dispatch modified event only once for all files/folders of proj_dir if self._proj_modified_outside: return self._confirm_dlg = ConfirmationDialog(message="Current Project has " "been modified\n" "outside the Kivy Designer.\n" "Do you want to reload project?") self._confirm_dlg.bind(on_ok=self._perform_reload, on_cancel=self._cancel_popup) self._popup = Popup(title='Kivy Designer', content=self._confirm_dlg, size_hint=(None, None),size=('200pt', '150pt'), auto_dismiss=False) self._popup.open() self._proj_modified_outside = True def _perform_reload(self, *args): '''Perform reload of project after it is modified ''' #Perform reload of project after it is modified self._popup.dismiss() self.project_watcher.allow_event_dispatch = False self._perform_open(self.project_loader.proj_dir) self.project_watcher.allow_event_dispatch = True self._proj_modified_outside = False def on_show_edit(self, *args): '''Event Handler of 'on_show_edit' event. This will show EditContView in ActionBar ''' if isinstance(self.actionbar.children[0], EditContView): return if self.editcontview == None: self.editcontview = EditContView( on_undo=self.action_btn_undo_pressed, on_redo=self.action_btn_redo_pressed, on_cut=self.action_btn_cut_pressed, on_copy=self.action_btn_copy_pressed, on_paste=self.action_btn_paste_pressed, on_delete=self.action_btn_delete_pressed, on_selectall=self.action_btn_select_all_pressed, on_next_screen=self._next_screen, on_prev_screen=self._prev_screen) self.actionbar.add_widget(self.editcontview) widget = self.ui_creator.propertyviewer.widget if isinstance(widget, Carousel) or\ isinstance(widget, ScreenManager) or\ isinstance(widget, TabbedPanel): self.editcontview.show_action_btn_screen(True) else: self.editcontview.show_action_btn_screen(False) if self.ui_creator.kv_code_input.clicked: self._edit_selected = 'KV' elif self.ui_creator.playground.clicked: self._edit_selected = 'Play' else: self._edit_selected = 'Py' self.ui_creator.playground.clicked = False self.ui_creator.kv_code_input.clicked = False def _prev_screen(self, *args): widget = self.ui_creator.propertyviewer.widget if isinstance(widget, Carousel): widget.load_previous() elif isinstance(widget, ScreenManager): widget.current = widget.previous() elif isinstance(widget, TabbedPanel): index = widget.tab_list.index(widget.current_tab) if len(widget.tab_list) <= index + 1: return widget.switch_to(widget.tab_list[index + 1]) def _next_screen(self, *args): widget = self.ui_creator.propertyviewer.widget if isinstance(widget, Carousel): widget.load_next() elif isinstance(widget, ScreenManager): widget.current = widget.next() elif isinstance(widget, TabbedPanel): index = widget.tab_list.index(widget.current_tab) if index == 0: return widget.switch_to(widget.tab_list[index - 1]) def on_touch_down(self, touch): '''Override of FloatLayout.on_touch_down. Used to determine where touch is down and to call self.actionbar.on_previous ''' if not isinstance(self.actionbar.children[0], EditContView) or\ self.actionbar.collide_point(*touch.pos): return super(FloatLayout, self).on_touch_down(touch) self.actionbar.on_previous(self) return super(FloatLayout, self).on_touch_down(touch) def action_btn_new_pressed(self, *args): '''Event Handler when ActionButton "New" is pressed. ''' if not self._curr_proj_changed: self._show_new_dialog() return self._confirm_dlg = ConfirmationDialog('All unsaved changes will be' ' lost.\n' 'Do you want to continue?') self._confirm_dlg.bind(on_ok=self._show_new_dialog, on_cancel=self._cancel_popup) self._popup = Popup(title='New', content = self._confirm_dlg, size_hint=(None,None),size=('200pt', '150pt'), auto_dismiss=False) self._popup.open() def _show_new_dialog(self, *args): if hasattr(self, '_popup'): self._popup.dismiss() self._new_dialog = NewProjectDialog() self._new_dialog.bind(on_select=self._perform_new, on_cancel=self._cancel_popup) self._popup = Popup(title='New Project', content = self._new_dialog, size_hint=(None,None),size=('650pt', '450pt'), auto_dismiss=False) self._popup.open() def _perform_new(self, *args): '''To load new project ''' if hasattr(self, '_popup'): self._popup.dismiss() self.cleanup() new_proj_dir = os.path.join(get_kivy_designer_dir(), NEW_PROJECT_DIR_NAME) if os.path.exists(new_proj_dir): shutil.rmtree(new_proj_dir) os.mkdir(new_proj_dir) template = self._new_dialog.adapter.selection[0].text kv_file = NEW_PROJECTS[template][0] py_file = NEW_PROJECTS[template][1] templates_dir = os.path.join(os.getcwd(), NEW_TEMPLATES_DIR) shutil.copy(os.path.join(templates_dir, py_file), os.path.join(new_proj_dir, "main.py")) shutil.copy(os.path.join(templates_dir, kv_file), os.path.join(new_proj_dir, "main.kv")) self.ui_creator.playground.sandbox.error_active = True with self.ui_creator.playground.sandbox: self.project_loader.load_new_project(os.path.join(new_proj_dir, "main.kv")) root_wigdet = self.project_loader.get_root_widget() self.ui_creator.playground.add_widget_to_parent(root_wigdet, None, from_undo=True) self.ui_creator.kv_code_input.text = self.project_loader.get_full_str() self.designer_content.update_tree_view(self.project_loader) self._add_designer_content() if self.project_loader.class_rules: for i, _rule in enumerate(self.project_loader.class_rules): widgets.append((_rule.name, 'custom')) self.designer_content.toolbox.add_custom() self.ui_creator.playground.sandbox.error_active = False def cleanup(self): '''To cleanup everything loaded by the current project before loading another project. ''' self.project_loader.cleanup() self.ui_creator.cleanup() self.undo_manager.cleanup() self.designer_content.toolbox.cleanup() for node in self.proj_tree_view.root.nodes[:]: self.proj_tree_view.remove_node(node) for widget in widgets[:]: if widget[1] == 'custom': widgets.remove(widget) self._curr_proj_changed = False self.ui_creator.kv_code_input.text = "" self.designer_content.tab_pannel.list_py_code_inputs = [] for th in self.designer_content.tab_pannel.tab_list[:-1]: self.designer_content.tab_pannel.remove_widget(th) def action_btn_open_pressed(self, *args): '''Event Handler when ActionButton "Open" is pressed. ''' if not self._curr_proj_changed: self._show_open_dialog() return self._confirm_dlg = ConfirmationDialog('All unsaved changes will be ' 'lost.\n' 'Do you want to continue?') self._confirm_dlg.bind(on_ok=self._show_open_dialog, on_cancel=self._cancel_popup) self._popup = Popup(title='Kivy Designer', content = self._confirm_dlg, size_hint=(None,None),size=('200pt', '150pt'), auto_dismiss=False) self._popup.open() def _show_open_dialog(self, *args): '''To show FileBrowser to "Open" a project ''' if hasattr(self, '_popup'): self._popup.dismiss() self._fbrowser = FileBrowser(select_string='Open') def_path = os.getcwd() if not self.project_loader.new_project and self.project_loader.proj_dir: def_path = self.project_loader.proj_dir if self._fbrowser.ids.tabbed_browser.current_tab.text == 'List View': self._fbrowser.ids.list_view.path = def_path else: self._fbrowser.ids.icon_view.path = def_path self._fbrowser.bind(on_success=self._fbrowser_load, on_canceled=self._cancel_popup) self._popup = Popup(title="Open", content = self._fbrowser, size_hint=(0.9, 0.9), auto_dismiss=False) self._popup.open() def _select_class_selected(self, *args): '''Event Handler for 'on_select' event of self._select_class ''' selection = self._select_class.listview.adapter.selection[0].text with self.ui_creator.playground.sandbox: root_widget = self.project_loader.set_root_widget(selection) self.ui_creator.playground.add_widget_to_parent(root_widget, None, from_undo=True) self.ui_creator.kv_code_input.text = self.project_loader.get_root_str() self._select_class_popup.dismiss() def _select_class_cancel(self, *args): '''Event Handler for 'on_cancel' event of self._select_class ''' self._select_class_popup.dismiss() def _fbrowser_load(self, instance): '''Event Handler for 'on_load' event of self._fbrowser ''' if instance.selection == []: return file_path = instance.selection[0] self._popup.dismiss() self._perform_open(file_path) def _perform_open(self, file_path): '''To open a project given by file_path ''' for widget in widgets[:]: if widget[1] == 'custom': widgets.remove(widget) self.cleanup() self.ui_creator.playground.sandbox.error_active = True root_widget = None with self.ui_creator.playground.sandbox: try: self.project_loader.load_project(file_path) if self.project_loader.class_rules: for i, _rule in enumerate(self.project_loader.class_rules): widgets.append((_rule.name, 'custom')) self.designer_content.toolbox.add_custom() #to test listview #root_wigdet = None root_wigdet = self.project_loader.get_root_widget() if not root_wigdet: #Show list box showing widgets self._select_class = SelectClass( self.project_loader.class_rules) self._select_class.bind(on_select=self._select_class_selected, on_cancel=self._select_class_cancel) self._select_class_popup = Popup(title="Select Root Widget", content = self._select_class, size_hint=(0.5, 0.5), auto_dismiss=False) self._select_class_popup.open() else: self.ui_creator.playground.add_widget_to_parent(root_wigdet, None, from_undo=True) self.ui_creator.kv_code_input.text = self.project_loader.get_full_str() self.recent_manager.add_file(file_path) #Record everything for later use self.project_loader.record() self.designer_content.update_tree_view(self.project_loader) self._add_designer_content() except Exception as e: self.statusbar.show_message('Cannot load Project: %s'%(str(e))) self.ui_creator.playground.sandbox.error_active = False def _cancel_popup(self, *args): '''EventHandler for all self._popup when self._popup.content emits 'on_cancel' or equivalent. ''' self._proj_modified_outside = False self._popup.dismiss() def action_btn_save_pressed(self, *args): '''Event Handler when ActionButton "Save" is pressed. ''' if self.project_loader.root_rule: try: if self.project_loader.new_project: self.action_btn_save_as_pressed() return else: self.project_loader.save_project() projdir = self.project_loader.proj_dir self.project_loader.cleanup(stop_watcher=False) self.ui_creator.playground.cleanup() self.project_loader.load_project(projdir) root_wigdet = self.project_loader.get_root_widget() self.ui_creator.playground.add_widget_to_parent(root_wigdet, None, from_undo=True, from_kv=True) self._curr_proj_changed = False self.statusbar.show_message('Project saved successfully') except: self.statusbar.show_message('Cannot save project') def action_btn_save_as_pressed(self, *args): '''Event Handler when ActionButton "Save As" is pressed. ''' if self.project_loader.root_rule: self._curr_proj_changed = False self._save_as_browser = FileBrowser(select_string='Save') def_path = os.getcwd() if not self.project_loader.new_project and self.project_loader.proj_dir: def_path = self.project_loader.proj_dir if self._save_as_browser.ids.tabbed_browser.current_tab.text == 'List View': self._save_as_browser.ids.list_view.path = def_path else: self._save_as_browser.ids.icon_view.path = def_path self._save_as_browser.bind(on_success=self._perform_save_as, on_canceled=self._cancel_popup) self._popup = Popup(title="Enter Folder Name", content = self._save_as_browser, size_hint=(0.9, 0.9), auto_dismiss=False) self._popup.open() def _perform_save_as(self, instance): '''Event handler for 'on_success' event of self._save_as_browser ''' if hasattr(self, '_popup'): self._popup.dismiss() proj_dir = '' if instance.ids.tabbed_browser.current_tab.text == 'List View': proj_dir = instance.ids.list_view.path else: proj_dir = instance.ids.icon_view.path proj_dir = os.path.join(proj_dir, instance.filename) #try: if True: self.project_loader.save_project(proj_dir) self.recent_manager.add_file(proj_dir) projdir = self.project_loader.proj_dir self.project_loader.cleanup() self.ui_creator.playground.cleanup() self.project_loader.load_project(projdir) root_wigdet = self.project_loader.get_root_widget() self.ui_creator.playground.add_widget_to_parent(root_wigdet, None, from_undo=True) self.statusbar.show_message('Project saved successfully') #except: # self.statusbar.show_message('Cannot save project') def action_btn_settings_pressed(self, *args): self.designer_settings.parent = None self._popup = Popup(title="Kivy Designer Settings", content = self.designer_settings, size_hint=(None, None), size=(600, 400), auto_dismiss=False) self._popup.open() def action_btn_recent_files_pressed(self, *args): '''Event Handler when ActionButton "Recent Files" is pressed. ''' pass def fill_recent_menu(self, *args): recent_menu = self.recent_files_cont_menu for _file in self.recent_manager.list_files: act_btn = DesignerActionButton(text=_file, shorten=True) recent_menu.add_widget(act_btn) act_btn.bind(on_release=self._recent_file_release) def _recent_file_release(self, instance, *args): '''Event Handler for 'on_select' event of self._recent_dlg. ''' self._perform_open(instance.text) def action_btn_quit_pressed(self, *args): '''Event Handler when ActionButton "Quit" is pressed. ''' App.get_running_app().stop() def action_btn_undo_pressed(self, *args): '''Event Handler when ActionButton "Undo" is pressed. ''' if self._edit_selected == 'Play': self.undo_manager.do_undo() elif self._edit_selected == 'KV': self.ui_creator.kv_code_input.do_undo() elif self._edit_selected == 'Py': for code_input in self.designer_content.tab_pannel.list_py_code_inputs: if code_input.clicked == True: code_input.clicked = False code_input.do_undo() def action_btn_redo_pressed(self, *args): '''Event Handler when ActionButton "Redo" is pressed. ''' if self._edit_selected == 'Play': self.undo_manager.do_redo() elif self._edit_selected == 'KV': self.ui_creator.kv_code_input.do_redo() elif self._edit_selected == 'Py': for code_input in self.designer_content.tab_pannel.list_py_code_inputs: if code_input.clicked == True: code_input.clicked = False code_input.do_redo() def action_btn_cut_pressed(self, *args): '''Event Handler when ActionButton "Cut" is pressed. ''' if self._edit_selected == 'Play': self.ui_creator.playground.do_cut() elif self._edit_selected == 'KV': self.ui_creator.kv_code_input.do_cut() elif self._edit_selected == 'Py': for code_input in self.designer_content.tab_pannel.list_py_code_inputs: if code_input.clicked == True: code_input.clicked = False code_input.do_cut() def action_btn_copy_pressed(self, *args): '''Event Handler when ActionButton "Copy" is pressed. ''' if self._edit_selected == 'Play': self.ui_creator.playground.do_copy() elif self._edit_selected == 'KV': self.ui_creator.kv_code_input.do_copy() elif self._edit_selected == 'Py': for code_input in self.designer_content.tab_pannel.list_py_code_inputs: if code_input.clicked == True: code_input.clicked = False code_input.do_copy() def action_btn_paste_pressed(self, *args): '''Event Handler when ActionButton "Paste" is pressed. ''' if self._edit_selected == 'Play': self.ui_creator.playground.do_paste() elif self._edit_selected == 'KV': self.ui_creator.kv_code_input.do_paste() elif self._edit_selected == 'Py': for code_input in self.designer_content.tab_pannel.list_py_code_inputs: if code_input.clicked == True: code_input.clicked = False code_input.do_paste() def action_btn_delete_pressed(self, *args): '''Event Handler when ActionButton "Delete" is pressed. ''' if self._edit_selected == 'Play': self.ui_creator.playground.do_delete() elif self._edit_selected == 'KV': self.ui_creator.kv_code_input.do_delete() elif self._edit_selected == 'Py': for code_input in self.designer_content.tab_pannel.list_py_code_inputs: if code_input.clicked == True: code_input.clicked = False code_input.do_delete() def action_btn_select_all_pressed(self, *args): '''Event Handler when ActionButton "Select All" is pressed. ''' if self._edit_selected == 'Play': self.ui_creator.playground.do_select_all() elif self._edit_selected == 'KV': self.ui_creator.kv_code_input.do_select_all() elif self._edit_selected == 'Py': for code_input in self.designer_content.tab_pannel.list_py_code_inputs: if code_input.clicked == True: code_input.clicked = False code_input.do_select_all() def action_btn_add_custom_widget_press(self, *args): '''Event Handler when ActionButton "Add Custom Widget" is pressed. ''' self._custom_browser = FileBrowser(select_string='Add') self._custom_browser.bind(on_success=self._custom_browser_load, on_canceled=self._cancel_popup) self._popup = Popup(title="Add Custom Widget", content = self._custom_browser, size_hint=(0.9, 0.9), auto_dismiss=False) self._popup.open() def _custom_browser_load(self, instance): '''Event Handler for 'on_success' event of self._custom_browser ''' file_path = instance.selection[0] self._popup.dismiss() self.ui_creator.playground.sandbox.error_active = True with self.ui_creator.playground.sandbox: try: self.project_loader.add_custom_widget(file_path) self.designer_content.toolbox.cleanup() for _rule in (self.project_loader.custom_widgets): widgets.append((_rule.name, 'custom')) self.designer_content.toolbox.add_custom() except ProjectLoaderException as e: self.statusbar.show_message('Cannot load widget. %s'%str(e)) self.ui_creator.playground.sandbox.error_active = False def action_chk_btn_toolbox_active(self, chk_btn): '''Event Handler when ActionCheckButton "Toolbox" is activated. ''' if chk_btn.checkbox.active: self._toolbox_parent.add_widget(self.designer_content.splitter_tree) self.designer_content.splitter_tree.width = self._toolbox_width else: self._toolbox_parent = self.designer_content.splitter_tree.parent self._toolbox_parent.remove_widget(self.designer_content.splitter_tree) self._toolbox_width = self.designer_content.splitter_tree.width self.designer_content.splitter_tree.width = 0 def action_chk_btn_property_viewer_active(self, chk_btn): '''Event Handler when ActionCheckButton "Property Viewer" is activated. ''' if chk_btn.checkbox.active: self._toggle_splitter_widget_tree() if self.ui_creator.splitter_widget_tree.parent is None: self._splitter_widget_tree_parent.add_widget(self.ui_creator.splitter_widget_tree) self.ui_creator.splitter_widget_tree.width = self._splitter_widget_tree_width add_tree = False if self.ui_creator.grid_widget_tree.parent is not None: add_tree = True self.ui_creator.splitter_property.size_hint_y = None self.ui_creator.splitter_property.height = 300 self._splitter_property_parent.clear_widgets() if add_tree: self._splitter_property_parent.add_widget(self.ui_creator.grid_widget_tree) self._splitter_property_parent.add_widget(self.ui_creator.splitter_property) else: self._splitter_property_parent = self.ui_creator.splitter_property.parent self._splitter_property_parent.remove_widget(self.ui_creator.splitter_property) self._toggle_splitter_widget_tree() def action_chk_btn_widget_tree_active(self, chk_btn): '''Event Handler when ActionCheckButton "Widget Tree" is activated. ''' if chk_btn.checkbox.active: self._toggle_splitter_widget_tree() add_prop = False if self.ui_creator.splitter_property.parent is not None: add_prop = True self._grid_widget_tree_parent.clear_widgets() self._grid_widget_tree_parent.add_widget(self.ui_creator.grid_widget_tree) if add_prop: self._grid_widget_tree_parent.add_widget(self.ui_creator.splitter_property) self.ui_creator.splitter_property.size_hint_y = None self.ui_creator.splitter_property.height = 300 else: self._grid_widget_tree_parent = self.ui_creator.grid_widget_tree.parent self._grid_widget_tree_parent.remove_widget(self.ui_creator.grid_widget_tree) self.ui_creator.splitter_property.size_hint_y = 1 self._toggle_splitter_widget_tree() def _toggle_splitter_widget_tree(self): '''To show/hide splitter_widget_tree ''' if self.ui_creator.splitter_widget_tree.parent is not None and\ self.ui_creator.splitter_property.parent is None and\ self.ui_creator.grid_widget_tree.parent is None: self._splitter_widget_tree_parent = self.ui_creator.splitter_widget_tree.parent self._splitter_widget_tree_parent.remove_widget(self.ui_creator.splitter_widget_tree) self._splitter_widget_tree_width = self.ui_creator.splitter_widget_tree.width self.ui_creator.splitter_widget_tree.width = 0 elif self.ui_creator.splitter_widget_tree.parent is None: self._splitter_widget_tree_parent.add_widget(self.ui_creator.splitter_widget_tree) self.ui_creator.splitter_widget_tree.width = self._splitter_widget_tree_width def action_chk_btn_status_bar_active(self, chk_btn): '''Event Handler when ActionCheckButton "StatusBar" is activated. ''' if chk_btn.checkbox.active: self._statusbar_parent.add_widget(self.statusbar) self.statusbar.height = self._statusbar_height else: self._statusbar_parent = self.statusbar.parent self._statusbar_height = self.statusbar.height self._statusbar_parent.remove_widget(self.statusbar) self.statusbar.height = 0 def action_chk_btn_kv_area_active(self, chk_btn): '''Event Handler when ActionCheckButton "KVLangArea" is activated. ''' if chk_btn.checkbox.active: self.ui_creator.splitter_kv_code_input.height = self._kv_area_height self._kv_area_parent.add_widget(self.ui_creator.splitter_kv_code_input) else: self._kv_area_parent = self.ui_creator.splitter_kv_code_input.parent self._kv_area_height = self.ui_creator.splitter_kv_code_input.height self.ui_creator.splitter_kv_code_input.height = 0 self._kv_area_parent.remove_widget(self.ui_creator.splitter_kv_code_input) def _error_adding_file(self, *args): '''Event Handler for 'on_error' event of self._add_file_dlg ''' self.statusbar.show_message('Error while adding file to project') self._popup.dismiss() def _added_file(self, *args): '''Event Handler for 'on_added' event of self._add_file_dlg ''' self.statusbar.show_message('File successfully added to project') self._popup.dismiss() if self._add_file_dlg.target_file[3:] == '.py': self.designer_content.add_file_to_tree_view( self._add_file_dlg.target_file) def action_btn_add_file_pressed(self, *args): '''Event Handler when ActionButton "Add File" is pressed. ''' self._add_file_dlg = AddFileDialog(self.project_loader) self._add_file_dlg.bind(on_added=self._added_file, on_error=self._error_adding_file, on_cancel=self._cancel_popup) self._popup = Popup(title="Add File", content = self._add_file_dlg, size_hint=(None, None), size=(400, 300), auto_dismiss=False) self._popup.open() def action_btn_project_pref_pressed(self, *args): '''Event Handler when ActionButton "Project Prefences" is pressed. ''' self.proj_settings = ProjectSettings(proj_loader=self.project_loader) self.proj_settings.load_proj_settings() self.proj_settings.bind(on_close=self._cancel_popup) self._popup = Popup(title="Project Preferences", content = self.proj_settings, size_hint=(None, None), size=(600, 400), auto_dismiss=False) self._popup.open() def action_btn_run_project_pressed(self, *args): '''Event Handler when ActionButton "Run" is pressed. ''' if self.project_loader.file_list == []: return args = '' envs = '' python_path = self.designer_settings.config_parser.getdefault( 'global', 'python_shell_path', '') if python_path == '': self.statusbar.show_message("Python Shell Path not specified," " please specify it before running" " project") return if self.proj_settings and self.proj_settings.config_parser: args = self.proj_settings.config_parser.getdefault('arguments', 'arg', '') envs = self.proj_settings.config_parser.getdefault('env variables', 'env', '') for env in envs.split(' '): self.ui_creator.kivy_console.environment[env[:env.find('=')]] = env[env.find('=')+1:] for _file in self.project_loader.file_list: if 'main.py' in os.path.basename(_file): self.ui_creator.kivy_console.stdin.write('%s %s %s'% (python_path, _file, args)) self.ui_creator.tab_pannel.switch_to( self.ui_creator.tab_pannel.tab_list[2]) return self.ui_creator.kivy_console.stdin.write('%s %s %s'% (python_path, self.project_loader._app_file, args)) self.ui_creator.tab_pannel.switch_to( self.ui_creator.tab_pannel.tab_list[2]) def on_sandbox_getting_exception(self, *args): '''Event Handler for :class:`~designer.uix.designer_sandbox.DesignerSandbox` on_getting_exception event. This function will add exception string in error_console. ''' s = traceback.format_list(traceback.extract_tb( self.ui_creator.playground.sandbox.tb)) s = '\n'.join(s) to_insert = "Exception:\n" + s + '\n' + \ "{!r}".format(self.ui_creator.playground.sandbox.exception) text = self.ui_creator.error_console.text + to_insert + '\n\n' self.ui_creator.error_console.text = text if self.ui_creator.playground.sandbox.error_active: self.ui_creator.tab_pannel.switch_to( self.ui_creator.tab_pannel.tab_list[0]) self.ui_creator.playground.sandbox.error_active = False
class Designer(FloatLayout): '''Designer is the Main Window class of Kivy Designer :data:`message` is a :class:`~kivy.properties.StringProperty` ''' designer_console = ObjectProperty(None) '''Instance of :class:`designer.designer_console.ConsoleDialog` ''' statusbar = ObjectProperty(None) '''Reference to the :class:`~designer.statusbar.StatusBar` instance. :data:`statusbar` is a :class:`~kivy.properties.ObjectProperty` ''' editcontview = ObjectProperty(None) '''Reference to the :class:`~designer.uix.EditContView` instance. :data:`v` is a :class:`~kivy.properties.ObjectProperty` ''' actionbar = ObjectProperty(None) '''Reference to the :class:`~kivy.actionbar.ActionBar` instance. ActionBar is used as a MenuBar to display bunch of menu items. :data:`actionbar` is a :class:`~kivy.properties.ObjectProperty` ''' undo_manager = ObjectProperty(UndoManager()) '''Reference to the :class:`~designer.UndoManager` instance. :data:`undo_manager` is a :class:`~kivy.properties.ObjectProperty` ''' project_watcher = ObjectProperty(None) '''Reference to the :class:`~designer.project_watcher.ProjectWatcher`. :data:`project_watcher` is a :class:`~kivy.properties.ObjectProperty` ''' project_loader = ObjectProperty(None) '''Reference to the :class:`~designer.project_loader.ProjectLoader`. :data:`project_loader` is a :class:`~kivy.properties.ObjectProperty` ''' proj_settings = ObjectProperty(None) '''Reference of :class:`~designer.project_settings.ProjectSettings`. :data:`proj_settings` is a :class:`~kivy.properties.ObjectProperty` ''' _curr_proj_changed = BooleanProperty(False) '''Specifies whether current project has been changed inside Kivy Designer :data:`_curr_proj_changed` is a :class:`~kivy.properties.BooleanProperty` ''' _proj_modified_outside = BooleanProperty(False) '''Specifies whether current project has been changed outside Kivy Designer :data:`_proj_modified_outside` is a :class:`~kivy.properties.BooleanProperty` ''' ui_creator = ObjectProperty(None) '''Reference to :class:`~designer.ui_creator.UICreator` instance. :data:`ui_creator` is a :class:`~kivy.properties.ObjectProperty` ''' designer_content = ObjectProperty(None) '''Reference to :class:`~designer.designer_content.DesignerContent` instance. :data:`designer_content` is a :class:`~kivy.properties.ObjectProperty` ''' proj_tree_view = ObjectProperty(None) '''Reference to Project Tree instance :data:`proj_tree_view` is a :class:`~kivy.properties.ObjectProperty` ''' designer_settings = ObjectProperty(None) '''Reference of :class:`~designer.designer_settings.DesignerSettings`. :data:`designer_settings` is a :class:`~kivy.properties.ObjectProperty` ''' start_page = ObjectProperty(None) '''Reference of :class:`~designer.start_page.DesignerStartPage`. :data:`start_page` is a :class:`~kivy.properties.ObjectProperty` ''' recent_files_cont_menu = ObjectProperty(None) '''The context sub menu, containing the recently opened/saved projects. Reference of :class:`~designer.uix.contextual.ContextSubMenu`. :data:`recent_files_cont_menu` is a :class:`~kivy.properties.ObjectProperty` ''' def __init__(self, **kwargs): super(Designer, self).__init__(**kwargs) self.project_watcher = ProjectWatcher(self.project_modified) self.project_loader = ProjectLoader(self.project_watcher) self.recent_manager = RecentManager() self.widget_to_paste = None self.designer_content = DesignerContent(size_hint=(1, None)) self.designer_settings = DesignerSettings() self.designer_settings.bind(on_config_change=self._config_change) self.designer_settings.load_settings() self.designer_settings.bind(on_close=self._cancel_popup) Clock.schedule_interval( self.project_loader.perform_auto_save, int( self.designer_settings.config_parser.getdefault( 'global', 'auto_save_time', 5)) * 60) def show_help(self, *args): '''Event handler for 'on_help' event of self.start_page ''' self.help_dlg = HelpDialog() self._popup = Popup(title='Kivy Designer Help', content=self.help_dlg, size_hint=(0.95, 0.95), auto_dismiss=False) self._popup.open() self.help_dlg.bind(on_cancel=self._cancel_popup) self.help_dlg.rst.source = 'help.rst' def _config_change(self, *args): '''Event Handler for 'on_config_change' event of self.designer_settings. ''' Clock.unschedule(self.project_loader.perform_auto_save) Clock.schedule_interval( self.project_loader.perform_auto_save, int( self.designer_settings.config_parser.getdefault( 'global', 'auto_save_time', 5)) * 60) self.ui_creator.kv_code_input.reload_kv = \ bool(self.designer_settings.config_parser.getdefault( 'global', 'reload_kv', True)) self.recent_manager.max_recent_files = \ int(self.designer_settings.config_parser.getdefault( 'global', 'num_recent_files', 5)) def _add_designer_content(self): '''Add designer_content to Designer, when a project is loaded ''' for _child in self.children[:]: if _child == self.designer_content: return self.remove_widget(self.start_page) self.add_widget(self.designer_content, 1) self.ids['actn_btn_save'].disabled = False self.ids['actn_btn_save_as'].disabled = False self.ids['actn_chk_proj_tree'].disabled = False self.ids['actn_chk_prop_event'].disabled = False self.ids['actn_chk_widget_tree'].disabled = False self.ids['actn_chk_status_bar'].disabled = False self.ids['actn_chk_kv_lang_area'].disabled = False self.ids['actn_btn_add_file'].disabled = False self.ids['actn_btn_custom_widget'].disabled = False self.ids['actn_btn_proj_pref'].disabled = False self.ids['actn_btn_run_proj'].disabled = False def on_statusbar_height(self, *args): '''Callback for statusbar.height ''' self.designer_content.y = self.statusbar.height self.on_height(*args) def on_actionbar_height(self, *args): '''Callback for actionbar.height ''' self.on_height(*args) def on_height(self, *args): '''Callback for self.height ''' if self.actionbar and self.statusbar: self.designer_content.height = self.height - \ self.actionbar.height - self.statusbar.height self.designer_content.y = self.statusbar.height def project_modified(self, *args): '''Event Handler called when Project is modified outside Kivy Designer ''' #To dispatch modified event only once for all files/folders of proj_dir if self._proj_modified_outside: return self._confirm_dlg = ConfirmationDialog( message="Current Project has been modified\n" "outside the Kivy Designer.\nDo you want to reload project?") self._confirm_dlg.bind(on_ok=self._perform_reload, on_cancel=self._cancel_popup) self._popup = Popup(title='Kivy Designer', content=self._confirm_dlg, size_hint=(None, None), size=('200pt', '150pt'), auto_dismiss=False) self._popup.open() self._proj_modified_outside = True def _perform_reload(self, *args): '''Perform reload of project after it is modified ''' #Perform reload of project after it is modified self._popup.dismiss() self.project_watcher.allow_event_dispatch = False self._perform_open(self.project_loader.proj_dir) self.project_watcher.allow_event_dispatch = True self._proj_modified_outside = False def on_show_edit(self, *args): '''Event Handler of 'on_show_edit' event. This will show EditContView in ActionBar ''' if isinstance(self.actionbar.children[0], EditContView): return if self.editcontview is None: self.editcontview = EditContView( on_undo=self.action_btn_undo_pressed, on_redo=self.action_btn_redo_pressed, on_cut=self.action_btn_cut_pressed, on_copy=self.action_btn_copy_pressed, on_paste=self.action_btn_paste_pressed, on_delete=self.action_btn_delete_pressed, on_selectall=self.action_btn_select_all_pressed, on_next_screen=self._next_screen, on_prev_screen=self._prev_screen) self.actionbar.add_widget(self.editcontview) widget = self.ui_creator.propertyviewer.widget if isinstance(widget, Carousel) or\ isinstance(widget, ScreenManager) or\ isinstance(widget, TabbedPanel): self.editcontview.show_action_btn_screen(True) else: self.editcontview.show_action_btn_screen(False) if self.ui_creator.kv_code_input.clicked: self._edit_selected = 'KV' elif self.ui_creator.playground.clicked: self._edit_selected = 'Play' else: self._edit_selected = 'Py' self.ui_creator.playground.clicked = False self.ui_creator.kv_code_input.clicked = False def _prev_screen(self, *args): '''Event handler for 'on_prev_screen' for self.editcontview ''' widget = self.ui_creator.propertyviewer.widget if isinstance(widget, Carousel): widget.load_previous() elif isinstance(widget, ScreenManager): widget.current = widget.previous() elif isinstance(widget, TabbedPanel): index = widget.tab_list.index(widget.current_tab) if len(widget.tab_list) <= index + 1: return widget.switch_to(widget.tab_list[index + 1]) def _next_screen(self, *args): '''Event handler for 'on_next_screen' for self.editcontview ''' widget = self.ui_creator.propertyviewer.widget if isinstance(widget, Carousel): widget.load_next() elif isinstance(widget, ScreenManager): widget.current = widget.next() elif isinstance(widget, TabbedPanel): index = widget.tab_list.index(widget.current_tab) if index == 0: return widget.switch_to(widget.tab_list[index - 1]) def on_touch_down(self, touch): '''Override of FloatLayout.on_touch_down. Used to determine where touch is down and to call self.actionbar.on_previous ''' if not isinstance(self.actionbar.children[0], EditContView) or\ self.actionbar.collide_point(*touch.pos): return super(FloatLayout, self).on_touch_down(touch) self.actionbar.on_previous(self) return super(FloatLayout, self).on_touch_down(touch) def action_btn_new_pressed(self, *args): '''Event Handler when ActionButton "New" is pressed. ''' if not self._curr_proj_changed: self._show_new_dialog() return self._confirm_dlg = ConfirmationDialog('All unsaved changes will be' ' lost.\n' 'Do you want to continue?') self._confirm_dlg.bind(on_ok=self._show_new_dialog, on_cancel=self._cancel_popup) self._popup = Popup(title='New', content=self._confirm_dlg, size_hint=(None, None), size=('200pt', '150pt'), auto_dismiss=False) self._popup.open() def _show_new_dialog(self, *args): if hasattr(self, '_popup'): self._popup.dismiss() self._new_dialog = NewProjectDialog() self._new_dialog.bind(on_select=self._perform_new, on_cancel=self._cancel_popup) self._popup = Popup(title='New Project', content=self._new_dialog, size_hint=(None, None), size=('650pt', '450pt'), auto_dismiss=False) self._popup.open() def _perform_new(self, *args): '''To load new project ''' if hasattr(self, '_popup'): self._popup.dismiss() self.cleanup() new_proj_dir = os.path.join(get_kivy_designer_dir(), NEW_PROJECT_DIR_NAME) if os.path.exists(new_proj_dir): shutil.rmtree(new_proj_dir) os.mkdir(new_proj_dir) template = self._new_dialog.adapter.selection[0].text kv_file = NEW_PROJECTS[template][0] py_file = NEW_PROJECTS[template][1] _dir = os.path.dirname(designer.__file__) _dir = os.path.split(_dir)[0] templates_dir = os.path.join(_dir, NEW_TEMPLATES_DIR) shutil.copy(os.path.join(templates_dir, py_file), os.path.join(new_proj_dir, "main.py")) shutil.copy(os.path.join(templates_dir, kv_file), os.path.join(new_proj_dir, "main.kv")) self.ui_creator.playground.sandbox.error_active = True with self.ui_creator.playground.sandbox: self.project_loader.load_new_project( os.path.join(new_proj_dir, "main.kv")) root_wigdet = self.project_loader.get_root_widget() self.ui_creator.playground.add_widget_to_parent(root_wigdet, None, from_undo=True) self.ui_creator.kv_code_input.text = \ self.project_loader.get_full_str() self.designer_content.update_tree_view(self.project_loader) self._add_designer_content() if self.project_loader.class_rules: for i, _rule in enumerate(self.project_loader.class_rules): widgets.append((_rule.name, 'custom')) self.designer_content.toolbox.add_custom() self.ui_creator.playground.sandbox.error_active = False def cleanup(self): '''To cleanup everything loaded by the current project before loading another project. ''' self.project_loader.cleanup() self.ui_creator.cleanup() self.undo_manager.cleanup() self.designer_content.toolbox.cleanup() for node in self.proj_tree_view.root.nodes[:]: self.proj_tree_view.remove_node(node) for widget in widgets[:]: if widget[1] == 'custom': widgets.remove(widget) self._curr_proj_changed = False self.ui_creator.kv_code_input.text = "" self.designer_content.tab_pannel.list_py_code_inputs = [] for th in self.designer_content.tab_pannel.tab_list[:-1]: self.designer_content.tab_pannel.remove_widget(th) def action_btn_open_pressed(self, *args): '''Event Handler when ActionButton "Open" is pressed. ''' if not self._curr_proj_changed: self._show_open_dialog() return self._confirm_dlg = ConfirmationDialog('All unsaved changes will be ' 'lost.\n' 'Do you want to continue?') self._confirm_dlg.bind(on_ok=self._show_open_dialog, on_cancel=self._cancel_popup) self._popup = Popup(title='Kivy Designer', content=self._confirm_dlg, size_hint=(None, None), size=('200pt', '150pt'), auto_dismiss=False) self._popup.open() def _show_open_dialog(self, *args): '''To show FileBrowser to "Open" a project ''' if hasattr(self, '_popup'): self._popup.dismiss() self._fbrowser = FileBrowser(select_string='Open') def_path = os.getcwd() if not self.project_loader.new_project and \ self.project_loader.proj_dir: def_path = self.project_loader.proj_dir if self._fbrowser.ids.tabbed_browser.current_tab.text == 'List View': self._fbrowser.ids.list_view.path = def_path else: self._fbrowser.ids.icon_view.path = def_path self._fbrowser.bind(on_success=self._fbrowser_load, on_canceled=self._cancel_popup) self._popup = Popup(title="Open", content=self._fbrowser, size_hint=(0.9, 0.9), auto_dismiss=False) self._popup.open() def _select_class_selected(self, *args): '''Event Handler for 'on_select' event of self._select_class ''' selection = self._select_class.listview.adapter.selection[0].text with self.ui_creator.playground.sandbox: root_widget = self.project_loader.set_root_widget(selection) self.ui_creator.playground.add_widget_to_parent(root_widget, None, from_undo=True) self.ui_creator.kv_code_input.text = \ self.project_loader.get_root_str() self._select_class_popup.dismiss() def _select_class_cancel(self, *args): '''Event Handler for 'on_cancel' event of self._select_class ''' self._select_class_popup.dismiss() def _fbrowser_load(self, instance): '''Event Handler for 'on_load' event of self._fbrowser ''' if instance.selection == []: return file_path = instance.selection[0] self._popup.dismiss() self._perform_open(file_path) def _perform_open(self, file_path): '''To open a project given by file_path ''' for widget in widgets[:]: if widget[1] == 'custom': widgets.remove(widget) self.cleanup() self.ui_creator.playground.sandbox.error_active = True root_widget = None with self.ui_creator.playground.sandbox: try: self.project_loader.load_project(file_path) if self.project_loader.class_rules: for i, _rule in enumerate(self.project_loader.class_rules): widgets.append((_rule.name, 'custom')) self.designer_content.toolbox.add_custom() #to test listview #root_wigdet = None root_wigdet = self.project_loader.get_root_widget() if not root_wigdet: #Show list box showing widgets self._select_class = SelectClass( self.project_loader.class_rules) self._select_class.bind( on_select=self._select_class_selected, on_cancel=self._select_class_cancel) self._select_class_popup = Popup( title="Select Root Widget", content=self._select_class, size_hint=(0.5, 0.5), auto_dismiss=False) self._select_class_popup.open() else: self.ui_creator.playground.add_widget_to_parent( root_wigdet, None, from_undo=True) self.ui_creator.kv_code_input.text = \ self.project_loader.get_full_str() self.recent_manager.add_file(file_path) #Record everything for later use self.project_loader.record() self.designer_content.update_tree_view(self.project_loader) self._add_designer_content() except Exception as e: self.statusbar.show_message('Cannot load Project: %s' % (str(e))) self.ui_creator.playground.sandbox.error_active = False def _cancel_popup(self, *args): '''EventHandler for all self._popup when self._popup.content emits 'on_cancel' or equivalent. ''' self._proj_modified_outside = False self._popup.dismiss() def action_btn_save_pressed(self, *args): '''Event Handler when ActionButton "Save" is pressed. ''' if self.project_loader.root_rule: try: if self.project_loader.new_project: self.action_btn_save_as_pressed() return else: self.project_loader.save_project() projdir = self.project_loader.proj_dir self.project_loader.cleanup(stop_watcher=False) self.ui_creator.playground.cleanup() self.project_loader.load_project(projdir) root_wigdet = self.project_loader.get_root_widget() self.ui_creator.playground.add_widget_to_parent( root_wigdet, None, from_undo=True, from_kv=True) self._curr_proj_changed = False self.statusbar.show_message('Project saved successfully') except: self.statusbar.show_message('Cannot save project') def action_btn_save_as_pressed(self, *args): '''Event Handler when ActionButton "Save As" is pressed. ''' if self.project_loader.root_rule: self._curr_proj_changed = False self._save_as_browser = FileBrowser(select_string='Save') def_path = os.getcwd() if not self.project_loader.new_project and \ self.project_loader.proj_dir: def_path = self.project_loader.proj_dir if self._save_as_browser.ids.tabbed_browser.current_tab.text == \ 'List View': self._save_as_browser.ids.list_view.path = def_path else: self._save_as_browser.ids.icon_view.path = def_path self._save_as_browser.bind(on_success=self._perform_save_as, on_canceled=self._cancel_popup) self._popup = Popup(title="Enter Folder Name", content=self._save_as_browser, size_hint=(0.9, 0.9), auto_dismiss=False) self._popup.open() def _perform_save_as(self, instance): '''Event handler for 'on_success' event of self._save_as_browser ''' if hasattr(self, '_popup'): self._popup.dismiss() proj_dir = '' if instance.ids.tabbed_browser.current_tab.text == 'List View': proj_dir = instance.ids.list_view.path else: proj_dir = instance.ids.icon_view.path proj_dir = os.path.join(proj_dir, instance.filename) try: self.project_loader.save_project(proj_dir) self.recent_manager.add_file(proj_dir) projdir = self.project_loader.proj_dir self.project_loader.cleanup() self.ui_creator.playground.cleanup() self.project_loader.load_project(projdir) root_wigdet = self.project_loader.get_root_widget() self.ui_creator.playground.add_widget_to_parent(root_wigdet, None, from_undo=True) self.statusbar.show_message('Project saved successfully') except: self.statusbar.show_message('Cannot save project') def action_btn_settings_pressed(self, *args): '''Event handler for 'on_release' event of DesignerActionButton "Settings" ''' self.designer_settings.parent = None self._popup = Popup(title="Kivy Designer Settings", content=self.designer_settings, size_hint=(None, None), size=(600, 400), auto_dismiss=False) self._popup.open() def action_btn_recent_files_pressed(self, *args): '''Event Handler when ActionButton "Recent Files" is pressed. ''' pass def fill_recent_menu(self, *args): '''Fill self.recent_files_cont_menu with DesignerActionButton of all Recent Files ''' recent_menu = self.recent_files_cont_menu for _file in self.recent_manager.list_files: act_btn = DesignerActionButton(text=_file, shorten=True) recent_menu.add_widget(act_btn) act_btn.bind(on_release=self._recent_file_release) def _recent_file_release(self, instance, *args): '''Event Handler for 'on_select' event of self._recent_dlg. ''' self._perform_open(instance.text) def action_btn_quit_pressed(self, *args): '''Event Handler when ActionButton "Quit" is pressed. ''' App.get_running_app().stop() def action_btn_undo_pressed(self, *args): '''Event Handler when ActionButton "Undo" is pressed. ''' if self._edit_selected == 'Play': self.undo_manager.do_undo() elif self._edit_selected == 'KV': self.ui_creator.kv_code_input.do_undo() elif self._edit_selected == 'Py': list_py = self.designer_content.tab_pannel.list_py_code_inputs for code_input in list_py: if code_input.clicked is True: code_input.clicked = False code_input.do_undo() def action_btn_redo_pressed(self, *args): '''Event Handler when ActionButton "Redo" is pressed. ''' if self._edit_selected == 'Play': self.undo_manager.do_redo() elif self._edit_selected == 'KV': self.ui_creator.kv_code_input.do_redo() elif self._edit_selected == 'Py': list_py = self.designer_content.tab_pannel.list_py_code_inputs for code_input in list_py: if code_input.clicked is True: code_input.clicked = False code_input.do_redo() def action_btn_cut_pressed(self, *args): '''Event Handler when ActionButton "Cut" is pressed. ''' if self._edit_selected == 'Play': self.ui_creator.playground.do_cut() elif self._edit_selected == 'KV': self.ui_creator.kv_code_input.do_cut() elif self._edit_selected == 'Py': list_py = self.designer_content.tab_pannel.list_py_code_inputs for code_input in list_py: if code_input.clicked is True: code_input.clicked = False code_input.do_cut() def action_btn_copy_pressed(self, *args): '''Event Handler when ActionButton "Copy" is pressed. ''' if self._edit_selected == 'Play': self.ui_creator.playground.do_copy() elif self._edit_selected == 'KV': self.ui_creator.kv_code_input.do_copy() elif self._edit_selected == 'Py': list_py = self.designer_content.tab_pannel.list_py_code_inputs for code_input in list_py: if code_input.clicked is True: code_input.clicked = False code_input.do_copy() def action_btn_paste_pressed(self, *args): '''Event Handler when ActionButton "Paste" is pressed. ''' if self._edit_selected == 'Play': self.ui_creator.playground.do_paste() elif self._edit_selected == 'KV': self.ui_creator.kv_code_input.do_paste() elif self._edit_selected == 'Py': list_py = self.designer_content.tab_pannel.list_py_code_inputs for code_input in list_py: if code_input.clicked is True: code_input.clicked = False code_input.do_paste() def action_btn_delete_pressed(self, *args): '''Event Handler when ActionButton "Delete" is pressed. ''' if self._edit_selected == 'Play': self.ui_creator.playground.do_delete() elif self._edit_selected == 'KV': self.ui_creator.kv_code_input.do_delete() elif self._edit_selected == 'Py': list_py = self.designer_content.tab_pannel.list_py_code_inputs for code_input in list_py: if code_input.clicked is True: code_input.clicked = False code_input.do_delete() def action_btn_select_all_pressed(self, *args): '''Event Handler when ActionButton "Select All" is pressed. ''' if self._edit_selected == 'Play': self.ui_creator.playground.do_select_all() elif self._edit_selected == 'KV': self.ui_creator.kv_code_input.do_select_all() elif self._edit_selected == 'Py': list_py = self.designer_content.tab_pannel.list_py_code_inputs for code_input in list_py: if code_input.clicked is True: code_input.clicked = False code_input.do_select_all() def action_btn_add_custom_widget_press(self, *args): '''Event Handler when ActionButton "Add Custom Widget" is pressed. ''' self._custom_browser = FileBrowser(select_string='Add') self._custom_browser.bind(on_success=self._custom_browser_load, on_canceled=self._cancel_popup) self._popup = Popup(title="Add Custom Widget", content=self._custom_browser, size_hint=(0.9, 0.9), auto_dismiss=False) self._popup.open() def _custom_browser_load(self, instance): '''Event Handler for 'on_success' event of self._custom_browser ''' file_path = instance.selection[0] self._popup.dismiss() self.ui_creator.playground.sandbox.error_active = True with self.ui_creator.playground.sandbox: try: self.project_loader.add_custom_widget(file_path) self.designer_content.toolbox.cleanup() for _rule in (self.project_loader.custom_widgets): widgets.append((_rule.name, 'custom')) self.designer_content.toolbox.add_custom() except ProjectLoaderException as e: self.statusbar.show_message('Cannot load widget. %s' % str(e)) self.ui_creator.playground.sandbox.error_active = False def action_chk_btn_toolbox_active(self, chk_btn): '''Event Handler when ActionCheckButton "Toolbox" is activated. ''' if chk_btn.checkbox.active: self._toolbox_parent.add_widget( self.designer_content.splitter_tree) self.designer_content.splitter_tree.width = self._toolbox_width else: self._toolbox_parent = self.designer_content.splitter_tree.parent self._toolbox_parent.remove_widget( self.designer_content.splitter_tree) self._toolbox_width = self.designer_content.splitter_tree.width self.designer_content.splitter_tree.width = 0 def action_chk_btn_property_viewer_active(self, chk_btn): '''Event Handler when ActionCheckButton "Property Viewer" is activated. ''' if chk_btn.checkbox.active: self._toggle_splitter_widget_tree() if self.ui_creator.splitter_widget_tree.parent is None: self._splitter_widget_tree_parent.add_widget( self.ui_creator.splitter_widget_tree) self.ui_creator.splitter_widget_tree.width = \ self._splitter_widget_tree_width add_tree = False if self.ui_creator.grid_widget_tree.parent is not None: add_tree = True self.ui_creator.splitter_property.size_hint_y = None self.ui_creator.splitter_property.height = 300 self._splitter_property_parent.clear_widgets() if add_tree: self._splitter_property_parent.add_widget( self.ui_creator.grid_widget_tree) self._splitter_property_parent.add_widget( self.ui_creator.splitter_property) else: self._splitter_property_parent = \ self.ui_creator.splitter_property.parent self._splitter_property_parent.remove_widget( self.ui_creator.splitter_property) self._toggle_splitter_widget_tree() def action_chk_btn_widget_tree_active(self, chk_btn): '''Event Handler when ActionCheckButton "Widget Tree" is activated. ''' if chk_btn.checkbox.active: self._toggle_splitter_widget_tree() add_prop = False if self.ui_creator.splitter_property.parent is not None: add_prop = True self._grid_widget_tree_parent.clear_widgets() self._grid_widget_tree_parent.add_widget( self.ui_creator.grid_widget_tree) if add_prop: self._grid_widget_tree_parent.add_widget( self.ui_creator.splitter_property) self.ui_creator.splitter_property.size_hint_y = None self.ui_creator.splitter_property.height = 300 else: self._grid_widget_tree_parent = \ self.ui_creator.grid_widget_tree.parent self._grid_widget_tree_parent.remove_widget( self.ui_creator.grid_widget_tree) self.ui_creator.splitter_property.size_hint_y = 1 self._toggle_splitter_widget_tree() def _toggle_splitter_widget_tree(self): '''To show/hide splitter_widget_tree ''' if self.ui_creator.splitter_widget_tree.parent is not None and\ self.ui_creator.splitter_property.parent is None and\ self.ui_creator.grid_widget_tree.parent is None: self._splitter_widget_tree_parent = \ self.ui_creator.splitter_widget_tree.parent self._splitter_widget_tree_parent.remove_widget( self.ui_creator.splitter_widget_tree) self._splitter_widget_tree_width = \ self.ui_creator.splitter_widget_tree.width self.ui_creator.splitter_widget_tree.width = 0 elif self.ui_creator.splitter_widget_tree.parent is None: self._splitter_widget_tree_parent.add_widget( self.ui_creator.splitter_widget_tree) self.ui_creator.splitter_widget_tree.width = \ self._splitter_widget_tree_width def action_chk_btn_status_bar_active(self, chk_btn): '''Event Handler when ActionCheckButton "StatusBar" is activated. ''' if chk_btn.checkbox.active: self._statusbar_parent.add_widget(self.statusbar) self.statusbar.height = self._statusbar_height else: self._statusbar_parent = self.statusbar.parent self._statusbar_height = self.statusbar.height self._statusbar_parent.remove_widget(self.statusbar) self.statusbar.height = 0 def action_chk_btn_kv_area_active(self, chk_btn): '''Event Handler when ActionCheckButton "KVLangArea" is activated. ''' if chk_btn.checkbox.active: self.ui_creator.splitter_kv_code_input.height = \ self._kv_area_height self._kv_area_parent.add_widget( self.ui_creator.splitter_kv_code_input) else: self._kv_area_parent = \ self.ui_creator.splitter_kv_code_input.parent self._kv_area_height = \ self.ui_creator.splitter_kv_code_input.height self.ui_creator.splitter_kv_code_input.height = 0 self._kv_area_parent.remove_widget( self.ui_creator.splitter_kv_code_input) def _error_adding_file(self, *args): '''Event Handler for 'on_error' event of self._add_file_dlg ''' self.statusbar.show_message('Error while adding file to project') self._popup.dismiss() def _added_file(self, *args): '''Event Handler for 'on_added' event of self._add_file_dlg ''' self.statusbar.show_message('File successfully added to project') self._popup.dismiss() if self._add_file_dlg.target_file[3:] == '.py': self.designer_content.add_file_to_tree_view( self._add_file_dlg.target_file) def action_btn_add_file_pressed(self, *args): '''Event Handler when ActionButton "Add File" is pressed. ''' self._add_file_dlg = AddFileDialog(self.project_loader) self._add_file_dlg.bind(on_added=self._added_file, on_error=self._error_adding_file, on_cancel=self._cancel_popup) self._popup = Popup(title="Add File", content=self._add_file_dlg, size_hint=(None, None), size=(400, 300), auto_dismiss=False) self._popup.open() def action_btn_project_pref_pressed(self, *args): '''Event Handler when ActionButton "Project Prefences" is pressed. ''' self.proj_settings = ProjectSettings(proj_loader=self.project_loader) self.proj_settings.load_proj_settings() self.proj_settings.bind(on_close=self._cancel_popup) self._popup = Popup(title="Project Preferences", content=self.proj_settings, size_hint=(None, None), size=(600, 400), auto_dismiss=False) self._popup.open() def action_btn_run_project_pressed(self, *args): '''Event Handler when ActionButton "Run" is pressed. ''' if self.project_loader.file_list == []: return args = '' envs = '' python_path = self.designer_settings.config_parser.getdefault( 'global', 'python_shell_path', '') if python_path == '': self.statusbar.show_message("Python Shell Path not specified," " please specify it before running" " project") return if self.proj_settings and self.proj_settings.config_parser: args = self.proj_settings.config_parser.getdefault( 'arguments', 'arg', '') envs = self.proj_settings.config_parser.getdefault( 'env variables', 'env', '') for env in envs.split(' '): self.ui_creator.kivy_console.environment[ env[:env.find('=')]] = env[env.find('=') + 1:] for _file in self.project_loader.file_list: if 'main.py' in os.path.basename(_file): self.ui_creator.kivy_console.stdin.write( '%s %s %s' % (python_path, _file, args)) self.ui_creator.tab_pannel.switch_to( self.ui_creator.tab_pannel.tab_list[2]) return self.ui_creator.kivy_console.stdin.write( '%s %s %s' % (python_path, self.project_loader._app_file, args)) self.ui_creator.tab_pannel.switch_to( self.ui_creator.tab_pannel.tab_list[2]) def on_sandbox_getting_exception(self, *args): '''Event Handler for :class:`~designer.uix.designer_sandbox.DesignerSandbox` on_getting_exception event. This function will add exception string in error_console. ''' s = traceback.format_list( traceback.extract_tb(self.ui_creator.playground.sandbox.tb)) s = '\n'.join(s) to_insert = "Exception:\n" + s + '\n' + \ "{!r}".format(self.ui_creator.playground.sandbox.exception) text = self.ui_creator.error_console.text + to_insert + '\n\n' self.ui_creator.error_console.text = text if self.ui_creator.playground.sandbox.error_active: self.ui_creator.tab_pannel.switch_to( self.ui_creator.tab_pannel.tab_list[0]) self.ui_creator.playground.sandbox.error_active = False def action_btn_about_pressed(self, *args): '''Event handler for 'on_release' event of DesignerActionButton "About Kivy Designer" ''' self.about_dlg = AboutDialog() self._popup = Popup(title='About Kivy Designer', content=self.about_dlg, size_hint=(None, None), size=(600, 400), auto_dismiss=False) self._popup.open() self.about_dlg.bind(on_cancel=self._cancel_popup)