def __init__(self, parent, existing_folders): """Prepare the AppFolder creation dialog""" # Load the user interface self.ui = GtkBuilderLoader(get_ui_file('create_appfolder.ui')) self.ui.dialog_create_appfolder.set_titlebar(self.ui.header_bar) # Initialize actions for widget in self.ui.get_objects_by_type(Gtk.Action): # Connect the actions accelerators widget.connect_accelerator() # Set labels label = widget.get_label() if not label: label = widget.get_short_label() widget.set_short_label(text(label)) widget.set_label(text(label)) # Initialize labels for widget in self.ui.get_objects_by_type(Gtk.Label): widget.set_label(text(widget.get_label())) # Initialize tooltips for widget in self.ui.get_objects_by_type(Gtk.Button): action = widget.get_related_action() if action: widget.set_tooltip_text(action.get_label().replace('_', '')) # Set various properties self.ui.dialog_create_appfolder.set_transient_for(parent) set_style_suggested_action(self.ui.button_ok) self.existing_folders = existing_folders self.ui.button_ok.grab_default() self.folder_name = '' self.folder_title = '' # Connect signals from the glade file to the module functions self.ui.connect_signals(self)
def __init__(self, parent): """Prepare the shortcuts dialog""" # Load the user interface self.ui = GtkBuilderLoader(get_ui_file('shortcuts.ui')) self.ui.shortcuts.set_transient_for(parent) # Initialize groups for widget in self.ui.get_objects_by_type(Gtk.ShortcutsGroup): widget.props.title = text(widget.props.title) # Initialize shortcuts for widget in self.ui.get_objects_by_type(Gtk.ShortcutsShortcut): widget.props.title = text(widget.props.title)
def loadUI(self): """Load the interface UI""" self.ui = GtkBuilderLoader(get_ui_file('main.ui')) self.ui.win_main.set_application(self.application) self.ui.win_main.set_title(APP_NAME) # Initialize actions for widget in self.ui.get_objects_by_type(Gtk.Action): # Connect the actions accelerators widget.connect_accelerator() # Set labels label = widget.get_label() if not label: label = widget.get_short_label() widget.set_label(text(label)) widget.set_short_label(label) # Initialize labels for widget in self.ui.get_objects_by_type(Gtk.Label): widget.set_label(text(widget.get_label())) # Initialize tooltips for widget in self.ui.get_objects_by_type(Gtk.Button): action = widget.get_related_action() if action: widget.set_tooltip_text(action.get_label().replace('_', '')) # Initialize Gtk.HeaderBar self.ui.header_bar.props.title = self.ui.win_main.get_title() self.ui.win_main.set_titlebar(self.ui.header_bar) for button in (self.ui.button_folder_new, self.ui.button_folder_remove, self.ui.button_folder_properties, self.ui.button_files_add, self.ui.button_files_remove, self.ui.button_files_save, self.ui.button_about, ): action = button.get_related_action() icon_name = action.get_icon_name() if preferences.get(preferences.HEADERBARS_SYMBOLIC_ICONS): icon_name += '-symbolic' # Get desired icon size icon_size = (Gtk.IconSize.BUTTON if preferences.get(preferences.HEADERBARS_SMALL_ICONS) else Gtk.IconSize.LARGE_TOOLBAR) button.set_image(Gtk.Image.new_from_icon_name(icon_name, icon_size)) # Remove the button label button.props.label = None # Set the tooltip from the action label button.set_tooltip_text(action.get_label().replace('_', '')) # Set preferences button icon icon_name = self.ui.image_preferences.get_icon_name()[0] if preferences.get(preferences.HEADERBARS_SYMBOLIC_ICONS): icon_name += '-symbolic' self.ui.image_preferences.set_from_icon_name(icon_name, icon_size) # Load settings self.dict_settings_map = { preferences.HEADERBARS_SMALL_ICONS: self.ui.action_preferences_small_icons, preferences.HEADERBARS_SYMBOLIC_ICONS: self.ui.action_preferences_symbolic_icons, preferences.PREFERENCES_SHOW_MISSING: self.ui.action_preferences_show_missing_files } for setting_name, action in self.dict_settings_map.items(): action.set_active(preferences.get(setting_name)) # Connect signals from the glade file to the module functions self.ui.connect_signals(self)
class UIMain(object): def __init__(self, application): self.application = application # Load settings settings.settings = settings.Settings(FILE_SETTINGS, False) settings.positions = settings.Settings(FILE_WINDOWS_POSITION, False) self.folders = {} preferences.preferences = preferences.Preferences() self.loadUI() # Prepares the models for folders and applications self.model_folders = ModelAppFolders(self.ui.store_folders) self.model_applications = ModelApplications(self.ui.store_applications) self.model_applications.model.set_sort_column_id( self.ui.treeview_column_applications.get_sort_column_id(), Gtk.SortType.ASCENDING) # Detect the AppFolders and select the first one automatically self.reload_folders() if self.model_folders.count() > 0: self.ui.treeview_folders.set_cursor(0) self.ui.treeview_folders.grab_focus() # Restore the saved size and position settings.positions.restore_window_position( self.ui.win_main, SECTION_WINDOW_NAME) def loadUI(self): """Load the interface UI""" self.ui = GtkBuilderLoader(get_ui_file('main.ui')) self.ui.win_main.set_application(self.application) self.ui.win_main.set_title(APP_NAME) # Initialize actions for widget in self.ui.get_objects_by_type(Gtk.Action): # Connect the actions accelerators widget.connect_accelerator() # Set labels label = widget.get_label() if not label: label = widget.get_short_label() widget.set_label(text(label)) widget.set_short_label(label) # Initialize labels for widget in self.ui.get_objects_by_type(Gtk.Label): widget.set_label(text(widget.get_label())) # Initialize tooltips for widget in self.ui.get_objects_by_type(Gtk.Button): action = widget.get_related_action() if action: widget.set_tooltip_text(action.get_label().replace('_', '')) # Initialize Gtk.HeaderBar self.ui.header_bar.props.title = self.ui.win_main.get_title() self.ui.win_main.set_titlebar(self.ui.header_bar) for button in (self.ui.button_folder_new, self.ui.button_folder_remove, self.ui.button_folder_properties, self.ui.button_files_add, self.ui.button_files_remove, self.ui.button_files_save, self.ui.button_about, ): action = button.get_related_action() icon_name = action.get_icon_name() if preferences.get(preferences.HEADERBARS_SYMBOLIC_ICONS): icon_name += '-symbolic' # Get desired icon size icon_size = (Gtk.IconSize.BUTTON if preferences.get(preferences.HEADERBARS_SMALL_ICONS) else Gtk.IconSize.LARGE_TOOLBAR) button.set_image(Gtk.Image.new_from_icon_name(icon_name, icon_size)) # Remove the button label button.props.label = None # Set the tooltip from the action label button.set_tooltip_text(action.get_label().replace('_', '')) # Set preferences button icon icon_name = self.ui.image_preferences.get_icon_name()[0] if preferences.get(preferences.HEADERBARS_SYMBOLIC_ICONS): icon_name += '-symbolic' self.ui.image_preferences.set_from_icon_name(icon_name, icon_size) # Load settings self.dict_settings_map = { preferences.HEADERBARS_SMALL_ICONS: self.ui.action_preferences_small_icons, preferences.HEADERBARS_SYMBOLIC_ICONS: self.ui.action_preferences_symbolic_icons, preferences.PREFERENCES_SHOW_MISSING: self.ui.action_preferences_show_missing_files } for setting_name, action in self.dict_settings_map.items(): action.set_active(preferences.get(setting_name)) # Connect signals from the glade file to the module functions self.ui.connect_signals(self) def run(self): """Show the UI""" self.ui.win_main.show_all() def on_win_main_delete_event(self, widget, event): """Save the settings and close the application""" settings.positions.save_window_position( self.ui.win_main, SECTION_WINDOW_NAME) settings.positions.save() settings.settings.save() self.application.quit() def on_action_about_activate(self, action): """Show the about dialog""" dialog = UIAbout(self.ui.win_main) dialog.show() dialog.destroy() def on_action_shortcuts_activate(self, action): """Show the shortcuts dialog""" dialog = UIShortcuts(self.ui.win_main) dialog.show() def on_action_quit_activate(self, action): """Close the application by closing the main window""" event = Gdk.Event() event.key.type = Gdk.EventType.DELETE self.ui.win_main.event(event) def reload_folders(self): """Reload the Application Folders""" self.folders = {} self.model_folders.clear() settings_folders = Gio.Settings.new(SCHEMA_FOLDERS) list_folders = settings_folders.get_strv('folder-children') for folder_name in list_folders: folder_info = FolderInfo(folder_name) appfolder = AppFolderInfo(folder_info) self.model_folders.add_data(appfolder) self.folders[folder_info.folder] = folder_info def on_treeview_folders_cursor_changed(self, widget): selected_row = get_treeview_selected_row(self.ui.treeview_folders) if selected_row: folder_name = self.model_folders.get_key(selected_row) # Check if the folder still exists # (model erased while the cursor moves through the Gtk.TreeView) if folder_name in self.folders: folder_info = self.folders[folder_name] # Clear any previous application icon self.model_applications.clear() # Add new application icons applications = folder_info.get_applications() for application in applications: desktop_file = applications[application] if desktop_file or preferences.get( preferences.PREFERENCES_SHOW_MISSING): application_file = applications[application] application_info = ApplicationInfo( application, application_file.getName() if desktop_file else 'Missing desktop file', application_file.getComment() if desktop_file else application, application_file.getIcon() if desktop_file else None, # Always show any application, also if hidden True) self.model_applications.add_data(application_info) # Disable folder content saving self.ui.action_files_save.set_sensitive(False) def on_treeview_selection_folders_changed(self, widget): """Set action sensitiveness on selection change""" selected_row = get_treeview_selected_row(self.ui.treeview_folders) for widget in (self.ui.action_folders_remove, self.ui.action_folders_properties, self.ui.action_files_new): widget.set_sensitive(bool(selected_row)) if not selected_row: self.ui.action_files_new.set_sensitive(False) self.ui.action_files_remove.set_sensitive(False) self.ui.action_files_save.set_sensitive(False) self.model_applications.clear() def on_action_files_new_activate(self, action): """Show an application picker to add to the current AppFolder""" dialog = UIApplicationPicker(self.ui.win_main, self.model_applications.rows.keys()) if dialog.show() == Gtk.ResponseType.OK: if dialog.selected_applications: for application in dialog.selected_applications: # Get the selected application in the application picker # and add it to the current AppFolder application_info = dialog.model_applications.items[ application] self.model_applications.add_data(application_info) # Automatically select the newly added application filename = application_info.filename treeiter = self.model_applications.rows[filename] if treeiter: # Automatically select the last added application self.ui.treeview_applications.set_cursor( self.model_applications.get_path(treeiter)) # Enable folder content saving self.ui.action_files_save.set_sensitive(True) dialog.destroy() def on_treeview_selection_applications_changed(self, widget): """Set action sensitiveness on selection change""" selected_row = get_treeview_selected_row(self.ui.treeview_applications) self.ui.action_files_remove.set_sensitive(bool(selected_row)) def on_action_files_remove_activate(self, action): """Remove the selected application from the current AppFolder""" selected_row = get_treeview_selected_row(self.ui.treeview_applications) if selected_row: self.model_applications.remove(selected_row) # Enable folder content saving self.ui.action_files_save.set_sensitive(True) def on_action_files_save_activate(self, action): """Save the current AppFolder""" selected_row = get_treeview_selected_row(self.ui.treeview_folders) if selected_row: folder_name = self.model_folders.get_key(selected_row) folder_info = self.folders[folder_name] folder_info.set_applications(self.model_applications.rows.keys()) # Disable folder content saving self.ui.action_files_save.set_sensitive(False) def on_action_folders_remove_activate(self, action): """Remove the current AppFolder""" selected_row = get_treeview_selected_row(self.ui.treeview_folders) if selected_row: folder_name = self.model_folders.get_key(selected_row) if show_message_dialog(class_=UIMessageDialogNoYes, parent=self.ui.win_main, message_type=Gtk.MessageType.QUESTION, title=None, msg1=_('Remove the selected folder?'), msg2=_('Are you sure you want to remove ' 'the folder %s?') % folder_name, is_response_id=Gtk.ResponseType.YES): # Remove the AppFolder from settings folder_info = self.folders[folder_name] folder_info.remove() self.folders.pop(folder_name) # Remove the folder name from the folders list settings_folders = Gio.Settings.new(SCHEMA_FOLDERS) list_folders = settings_folders.get_strv('folder-children') list_folders.remove(folder_name) settings_folders.set_strv('folder-children', list_folders) # Clear the applications model self.model_applications.clear() # Remove the folder from the folders model self.model_folders.remove(selected_row) def on_action_folders_new_activate(self, action): """Creat a new AppFolder""" dialog = UICreateAppFolder(self.ui.win_main, self.model_folders.rows.keys()) if dialog.show(name='', title='') == Gtk.ResponseType.OK: # Create a new FolderInfo object and set its title folder_info = FolderInfo(dialog.folder_name) folder_info.set_title(dialog.folder_title) # Add the folder to the folders list settings_folders = Gio.Settings.new(SCHEMA_FOLDERS) list_folders = settings_folders.get_strv('folder-children') list_folders.append(dialog.folder_name) settings_folders.set_strv('folder-children', list_folders) # Reload folders list self.reload_folders() dialog.destroy() def on_action_folders_properties_activate(self, action): """Set the AppFolder properties""" selected_row = get_treeview_selected_row(self.ui.treeview_folders) if selected_row: name = self.model_folders.get_key(selected_row) title = self.model_folders.get_title(selected_row) dialog = UICreateAppFolder(self.ui.win_main, self.model_folders.rows.keys()) if dialog.show(name=name, title=title) == Gtk.ResponseType.OK: folder_name = dialog.folder_name folder_title = dialog.folder_title # Update the folder title folder_info = self.folders[folder_name] folder_info.name = folder_title folder_info.set_title(folder_title) # Reload the folders list and select the folder again self.reload_folders() self.ui.treeview_folders.set_cursor( self.model_folders.get_path_by_name(folder_name)) dialog.destroy() def on_action_preferences_toggled(self, widget): """Change a preference value""" for setting_name, action in self.dict_settings_map.items(): if action is widget: preferences.set(setting_name, widget.get_active()) def on_action_preferences_need_restart_toggled(self, widget): """Show the infobar to require application restart""" self.ui.label_infobar.set_label( _('The application must be restarted to apply the settings')) self.ui.infobar.show() def on_action_preferences_show_missing_files_toggled(self, widget): """Show and hide the missing desktop files""" self.on_treeview_folders_cursor_changed( self.ui.treeview_folders) def on_treeview_folders_row_activated(self, widget, path, column): """Show folder properties on activation""" self.ui.action_folders_properties.activate()
def __init__(self, parent, existing_files): """Prepare the application picker dialog""" # Load the user interface self.ui = GtkBuilderLoader(get_ui_file('application_picker.ui')) self.ui.dialog_application_picker.set_titlebar(self.ui.header_bar) # Prepares the models for the applications self.model_applications = ModelApplications(self.ui.store_applications) self.model_applications.model.set_sort_column_id( self.ui.treeview_column_applications.get_sort_column_id(), Gtk.SortType.ASCENDING) self.ui.filter_applications.set_visible_column( ModelApplications.COL_VISIBLE) # Initialize actions for widget in self.ui.get_objects_by_type(Gtk.Action): # Connect the actions accelerators widget.connect_accelerator() # Set labels label = widget.get_label() if not label: label = widget.get_short_label() widget.set_short_label(text(label)) widget.set_label(text(label)) # Initialize tooltips for widget in self.ui.get_objects_by_type(Gtk.Button): action = widget.get_related_action() if action: widget.set_tooltip_text(action.get_label().replace('_', '')) # Set various properties self.ui.dialog_application_picker.set_transient_for(parent) set_style_suggested_action(self.ui.button_add) self.selected_applications = None # Set preferences button icon icon_name = self.ui.image_preferences.get_icon_name()[0] if preferences.get(preferences.HEADERBARS_SYMBOLIC_ICONS): icon_name += '-symbolic' # Get desired icon size icon_size = (Gtk.IconSize.BUTTON if preferences.get(preferences.HEADERBARS_SMALL_ICONS) else Gtk.IconSize.LARGE_TOOLBAR) self.ui.image_preferences.set_from_icon_name(icon_name, icon_size) # Load settings self.dict_settings_map = { preferences.APP_PICKER_SHOW_HIDDEN: self.ui.action_show_hidden } for setting_name, action in self.dict_settings_map.items(): action.set_active(preferences.get(setting_name)) # Prepares the applications list for desktop_entry in Gio.app_info_get_all(): try: icon_name = None icon = desktop_entry.get_icon() if isinstance(icon, Gio.ThemedIcon): # From Gio.ThemedIcon get the icon name only icons = desktop_entry.get_icon().get_names() icon_name = icons[0] if icons else None elif isinstance(icon, Gio.FileIcon): # From Gio.FileIcon get the full file name icon_name = icon.get_file().get_parse_name() description = (desktop_entry.get_description() if desktop_entry.get_description() else '') application = ApplicationInfo(desktop_entry.get_id(), desktop_entry.get_name(), description, icon_name, desktop_entry.should_show()) # Skip existing files if application.filename not in existing_files: self.model_applications.add_data(application) except Exception as e: print 'error for', desktop_entry.get_id(), e self.model_applications.set_all_rows_visibility( preferences.get(preferences.APP_PICKER_SHOW_HIDDEN)) # Connect signals from the glade file to the module functions self.ui.connect_signals(self)
class UIApplicationPicker(object): def __init__(self, parent, existing_files): """Prepare the application picker dialog""" # Load the user interface self.ui = GtkBuilderLoader(get_ui_file('application_picker.ui')) self.ui.dialog_application_picker.set_titlebar(self.ui.header_bar) # Prepares the models for the applications self.model_applications = ModelApplications(self.ui.store_applications) self.model_applications.model.set_sort_column_id( self.ui.treeview_column_applications.get_sort_column_id(), Gtk.SortType.ASCENDING) self.ui.filter_applications.set_visible_column( ModelApplications.COL_VISIBLE) # Initialize actions for widget in self.ui.get_objects_by_type(Gtk.Action): # Connect the actions accelerators widget.connect_accelerator() # Set labels label = widget.get_label() if not label: label = widget.get_short_label() widget.set_short_label(text(label)) widget.set_label(text(label)) # Initialize tooltips for widget in self.ui.get_objects_by_type(Gtk.Button): action = widget.get_related_action() if action: widget.set_tooltip_text(action.get_label().replace('_', '')) # Set various properties self.ui.dialog_application_picker.set_transient_for(parent) set_style_suggested_action(self.ui.button_add) self.selected_applications = None # Set preferences button icon icon_name = self.ui.image_preferences.get_icon_name()[0] if preferences.get(preferences.HEADERBARS_SYMBOLIC_ICONS): icon_name += '-symbolic' # Get desired icon size icon_size = (Gtk.IconSize.BUTTON if preferences.get(preferences.HEADERBARS_SMALL_ICONS) else Gtk.IconSize.LARGE_TOOLBAR) self.ui.image_preferences.set_from_icon_name(icon_name, icon_size) # Load settings self.dict_settings_map = { preferences.APP_PICKER_SHOW_HIDDEN: self.ui.action_show_hidden } for setting_name, action in self.dict_settings_map.items(): action.set_active(preferences.get(setting_name)) # Prepares the applications list for desktop_entry in Gio.app_info_get_all(): try: icon_name = None icon = desktop_entry.get_icon() if isinstance(icon, Gio.ThemedIcon): # From Gio.ThemedIcon get the icon name only icons = desktop_entry.get_icon().get_names() icon_name = icons[0] if icons else None elif isinstance(icon, Gio.FileIcon): # From Gio.FileIcon get the full file name icon_name = icon.get_file().get_parse_name() description = (desktop_entry.get_description() if desktop_entry.get_description() else '') application = ApplicationInfo(desktop_entry.get_id(), desktop_entry.get_name(), description, icon_name, desktop_entry.should_show()) # Skip existing files if application.filename not in existing_files: self.model_applications.add_data(application) except Exception as e: print 'error for', desktop_entry.get_id(), e self.model_applications.set_all_rows_visibility( preferences.get(preferences.APP_PICKER_SHOW_HIDDEN)) # Connect signals from the glade file to the module functions self.ui.connect_signals(self) def show(self): """Show the application picker dialog""" settings.positions.restore_window_position( self.ui.dialog_application_picker, SECTION_WINDOW_NAME) response = self.ui.dialog_application_picker.run() self.ui.dialog_application_picker.hide() return response def destroy(self): """Destroy the application picker dialog""" settings.positions.save_window_position( self.ui.dialog_application_picker, SECTION_WINDOW_NAME) self.ui.dialog_application_picker.destroy() self.ui.dialog_application_picker = None def on_action_close_activate(self, action): """Close the application picker dialog""" self.ui.dialog_application_picker.response(Gtk.ResponseType.CLOSE) def on_action_add_activate(self, action): """Add the selected application to the current AppFolder""" self.selected_applications = [] for row in get_treeview_selected_rows(self.ui.treeview_applications): application = self.model_applications.get_key( self.ui.filter_applications.convert_path_to_child_path(row)) self.selected_applications.append(application) self.ui.dialog_application_picker.response(Gtk.ResponseType.OK) def on_treeview_applications_row_activated(self, widget, path, column): """Add the selected application on row activation""" self.ui.action_add.activate() def on_treeview_selection_applications_changed(self, widget): """Set action sensitiveness on selection change""" selected_rows = get_treeview_selected_rows( self.ui.treeview_applications) self.ui.action_add.set_sensitive(bool(selected_rows)) def on_action_preferences_toggled(self, widget): """Change a preference value""" for setting_name, action in self.dict_settings_map.items(): if action is widget: preferences.set(setting_name, widget.get_active()) def on_action_show_hidden_toggled(self, widget): """Set the visibility for all the Gtk.TreeModelRows""" self.model_applications.set_all_rows_visibility( self.ui.action_show_hidden.get_active())
class UICreateAppFolder(object): def __init__(self, parent, existing_folders): """Prepare the AppFolder creation dialog""" # Load the user interface self.ui = GtkBuilderLoader(get_ui_file('create_appfolder.ui')) self.ui.dialog_create_appfolder.set_titlebar(self.ui.header_bar) # Initialize actions for widget in self.ui.get_objects_by_type(Gtk.Action): # Connect the actions accelerators widget.connect_accelerator() # Set labels label = widget.get_label() if not label: label = widget.get_short_label() widget.set_short_label(text(label)) widget.set_label(text(label)) # Initialize labels for widget in self.ui.get_objects_by_type(Gtk.Label): widget.set_label(text(widget.get_label())) # Initialize tooltips for widget in self.ui.get_objects_by_type(Gtk.Button): action = widget.get_related_action() if action: widget.set_tooltip_text(action.get_label().replace('_', '')) # Set various properties self.ui.dialog_create_appfolder.set_transient_for(parent) set_style_suggested_action(self.ui.button_ok) self.existing_folders = existing_folders self.ui.button_ok.grab_default() self.folder_name = '' self.folder_title = '' # Connect signals from the glade file to the module functions self.ui.connect_signals(self) def show(self, name, title): """Show the dialog""" settings.positions.restore_window_position( self.ui.dialog_create_appfolder, SECTION_WINDOW_NAME) # Set initial values self.folder_name = name self.ui.entry_name.set_text(name) self.folder_title = title self.ui.entry_title.set_text(title) # Change label from Create folder to Save if a folder name was provided if name: self.ui.entry_name.set_sensitive(False) self.ui.button_ok.set_related_action(self.ui.action_save) self.ui.button_ok.set_tooltip_text( self.ui.action_save.get_label().replace('_', '')) response = self.ui.dialog_create_appfolder.run() self.ui.dialog_create_appfolder.hide() return response def destroy(self): """Destroy the dialog""" settings.positions.save_window_position( self.ui.dialog_create_appfolder, SECTION_WINDOW_NAME) self.ui.dialog_create_appfolder.destroy() self.ui.dialog_create_appfolder = None def on_action_close_activate(self, action): """Close the dialog""" self.ui.dialog_create_appfolder.response(Gtk.ResponseType.CLOSE) def on_action_confirm_activate(self, action): """Accept the folder name and title and close the dialog""" self.folder_name = self.ui.entry_name.get_text().strip() self.folder_title = self.ui.entry_title.get_text().strip() self.ui.dialog_create_appfolder.response(Gtk.ResponseType.OK) def on_entry_name_changed(self, widget): """Check if the folder already exists""" name = self.ui.entry_name.get_text().strip() existing = (name in self.existing_folders and name != self.folder_name) # If a folder with the specified name already exists # then disable the creation and show an icon self.ui.action_create.set_sensitive(bool(name) and not existing) self.ui.entry_name.set_icon_from_icon_name( Gtk.EntryIconPosition.SECONDARY, 'dialog-error' if existing else None) self.ui.entry_name.set_icon_tooltip_text( Gtk.EntryIconPosition.SECONDARY, text('A folder with that name already exists') if existing else None)
class UIMain(object): def __init__(self, application): self.application = application # Load settings settings.settings = settings.Settings(FILE_SETTINGS, False) settings.positions = settings.Settings(FILE_WINDOWS_POSITION, False) self.folders = {} preferences.preferences = preferences.Preferences() self.loadUI() # Prepares the models for folders and applications self.model_folders = ModelAppFolders(self.ui.store_folders) self.model_applications = ModelApplications(self.ui.store_applications) self.model_applications.model.set_sort_column_id( self.ui.treeview_column_applications.get_sort_column_id(), Gtk.SortType.ASCENDING) # Detect the AppFolders and select the first one automatically self.reload_folders() if self.model_folders.count() > 0: self.ui.treeview_folders.set_cursor(0) self.ui.treeview_folders.grab_focus() # Restore the saved size and position settings.positions.restore_window_position(self.ui.win_main, SECTION_WINDOW_NAME) def loadUI(self): """Load the interface UI""" self.ui = GtkBuilderLoader(get_ui_file('main.ui')) self.ui.win_main.set_application(self.application) self.ui.win_main.set_title(APP_NAME) # Initialize actions for widget in self.ui.get_objects_by_type(Gtk.Action): # Connect the actions accelerators widget.connect_accelerator() # Set labels label = widget.get_label() if not label: label = widget.get_short_label() widget.set_label(text(label)) widget.set_short_label(label) # Initialize labels for widget in self.ui.get_objects_by_type(Gtk.Label): widget.set_label(text(widget.get_label())) # Initialize tooltips for widget in self.ui.get_objects_by_type(Gtk.Button): action = widget.get_related_action() if action: widget.set_tooltip_text(action.get_label().replace('_', '')) # Initialize Gtk.HeaderBar self.ui.header_bar.props.title = self.ui.win_main.get_title() self.ui.win_main.set_titlebar(self.ui.header_bar) for button in ( self.ui.button_folder_new, self.ui.button_folder_remove, self.ui.button_folder_properties, self.ui.button_files_add, self.ui.button_files_remove, self.ui.button_files_save, self.ui.button_about, ): action = button.get_related_action() icon_name = action.get_icon_name() if preferences.get(preferences.HEADERBARS_SYMBOLIC_ICONS): icon_name += '-symbolic' # Get desired icon size icon_size = (Gtk.IconSize.BUTTON if preferences.get(preferences.HEADERBARS_SMALL_ICONS) else Gtk.IconSize.LARGE_TOOLBAR) button.set_image(Gtk.Image.new_from_icon_name( icon_name, icon_size)) # Remove the button label button.props.label = None # Set the tooltip from the action label button.set_tooltip_text(action.get_label().replace('_', '')) # Set preferences button icon icon_name = self.ui.image_preferences.get_icon_name()[0] if preferences.get(preferences.HEADERBARS_SYMBOLIC_ICONS): icon_name += '-symbolic' self.ui.image_preferences.set_from_icon_name(icon_name, icon_size) # Load settings self.dict_settings_map = { preferences.HEADERBARS_SMALL_ICONS: self.ui.action_preferences_small_icons, preferences.HEADERBARS_SYMBOLIC_ICONS: self.ui.action_preferences_symbolic_icons, preferences.PREFERENCES_SHOW_MISSING: self.ui.action_preferences_show_missing_files } for setting_name, action in self.dict_settings_map.items(): action.set_active(preferences.get(setting_name)) # Connect signals from the glade file to the module functions self.ui.connect_signals(self) def run(self): """Show the UI""" self.ui.win_main.show_all() def on_win_main_delete_event(self, widget, event): """Save the settings and close the application""" settings.positions.save_window_position(self.ui.win_main, SECTION_WINDOW_NAME) settings.positions.save() settings.settings.save() self.application.quit() def on_action_about_activate(self, action): """Show the about dialog""" dialog = UIAbout(self.ui.win_main) dialog.show() dialog.destroy() def on_action_shortcuts_activate(self, action): """Show the shortcuts dialog""" dialog = UIShortcuts(self.ui.win_main) dialog.show() def on_action_quit_activate(self, action): """Close the application by closing the main window""" event = Gdk.Event() event.key.type = Gdk.EventType.DELETE self.ui.win_main.event(event) def reload_folders(self): """Reload the Application Folders""" self.folders = {} self.model_folders.clear() settings_folders = Gio.Settings.new(SCHEMA_FOLDERS) list_folders = settings_folders.get_strv('folder-children') for folder_name in list_folders: folder_info = FolderInfo(folder_name) appfolder = AppFolderInfo(folder_info) self.model_folders.add_data(appfolder) self.folders[folder_info.folder] = folder_info def on_treeview_folders_cursor_changed(self, widget): selected_row = get_treeview_selected_row(self.ui.treeview_folders) if selected_row: folder_name = self.model_folders.get_key(selected_row) # Check if the folder still exists # (model erased while the cursor moves through the Gtk.TreeView) if folder_name in self.folders: folder_info = self.folders[folder_name] # Clear any previous application icon self.model_applications.clear() # Add new application icons applications = folder_info.get_applications() for application in applications: desktop_file = applications[application] if desktop_file or preferences.get( preferences.PREFERENCES_SHOW_MISSING): application_file = applications[application] application_info = ApplicationInfo( application, application_file.getName() if desktop_file else 'Missing desktop file', application_file.getComment() if desktop_file else application, application_file.getIcon() if desktop_file else None, # Always show any application, also if hidden True) self.model_applications.add_data(application_info) # Disable folder content saving self.ui.action_files_save.set_sensitive(False) def on_treeview_selection_folders_changed(self, widget): """Set action sensitiveness on selection change""" selected_row = get_treeview_selected_row(self.ui.treeview_folders) for widget in (self.ui.action_folders_remove, self.ui.action_folders_properties, self.ui.action_files_new): widget.set_sensitive(bool(selected_row)) if not selected_row: self.ui.action_files_new.set_sensitive(False) self.ui.action_files_remove.set_sensitive(False) self.ui.action_files_save.set_sensitive(False) self.model_applications.clear() def on_action_files_new_activate(self, action): """Show an application picker to add to the current AppFolder""" dialog = UIApplicationPicker(self.ui.win_main, self.model_applications.rows.keys()) if dialog.show() == Gtk.ResponseType.OK: if dialog.selected_applications: for application in dialog.selected_applications: # Get the selected application in the application picker # and add it to the current AppFolder application_info = dialog.model_applications.items[ application] self.model_applications.add_data(application_info) # Automatically select the newly added application filename = application_info.filename treeiter = self.model_applications.rows[filename] if treeiter: # Automatically select the last added application self.ui.treeview_applications.set_cursor( self.model_applications.get_path(treeiter)) # Enable folder content saving self.ui.action_files_save.set_sensitive(True) dialog.destroy() def on_treeview_selection_applications_changed(self, widget): """Set action sensitiveness on selection change""" selected_row = get_treeview_selected_row(self.ui.treeview_applications) self.ui.action_files_remove.set_sensitive(bool(selected_row)) def on_action_files_remove_activate(self, action): """Remove the selected application from the current AppFolder""" selected_row = get_treeview_selected_row(self.ui.treeview_applications) if selected_row: self.model_applications.remove(selected_row) # Enable folder content saving self.ui.action_files_save.set_sensitive(True) def on_action_files_save_activate(self, action): """Save the current AppFolder""" selected_row = get_treeview_selected_row(self.ui.treeview_folders) if selected_row: folder_name = self.model_folders.get_key(selected_row) folder_info = self.folders[folder_name] folder_info.set_applications(self.model_applications.rows.keys()) # Disable folder content saving self.ui.action_files_save.set_sensitive(False) def on_action_folders_remove_activate(self, action): """Remove the current AppFolder""" selected_row = get_treeview_selected_row(self.ui.treeview_folders) if selected_row: folder_name = self.model_folders.get_key(selected_row) if show_message_dialog(class_=UIMessageDialogNoYes, parent=self.ui.win_main, message_type=Gtk.MessageType.QUESTION, title=None, msg1=_('Remove the selected folder?'), msg2=_('Are you sure you want to remove ' 'the folder %s?') % folder_name, is_response_id=Gtk.ResponseType.YES): # Remove the AppFolder from settings folder_info = self.folders[folder_name] folder_info.remove() self.folders.pop(folder_name) # Remove the folder name from the folders list settings_folders = Gio.Settings.new(SCHEMA_FOLDERS) list_folders = settings_folders.get_strv('folder-children') list_folders.remove(folder_name) settings_folders.set_strv('folder-children', list_folders) # Clear the applications model self.model_applications.clear() # Remove the folder from the folders model self.model_folders.remove(selected_row) def on_action_folders_new_activate(self, action): """Creat a new AppFolder""" dialog = UICreateAppFolder(self.ui.win_main, self.model_folders.rows.keys()) if dialog.show(name='', title='') == Gtk.ResponseType.OK: # Create a new FolderInfo object and set its title folder_info = FolderInfo(dialog.folder_name) folder_info.set_title(dialog.folder_title) # Add the folder to the folders list settings_folders = Gio.Settings.new(SCHEMA_FOLDERS) list_folders = settings_folders.get_strv('folder-children') list_folders.append(dialog.folder_name) settings_folders.set_strv('folder-children', list_folders) # Reload folders list self.reload_folders() dialog.destroy() def on_action_folders_properties_activate(self, action): """Set the AppFolder properties""" selected_row = get_treeview_selected_row(self.ui.treeview_folders) if selected_row: name = self.model_folders.get_key(selected_row) title = self.model_folders.get_title(selected_row) dialog = UICreateAppFolder(self.ui.win_main, self.model_folders.rows.keys()) if dialog.show(name=name, title=title) == Gtk.ResponseType.OK: folder_name = dialog.folder_name folder_title = dialog.folder_title # Update the folder title folder_info = self.folders[folder_name] folder_info.name = folder_title folder_info.set_title(folder_title) # Reload the folders list and select the folder again self.reload_folders() self.ui.treeview_folders.set_cursor( self.model_folders.get_path_by_name(folder_name)) dialog.destroy() def on_action_preferences_toggled(self, widget): """Change a preference value""" for setting_name, action in self.dict_settings_map.items(): if action is widget: preferences.set(setting_name, widget.get_active()) def on_action_preferences_need_restart_toggled(self, widget): """Show the infobar to require application restart""" self.ui.label_infobar.set_label( _('The application must be restarted to apply the settings')) self.ui.infobar.show() def on_action_preferences_show_missing_files_toggled(self, widget): """Show and hide the missing desktop files""" self.on_treeview_folders_cursor_changed(self.ui.treeview_folders) def on_treeview_folders_row_activated(self, widget, path, column): """Show folder properties on activation""" self.ui.action_folders_properties.activate()