class BackendsDialog(object): ''' BackendsDialog manages a window that lets you manage and configure synchronization service. It can display two "views", or "panels": - the backend configuration view - the backend adding view ''' def __init__(self, req): ''' Initializes the gtk objects and signals. @param req: a Requester object ''' self.req = req self.icon_theme = None self._configure_icon_theme() # Declare subsequently loaded widget self.dialog = None self.treeview_window = None self.central_pane = None self.add_button = None self.remove_button = None self.backends_tv = None self.config_panel = None self.add_panel = None builder = Gtk.Builder() self._load_widgets_from_builder(builder) # Load and setup other widgets self.dialog.set_title(_("Synchronization Services - %s" % info.NAME)) self._create_widgets_for_add_panel() self._create_widgets_for_conf_panel() self._setup_signal_connections(builder) self._create_widgets_for_treeview() ######################################## ### INTERFACE WITH THE VIEWMANAGER ##### ######################################## def activate(self): '''Shows this window, refreshing the current view''' self.dialog.show_all() self.backends_tv.refresh() self.backends_tv.select_backend() self.dialog.present() def on_close(self, widget, data=None): ''' Hides this window, saving the backends configuration. @param widget: not used, here only for using this as signal callback @param data: same as widget, disregard the content ''' self.dialog.hide() self.req.save_datastore() return True ######################################## ### HELPER FUNCTIONS ################### ######################################## def get_requester(self): ''' Helper function: returns the requester. It's used by the "views" displayed by this class (backend editing and adding views) to access the requester ''' return self.req def get_pixbuf_from_icon_name(self, name, height): ''' Helper function: returns a pixbuf of an icon given its name in the loaded icon theme @param name: the name of the icon @param height: the height of the returned pixbuf @param width: the width of the returned pixbuf @returns GdkPixbuf: a pixbuf containing the wanted icon, or None (if the icon is not present) ''' icon_info = self.icon_theme.lookup_icon(name, height, 0) if icon_info is None: return None else: return Gtk.IconTheme.get_default().load_icon(name, height, 0) def _show_panel(self, panel_name): ''' Helper function to switch between panels. @param panel_name: the name of the wanted panel. Choose between "configuration" or "add" ''' if panel_name == "configuration": panel_to_remove = self.add_panel panel_to_add = self.config_panel side_is_enabled = True elif panel_name == "add": panel_to_remove = self.config_panel panel_to_add = self.add_panel side_is_enabled = False else: Log.error("panel name unknown") return # Central pane # NOTE: self.central_pane is the Gtk.Container in which we load panels if panel_to_remove in self.central_pane: self.central_pane.remove(panel_to_remove) if not panel_to_add in self.central_pane: self.central_pane.add(panel_to_add) self.central_pane.show_all() # Side treeview # disabled if we're adding a new backend try: # when this is called upon initialization of this class, the # backends_tv object has not been created yet. self.add_button.set_sensitive(side_is_enabled) self.remove_button.set_sensitive(side_is_enabled) self.backends_tv.set_sensitive(side_is_enabled) except AttributeError: pass ######################################## ### WIDGETS AND SIGNALS ################ ######################################## def _load_widgets_from_builder(self, builder): ''' Loads widgets from the builder .ui file @param builder: a Gtk.Builder ''' builder.add_from_file(ViewConfig.BACKENDS_UI_FILE) widgets = { 'dialog': 'backends_dialog', 'treeview_window': 'treeview_window', 'central_pane': 'central_pane', 'add_button': 'add_button', 'remove_button': 'remove_button', } for attr, widget in widgets.items(): setattr(self, attr, builder.get_object(widget)) def _setup_signal_connections(self, builder): ''' Creates some GTK signals connections @param builder: a Gtk.Builder ''' signals = { 'on_add_button_clicked': self.on_add_button, 'on_BackendsDialog_delete_event': self.on_close, 'on_close_button_clicked': self.on_close, 'on_remove_button_clicked': self.on_remove_button, 'on_help_button_clicked': lambda w: openurl("help:gtg/gtg-add-sync"), } builder.connect_signals(signals) def _configure_icon_theme(self): ''' Inform gtk on the location of the backends icons (which is in the GTG directory tree, and not in the default location for icons ''' self.icon_theme = Gtk.IconTheme.get_default() for directory in CoreConfig().get_icons_directories(): self.icon_theme.prepend_search_path(directory) def _create_widgets_for_treeview(self): ''' Creates the widgets for the lateral treeview displaying the backends the user has added ''' self.backends_tv = BackendsTree(self) self.treeview_window.add(self.backends_tv) def _create_widgets_for_conf_panel(self): '''simply creates the panel to configure backends''' self.config_panel = ConfigurePanel(self) def _create_widgets_for_add_panel(self): '''simply creates the panel to add backends''' self.add_panel = AddPanel(self) ######################################## ### EVENT HANDLING ##################### ######################################## def on_backend_selected(self, backend_id): ''' When a backend in the treeview gets selected, show its configuration pane @param backend_id: the id of the selected backend ''' if backend_id: self._show_panel("configuration") self.config_panel.set_backend(backend_id) backend = self.req.get_backend(backend_id) self.remove_button.set_sensitive(not backend.is_default()) def on_add_button(self, widget=None, data=None): ''' When the add button is pressed, the add panel is shown @param widget: not used, here only for using this as signal callback @param data: same as widget, disregard the content ''' self._show_panel("add") self.add_panel.refresh_backends() def on_backend_added(self, backend_name): ''' When a backend is added, it is created and registered in the Datastore. Also, the configuration panel is shown. @param backend_name: the name of the type of the backend to add (identified as BACKEND_NAME in the Backend class) ''' # Create Backend backend_dic = BackendFactory().get_new_backend_dict(backend_name) if backend_dic: backend_dic[GenericBackend.KEY_ENABLED] = False self.req.register_backend(backend_dic) # Restore UI self._show_panel("configuration") def show_config_for_backend(self, backend_id): ''' Selects a backend in the lateral treeview @param backend_id: the id of the backend that must be selected ''' self.backends_tv.select_backend(backend_id) def on_remove_button(self, widget=None, data=None): ''' When the remove button is pressed, a confirmation dialog is shown, and if the answer is positive, the backend is deleted. ''' backend_id = self.backends_tv.get_selected_backend_id() if backend_id is None: # no backend selected return backend = self.req.get_backend(backend_id) dialog = Gtk.MessageDialog( parent=self.dialog, flags=Gtk.DialogFlags.DESTROY_WITH_PARENT, type=Gtk.MessageType.QUESTION, buttons=Gtk.ButtonsType.YES_NO, message_format=_("Do you really want to remove the '%s' " "synchronization service?") % backend.get_human_name()) response = dialog.run() dialog.destroy() if response == Gtk.ResponseType.YES: # delete the backend and remove it from the lateral treeview self.req.remove_backend(backend_id) self.backends_tv.remove_backend(backend_id)
class BackendsDialog(object): ''' BackendsDialog manages a window that lets you manage and configure synchronization service. It can display two "views", or "panels": - the backend configuration view - the backend adding view ''' def __init__(self, req): ''' Initializes the gtk objects and signals. @param req: a Requester object ''' self.req = req # Declare subsequently loaded widget self.dialog = None self.treeview_window = None self.central_pane = None self.add_button = None self.remove_button = None self.backends_tv = None self.config_panel = None self.add_panel = None builder = Gtk.Builder() self._load_widgets_from_builder(builder) # Load and setup other widgets self.dialog.set_title(_("Synchronization Services - %s" % info.NAME)) self._create_widgets_for_add_panel() self._create_widgets_for_conf_panel() self._setup_signal_connections(builder) self._create_widgets_for_treeview() help.add_help_shortcut(self.dialog, "sync") ######################################## # INTERFACE WITH THE VIEWMANAGER ####### ######################################## def activate(self): '''Shows this window, refreshing the current view''' self.dialog.show_all() self.backends_tv.refresh() self.backends_tv.select_backend() self.dialog.present() def on_close(self, widget, data=None): ''' Hides this window, saving the backends configuration. @param widget: not used, here only for using this as signal callback @param data: same as widget, disregard the content ''' self.dialog.hide() self.req.save_datastore() return True ######################################## # HELPER FUNCTIONS ##################### ######################################## def get_requester(self): ''' Helper function: returns the requester. It's used by the "views" displayed by this class (backend editing and adding views) to access the requester ''' return self.req def get_pixbuf_from_icon_name(self, name, height): ''' Helper function: returns a pixbuf of an icon given its name in the loaded icon theme @param name: the name of the icon @param height: the height of the returned pixbuf @param width: the width of the returned pixbuf @returns GdkPixbuf: a pixbuf containing the wanted icon, or None (if the icon is not present) ''' return Gtk.IconTheme.get_default().load_icon(name, height, 0) def _show_panel(self, panel_name): ''' Helper function to switch between panels. @param panel_name: the name of the wanted panel. Choose between "configuration" or "add" ''' if panel_name == "configuration": panel_to_remove = self.add_panel panel_to_add = self.config_panel side_is_enabled = True elif panel_name == "add": panel_to_remove = self.config_panel panel_to_add = self.add_panel side_is_enabled = False else: Log.error("panel name unknown") return # Central pane # NOTE: self.central_pane is the Gtk.Container in which we load panels if panel_to_remove in self.central_pane: self.central_pane.remove(panel_to_remove) if panel_to_add not in self.central_pane: self.central_pane.add(panel_to_add) self.central_pane.show_all() # Side treeview # disabled if we're adding a new backend try: # when this is called upon initialization of this class, the # backends_tv object has not been created yet. self.add_button.set_sensitive(side_is_enabled) self.remove_button.set_sensitive(side_is_enabled) self.backends_tv.set_sensitive(side_is_enabled) except AttributeError: pass ######################################## # WIDGETS AND SIGNALS ################## ######################################## def _load_widgets_from_builder(self, builder): ''' Loads widgets from the builder .ui file @param builder: a Gtk.Builder ''' builder.add_from_file(ViewConfig.BACKENDS_UI_FILE) widgets = { 'dialog': 'backends_dialog', 'treeview_window': 'treeview_window', 'central_pane': 'central_pane', 'add_button': 'add_button', 'remove_button': 'remove_button', } for attr, widget in widgets.items(): setattr(self, attr, builder.get_object(widget)) def _setup_signal_connections(self, builder): ''' Creates some GTK signals connections @param builder: a Gtk.Builder ''' signals = { 'on_add_button_clicked': self.on_add_button, 'on_BackendsDialog_delete_event': self.on_close, 'on_close_button_clicked': self.on_close, 'on_remove_button_clicked': self.on_remove_button, 'on_help_button_clicked': self.on_help, } builder.connect_signals(signals) def _create_widgets_for_treeview(self): ''' Creates the widgets for the lateral treeview displaying the backends the user has added ''' self.backends_tv = BackendsTree(self) self.treeview_window.add(self.backends_tv) def _create_widgets_for_conf_panel(self): '''simply creates the panel to configure backends''' self.config_panel = ConfigurePanel(self) def _create_widgets_for_add_panel(self): '''simply creates the panel to add backends''' self.add_panel = AddPanel(self) ######################################## # EVENT HANDLING ####################### ######################################## @classmethod def on_help(cls, widget): """ Open help for syncronization services """ help.show_help("sync") return True def on_backend_selected(self, backend_id): ''' When a backend in the treeview gets selected, show its configuration pane @param backend_id: the id of the selected backend ''' if backend_id: self._show_panel("configuration") self.config_panel.set_backend(backend_id) backend = self.req.get_backend(backend_id) self.remove_button.set_sensitive(not backend.is_default()) def on_add_button(self, widget=None, data=None): ''' When the add button is pressed, the add panel is shown @param widget: not used, here only for using this as signal callback @param data: same as widget, disregard the content ''' self._show_panel("add") self.add_panel.refresh_backends() def on_backend_added(self, backend_name): ''' When a backend is added, it is created and registered in the Datastore. Also, the configuration panel is shown. @param backend_name: the name of the type of the backend to add (identified as BACKEND_NAME in the Backend class) ''' # Create Backend backend_dic = BackendFactory().get_new_backend_dict(backend_name) if backend_dic: backend_dic[GenericBackend.KEY_ENABLED] = False self.req.register_backend(backend_dic) # Restore UI self._show_panel("configuration") def show_config_for_backend(self, backend_id): ''' Selects a backend in the lateral treeview @param backend_id: the id of the backend that must be selected ''' self.backends_tv.select_backend(backend_id) def on_remove_button(self, widget=None, data=None): ''' When the remove button is pressed, a confirmation dialog is shown, and if the answer is positive, the backend is deleted. ''' backend_id = self.backends_tv.get_selected_backend_id() if backend_id is None: # no backend selected return backend = self.req.get_backend(backend_id) dialog = Gtk.MessageDialog( parent=self.dialog, flags=Gtk.DialogFlags.DESTROY_WITH_PARENT, type=Gtk.MessageType.QUESTION, buttons=Gtk.ButtonsType.YES_NO, message_format=_("Do you really want to remove the '%s' " "synchronization service?") % backend.get_human_name()) response = dialog.run() dialog.destroy() if response == Gtk.ResponseType.YES: # delete the backend and remove it from the lateral treeview self.req.remove_backend(backend_id) self.backends_tv.remove_backend(backend_id)
def _create_widgets_for_add_panel(self): '''simply creates the panel to add backends''' self.add_panel = AddPanel(self)